|
| 1 | +<div align="center"> |
| 2 | + <img src="assets/commentrix-logo.png" alt="Commentrix logo" width="160"> |
| 3 | + <h1>Commentrix</h1> |
| 4 | + <p>AI-assisted play-by-play commentary for sports video.</p> |
| 5 | + <p> |
| 6 | + <a href="https://commentrixai.com/">Live archive</a> · |
| 7 | + <a href="mvp/README.md">MVP guide</a> |
| 8 | + </p> |
| 9 | +</div> |
| 10 | + |
| 11 | +## About |
| 12 | + |
| 13 | +Commentrix explored an automated broadcast pipeline that samples sports footage, asks a multimodal model to identify noteworthy action, generates concise timestamped commentary, and turns those lines into a synchronized voice track and subtitle file. |
| 14 | + |
| 15 | +The project has been sunset and is published as a polished public snapshot. The [live website](https://commentrixai.com/) remains available as an informational archive; it does not run the Python MVP or accept new customers, pilots, or support requests. |
| 16 | + |
| 17 | +## Repository layout |
| 18 | + |
| 19 | +```text |
| 20 | +commentrix/ |
| 21 | +├── assets/ Archived brand assets |
| 22 | +├── docs/ Static Cloudflare Pages website |
| 23 | +├── mvp/ |
| 24 | +│ ├── app/ Processing, model, audio, and orchestration modules |
| 25 | +│ ├── public/ Local input and generated media directory |
| 26 | +│ ├── static/ MVP browser assets |
| 27 | +│ ├── templates/ MVP HTML shell |
| 28 | +│ ├── tests/ Backend test suite |
| 29 | +│ └── main.py FastAPI entry point |
| 30 | +└── wrangler.jsonc Cloudflare Pages configuration |
| 31 | +``` |
| 32 | + |
| 33 | +The two surfaces are deliberately separate: |
| 34 | + |
| 35 | +- `docs/` is a dependency-free static archive deployed to Cloudflare Pages. |
| 36 | +- `mvp/` is a local, single-operator FastAPI application retained as a working technical reference. |
| 37 | + |
| 38 | +## Architecture |
| 39 | + |
| 40 | +```text |
| 41 | +Local MP4 |
| 42 | + │ |
| 43 | + ▼ |
| 44 | +OpenCV frame sampling ──► Gemini commentary generation |
| 45 | + │ |
| 46 | + ├──► WebSocket updates in the browser |
| 47 | + │ |
| 48 | + ▼ |
| 49 | + ElevenLabs speech |
| 50 | + │ |
| 51 | + ▼ |
| 52 | + pydub timeline assembly |
| 53 | + │ |
| 54 | + ▼ |
| 55 | + FFmpeg MP4 + SRT |
| 56 | +``` |
| 57 | + |
| 58 | +Each video segment is sampled at approximately one frame per second. Gemini returns lines in a `[frame] commentary` format. When text-to-speech is configured, ElevenLabs renders those lines, and the MVP places them on the source timeline before writing `output.mp4` and `output.srt`. |
| 59 | + |
| 60 | +## Quick start |
| 61 | + |
| 62 | +### Static website |
| 63 | + |
| 64 | +The website has no build step: |
| 65 | + |
| 66 | +```bash |
| 67 | +python -m http.server 8080 --directory docs |
| 68 | +``` |
| 69 | + |
| 70 | +Open `http://localhost:8080`. |
| 71 | + |
| 72 | +### Local MVP |
| 73 | + |
| 74 | +Requirements: |
| 75 | + |
| 76 | +- Python 3.11 or newer |
| 77 | +- [FFmpeg](https://ffmpeg.org/) available on `PATH` |
| 78 | +- A Gemini API key |
| 79 | +- An ElevenLabs API key if voice output is required |
| 80 | + |
| 81 | +```bash |
| 82 | +cd mvp |
| 83 | +python -m venv .venv |
| 84 | +source .venv/bin/activate |
| 85 | +python -m pip install -r requirements.txt |
| 86 | +cp .env.example .env |
| 87 | +``` |
| 88 | + |
| 89 | +Add credentials to `.env`, place an input video at `mvp/public/input.mp4`, then run: |
| 90 | + |
| 91 | +```bash |
| 92 | +python main.py |
| 93 | +``` |
| 94 | + |
| 95 | +Open `http://127.0.0.1:8000`. API health is available at `http://127.0.0.1:8000/health`. |
| 96 | + |
| 97 | +## Environment variables |
| 98 | + |
| 99 | +All paths may be absolute or relative to `mvp/`. |
| 100 | + |
| 101 | +| Variable | Required | Default | Purpose | |
| 102 | +| --- | --- | --- | --- | |
| 103 | +| `GEMINI_API_KEY` | Yes | — | Gemini credential. `GOOGLE_API_KEY` is accepted as an alias. | |
| 104 | +| `GEMINI_MODEL` | No | `gemini-2.5-pro` | Gemini model used for frame analysis. | |
| 105 | +| `ELEVENLABS_API_KEY` | For voice | — | ElevenLabs credential. Without it, TTS is disabled. | |
| 106 | +| `ELEVENLABS_VOICE_ID` | No | Archived project voice | Voice used for narration. | |
| 107 | +| `ELEVENLABS_MODEL` | No | `eleven_multilingual_v2` | ElevenLabs synthesis model. | |
| 108 | +| `ELEVENLABS_OUTPUT_FORMAT` | No | `mp3_44100_128` | Requested voice-audio format. | |
| 109 | +| `ELEVENLABS_MAX_CONCURRENT` | No | `3` | Positive request-concurrency limit. | |
| 110 | +| `SEGMENT_DURATION` | No | `30` | Positive segment length in seconds. | |
| 111 | +| `VIDEO_PATH` | No | `public/input.mp4` | Source video. | |
| 112 | +| `OUTPUT_FILE` | No | `public/output.mp4` | Generated video path. | |
| 113 | +| `SUBTITLE_FILE` | No | `public/output.srt` | Generated subtitle path. | |
| 114 | +| `TTS_ENABLED` | No | `true` | Accepts `true/false`, `yes/no`, `on/off`, or `1/0`. | |
| 115 | +| `PORT` | No | `8000` | Port used by `python main.py`. | |
| 116 | + |
| 117 | +## Development commands |
| 118 | + |
| 119 | +Install the development tools once: |
| 120 | + |
| 121 | +```bash |
| 122 | +cd mvp |
| 123 | +python -m pip install -r requirements-dev.txt |
| 124 | +``` |
| 125 | + |
| 126 | +Then run: |
| 127 | + |
| 128 | +```bash |
| 129 | +python -m ruff check . |
| 130 | +python -m pytest |
| 131 | +python -m compileall -q app main.py |
| 132 | +``` |
| 133 | + |
| 134 | +There is no JavaScript build pipeline. The browser code is plain HTML, CSS, and JavaScript by design. |
| 135 | + |
| 136 | +## Deployment |
| 137 | + |
| 138 | +Cloudflare Pages should serve only `docs/`: |
| 139 | + |
| 140 | +| Setting | Value | |
| 141 | +| --- | --- | |
| 142 | +| Project name | `commentrix` | |
| 143 | +| Production branch | `main` | |
| 144 | +| Build command | Leave blank | |
| 145 | +| Build output directory | `docs` | |
| 146 | +| Custom domain | `commentrixai.com` | |
| 147 | + |
| 148 | +The checked-in `wrangler.jsonc` contains the same output-directory configuration. The MVP is not deployed by this repository configuration. |
| 149 | + |
| 150 | +## Operational notes |
| 151 | + |
| 152 | +- The MVP is intended for trusted local use by one operator. It has no authentication, upload boundary, persistent job queue, rate limiting, or multi-user output isolation. |
| 153 | +- Sampled video frames are sent to Gemini. Generated commentary is sent to ElevenLabs when TTS is enabled. Review those providers' current data and billing terms before using private footage. |
| 154 | +- The generated MP4 uses the synthesized commentary track in place of the source audio; the source video stream is copied without re-encoding. |
| 155 | +- If TTS is disabled, generated text still appears in the browser, but the final MP4 and SRT assembly step is skipped. |
| 156 | +- API calls already running in worker threads may finish after a browser job is stopped. |
| 157 | +- `.env` files, local input media, generated outputs, virtual environments, caches, and Cloudflare local state are intentionally ignored by Git. |
| 158 | + |
| 159 | +## License |
| 160 | + |
| 161 | +No open-source license is included. The code and assets are published for archival and reference purposes; obtain permission from the repository owner before reuse or redistribution. |
0 commit comments