Skip to content

Commit ff428de

Browse files
Create Commentrix AI sports commentary archive
Publish the static project archive and local FastAPI MVP for generating timestamped sports commentary with Gemini, ElevenLabs, and FFmpeg.
0 parents  commit ff428de

33 files changed

Lines changed: 3149 additions & 0 deletions

‎.claude/settings.json‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"$schema": "https://json.schemastore.org/claude-code-settings.json",
3+
"attribution": {
4+
"commit": "",
5+
"pr": "",
6+
"sessionUrl": false
7+
}
8+
}

‎.github/workflows/checks.yml‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Checks
2+
3+
on:
4+
push:
5+
pull_request:
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
11+
jobs:
12+
python:
13+
runs-on: ubuntu-latest
14+
timeout-minutes: 10
15+
defaults:
16+
run:
17+
working-directory: mvp
18+
19+
steps:
20+
- name: Check out repository
21+
uses: actions/checkout@v4
22+
23+
- name: Set up Python
24+
uses: actions/setup-python@v5
25+
with:
26+
python-version: "3.11"
27+
cache: pip
28+
cache-dependency-path: |
29+
mvp/requirements.txt
30+
mvp/requirements-dev.txt
31+
32+
- name: Install dependencies
33+
run: python -m pip install -r requirements-dev.txt
34+
35+
- name: Reject AI attribution trailers
36+
run: |
37+
if git log --format='%B' | grep -Eiq 'Co-Authored-By:.*(Claude|Anthropic)|Claude-Session:'; then
38+
echo "Claude attribution found in reachable commit history."
39+
exit 1
40+
fi
41+
42+
- name: Lint
43+
run: python -m ruff check .
44+
45+
- name: Test
46+
run: python -m pytest
47+
48+
- name: Compile
49+
run: python -m compileall -q app main.py tests

‎.gitignore‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
.DS_Store
2+
._*
3+
4+
# Python
5+
__pycache__/
6+
*.py[cod]
7+
.pytest_cache/
8+
.ruff_cache/
9+
.mypy_cache/
10+
11+
# Virtual environments
12+
venv/
13+
.venv/
14+
env/
15+
16+
# Local configuration
17+
.env
18+
.env.*
19+
!.env.example
20+
21+
# Node and Cloudflare leftovers
22+
node_modules/
23+
.wrangler/
24+
npm-debug.log*
25+
26+
# Generated media and local inputs
27+
mvp/public/*.mp4
28+
mvp/public/*.mov
29+
mvp/public/*.mkv
30+
mvp/public/*.wav
31+
mvp/public/*.mp3
32+
mvp/public/*.srt
33+
34+
# Build artifacts
35+
dist/
36+
build/
37+
*.egg-info/

‎README.md‎

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
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.

‎assets/commentrix-logo.png‎

1020 KB
Loading

‎docs/favicon.png‎

1.17 MB
Loading

0 commit comments

Comments
 (0)