No description
Find a file
Oliver Nutter 322a272ab9
Prefer bun and bunx for JS tooling
Document JavaScript tooling preference to use bun and bunx instead of npm and npx in agent workflow notes.
Keep this guidance alongside other remembered execution conventions.

Co-Authored-By: opencode noreply@opencode.ai
2026-03-06 00:30:32 -06:00
src/frcmon Clarify non-obvious runtime intent with targeted comments 2026-03-05 23:18:15 -06:00
tests Cache YouTube downloads for media test-video 2026-03-05 22:35:21 -06:00
.gitignore Ignore local .env files 2026-03-05 17:48:06 -06:00
AGENTS.md Prefer bun and bunx for JS tooling 2026-03-06 00:30:32 -06:00
pyproject.toml Print help text on required-arg CLI usage errors 2026-03-05 19:24:25 -06:00
README.md Ensure test-video includes final frame in analysis 2026-03-05 19:51:22 -06:00
uv.lock Switch schedule scraping to HTML-only requests 2026-03-05 13:48:49 -06:00

frcmon

frcmon monitors FRC event schedules and livestream signals for one or more teams, then sends updates through a pluggable messaging sink.

Current messaging provider:

  • Telegram Bot API

Built-in runtime capabilities:

  • scrape event result schedules (practice, qualifications, playoffs)
  • detect schedule additions, removals, and reschedules
  • send 5-minute and match-start notifications for monitored teams
  • monitor a YouTube livestream with configurable vision, transcription, and summary models

Installation (uv)

uv sync

Optional local media analysis (OCR + speech transcription):

uv sync --extra media

System dependencies:

  • ffmpeg (for stream capture)
  • tesseract (for OCR)
  • no browser install is required for schedule scraping (uses direct HTML requests)

Quick start

uv run frcmon init --event-url https://frc-events.firstinspires.org/2026/MNDU --team 3883
uv run frcmon notifications telegram --token <BOT_TOKEN> --chat-id <CHAT_ID>
uv run frcmon notifications provider telegram
uv run frcmon serve

If you have a bot token but no chat ID yet:

uv run frcmon notifications telegram --token <BOT_TOKEN>
# send /start or any message to your bot first
uv run frcmon notifications telegram discover-chat

CLI

frcmon serve                     # run monitor loop
frcmon schedule refresh          # one-off scrape + state update
frcmon media test-video <URL>    # test media pipeline on arbitrary video
frcmon team add 3883             # add monitored team
frcmon team remove 3883          # remove monitored team
frcmon team list                 # list monitored teams
frcmon config show               # inspect current config
frcmon config set-event <URL>    # set event page
frcmon config model ...          # configure summary/vision/transcription models
frcmon notifications config      # configure pre-match/start notification behavior
frcmon notifications test        # send test message via configured provider
frcmon notifications provider ...    # choose provider (console/telegram)
frcmon notifications telegram ...     # set telegram credentials
frcmon notifications telegram discover-chat  # auto-discover chat_id from getUpdates

Use --all-teams as a global option to monitor every team for a command run:

uv run frcmon --all-teams serve
uv run frcmon --all-teams schedule refresh --notify

Adjust notification toggles/timing:

uv run frcmon notifications config --pre-match --match-start --pre-match-minutes 5
uv run frcmon notifications test

Configure test-match behavior and idle stream monitoring:

uv run frcmon notifications config --monitor-idle-stream --ignore-test-summaries --no-transcribe-test-matches --notify-test-match-team

Test the media pipeline on recorded video (useful when no live matches are active):

uv run frcmon media test-video "https://www.youtube.com/watch?v=NlrtRQ2btkQ" --duration-seconds 90 --max-segments 6
uv run frcmon media test-video "https://www.youtube.com/watch?v=NlrtRQ2btkQ" --offset-seconds 300 --duration-seconds 60

# end-to-end replay through live notification pipeline
uv run frcmon media test-video "https://www.youtube.com/watch?v=NlrtRQ2btkQ" --e2e

# send replay notifications to configured provider (Telegram/console)
uv run frcmon media test-video "https://www.youtube.com/watch?v=NlrtRQ2btkQ" --e2e --send

media test-video uses the configured vision screenshot interval (monitor.frame_interval_seconds). The default is defined by DEFAULT_VISION_FRAME_INTERVAL_SECONDS in src/frcmon/config.py. When --max-segments truncates analysis, frcmon still includes the final video frame segment.

frcmon serve emits info-level runtime logs, including newly scraped schedule entries and the next scheduled entry when a monitored match starts or ends.

When test matches are detected from livestream vision, frcmon can suppress summaries, disable transcription, and notify you if monitored teams appear in the detected test-match lineup.

Model backends

frcmon uses three media-model roles:

  • summary model (LLM for user-facing live summaries)
  • vision model (analyzes screenshots for scoreboard/context)
  • transcription model (speech-to-text for commentary)

Each role is swappable via frcmon config model with either local or OpenAI-compatible providers (cloud or self-hosted).

At runtime, frcmon loads ./.env automatically (without overriding already-exported variables), logs model backend key-env status on startup, and logs a one-time authentication success line after the first successful OpenAI-compatible request.

Examples:

# local defaults
uv run frcmon config model --target summary --provider local
uv run frcmon config model --target vision --provider local
uv run frcmon config model --target transcription --provider local --model base

# OpenAI-compatible endpoint (cloud or self-hosted)
uv run frcmon config model --target summary --provider openai-compatible --model gpt-4o-mini --base-url https://api.openai.com/v1 --api-key-env OPENAI_API_KEY
uv run frcmon config model --target vision --provider openai-compatible --model gpt-4o-mini --base-url https://api.openai.com/v1 --api-key-env OPENAI_API_KEY
uv run frcmon config model --target transcription --provider openai-compatible --model gpt-4o-mini-transcribe --base-url https://api.openai.com/v1 --api-key-env OPENAI_API_KEY

For OpenAI-compatible transcription, use a transcription-capable model (gpt-4o-mini-transcribe, gpt-4o-transcribe, or whisper-1). If a chat model is configured by mistake, frcmon warns and retries with gpt-4o-mini-transcribe.

Notes on livestream handling

  • frcmon resolves a direct stream URL with yt-dlp
  • it keeps a continuous ffmpeg process per selected webcast URL
  • periodic frame captures are OCR-processed for score changes
  • audio segments are transcribed (when whisper is installed)
  • notable commentary and lead changes are posted as messages

Development

uv sync --extra dev
uv run pytest

Test suite notes:

  • scraper tests use stored HTML fixtures in tests/fixtures/
  • network access is blocked during tests to keep runs deterministic and offline-safe