Automated pipeline that takes YouTube music video URLs and produces timestamped SRT subtitle files in English and multiple target languages. Includes a browser-based review tool so non-technical team members can validate and correct output at each stage.
| Stage | What happens |
|---|---|
| 1 — Audio extraction | Downloads audio from YouTube as MP3 via yt-dlp |
| 2 — Lyrics lookup | Fetches synced or plain lyrics (lrclib → Genius → Musixmatch waterfall) |
| 3 — English SRT | Converts synced timestamps to SRT format |
| 3b — Forced alignment | (pending) Aligns plain lyrics to audio using Aeneas |
| 4 — ASR fallback | (pending) Vocal separation + speech recognition via Demucs + Deepgram |
| Human review (gate) | Required checkpoint. Lyrics and timestamps must be approved (or fixed and approved) in the browser review tool — translation cannot start on a song until both are cleared |
| 5 — Translation | (pending) Submitted via BLEND, which integrates with EasyTranslate for LLM translation + quality estimation (QE); lines QE flags for review are assigned to a human post-editor (PE) on our side |
Python 3.11+ — python.org/downloads
FFmpeg — required by yt-dlp for audio conversion
- Windows:
winget install ffmpegor download from ffmpeg.org and add to PATH - macOS:
brew install ffmpeg - Linux:
sudo apt install ffmpeg(Ubuntu/Debian) orsudo dnf install ffmpeg(Fedora)
# 1. Clone the repo
git clone <repo-url>
cd <repo-folder>
# 2. Create and activate a virtual environment (recommended)
python -m venv .venv
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate
# 3. Install dependencies
pip install -r requirements.txt
# 4. Configure API keys
cp .env.example .env
# Open .env and fill in the keys you have (all are optional — see notes below)| Key | Where to get it | Required? |
|---|---|---|
GENIUS_API_KEY |
genius.com/api-clients — free | Optional (plain lyrics fallback) |
MUSIXMATCH_API_KEY |
musixmatch.com — paid plan | Optional (synced lyrics) |
DEEPGRAM_API_KEY |
deepgram.com | Optional (ASR stage, not yet built) |
BLEND_API_KEY |
internal — BLEND platform | Optional (translation stage, not yet built) |
lrclib.net is always tried first and needs no key.
Create a plain text file with one YouTube URL per line (lines starting with # are ignored):
https://www.youtube.com/watch?v=...
https://www.youtube.com/watch?v=...
# this line is a comment
# Run all implemented stages (1–3)
python main.py urls.txt
# Run a single stage only
python main.py urls.txt --stage 1 # audio only
python main.py urls.txt --stage 2 # lyrics only (requires stage 1 output)
python main.py urls.txt --stage 3 # SRT only (requires stage 2 output)
python main.py urls.txt --stage 5 # review-gate check — reports which songs are cleared for translation
# Verbose logging
python main.py urls.txt --verboseOutput is written to output/Artist - Song Title/:
output/
└── Lykke Li - I Follow Rivers/
├── audio.mp3
├── song.json ← full metadata + pipeline state + review status
└── en.srt ← English subtitles
Use share.py to expose the review tool publicly via ngrok. Reviewers open a link in their browser — nothing to install on their end.
One-time ngrok setup (you only):
- Install ngrok
- Windows:
winget install ngrok - Mac:
brew install ngrok - Linux:
snap install ngrok
- Windows:
- Sign up free at ngrok.com and copy your authtoken
- Run once:
ngrok config add-authtoken <your-token>
Every time you want to share:
python share.pyOutput:
------------------------------------------------
Review tool is LIVE - share this link:
------------------------------------------------
https://abc123.ngrok-free.app
Local (your machine only): http://localhost:8080
------------------------------------------------
Press Ctrl+C to stop sharing.
Paste that URL into Slack/email. Your machine needs to stay on while reviewers are working. Press Ctrl+C to stop.
A local web app for validating and correcting pipeline output. Works in any browser.
python review.py serve
# Opens at http://localhost:8080Share the Network URL printed at startup with colleagues on the same Wi-Fi.
For remote access: ngrok http 8080
Overview of all processed songs with colour-coded review status per stage.
Edit the lyrics text, then Approve or Reject. Rejecting flags the current source so the next pipeline run automatically tries the next one in the waterfall.
Audio player + editable subtitle blocks.
- Full song / One segment toggle — Full song plays straight through; One segment plays only the clicked line then stops
- Play / Pause button — always visible
- ▶ button (audio paused) — seeks to that line and plays
- ● button (audio playing) — snaps that line's start timestamp and the previous line's end timestamp to the current playback position (live retiming)
- Save Changes → writes back to
en.srt
python review.py status # show review queue
python review.py approve "Lykke Li - I Follow Rivers" --stage 2
python review.py reject "Lykke Li - I Follow Rivers" --stage 2 --reason "wrong song"| Component | Library |
|---|---|
| Audio download | yt-dlp |
| Async HTTP | httpx |
| Lyrics (synced) | lrclib.net (no key needed) |
| Lyrics (plain) | lyricsgenius |
| Data models | Pydantic v2 |
| Config | pydantic-settings |
| Review web server | FastAPI + Jinja2 + uvicorn |
- Never commit
.env— it contains real API keys - Never commit the
output/folder — it contains client audio and lyrics - Test with at least one synced and one plain-lyrics song before opening a PR