Swiss Subtitle MVP is a local CLI pipeline for turning Swiss German video audio into subtitle files with:
- raw ASR subtitles
- Zurich-style Swiss German normalized subtitles
- JSON artifacts for further analysis
The current focus is offline subtitle generation for Swiss German content. Live translation is out of scope for this MVP.
The repository includes a 120-second preview rendered from a real run:
- Dual-subtitle video: assets/preview/preview_120s_dual_subs.mp4
- Dual-subtitle GIF preview: assets/preview/preview_120s_dual_preview.gif
- Swiss German SRT: assets/preview/zurich_preview_120s.srt
- Hochdeutsch SRT: assets/preview/hochdeutsch_preview_120s.srt
- Combined dual-subtitle SRT: assets/preview/zurich_hochdeutsch_preview_120s.srt
Click the GIF to open the full MP4 preview with Swiss German and Hochdeutsch subtitles.
Example subtitle pair:
Swiss German: Das macht sich so einiges in de junge, dassi guet hie nöd bi.
Hochdeutsch: Das macht sich so einiges in den jungen Jahren, dass ich hier nicht gut dabei bin.
- Download audio from a YouTube video with
yt-dlp - Extract a mono 16 kHz WAV with
ffmpeg - Transcribe Swiss German speech locally with
faster-whisper - Normalize each subtitle segment into readable Zurich-style Swiss German with DeepSeek
- Export
.srtand.jsonoutputs underruns/<job_id>/
Time alignment always comes from the ASR step. The LLM only rewrites subtitle text.
- Python 3.10+
ffmpegyt-dlp- A DeepSeek API key
Recommended:
- Python 3.11
- A machine that can run
faster-whisperefficiently
python3.11 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
pip install yt-dlpDo not commit API keys.
- Copy the example file:
cp .env.example .env- Put your key into
.env:
DEEPSEEK_API_KEY=your_deepseek_api_key_here.env is ignored by git, and the CLI loads it automatically.
Run the full pipeline:
python3 main.py run "https://www.youtube.com/watch?v=_qJdJTekb64"If YouTube blocks the request, retry with browser cookies:
python3 main.py run "https://www.youtube.com/watch?v=_qJdJTekb64" --cookies-from-browser chromeNormalize an existing run again:
python3 main.py resume-normalize runs/<job_id> --url "https://www.youtube.com/watch?v=_qJdJTekb64"Each run writes files under runs/<job_id>/:
source.*audio.wavraw_segments.jsonnormalized_segments.jsonraw_subtitle.srtzurich_subtitle.srtjob.json
- Swiss German accuracy is currently limited more by ASR quality than by token budget.
- Normalization improves readability, but it cannot fully recover meaning from a badly transcribed segment.
- The current implementation is optimized for local batch processing, not low-latency streaming.
.envand runtimeruns/outputs are excluded from git.- The committed preview asset is stored under
assets/preview/so the repository can show a polished example without leaking local runtime data.
