Turn a whole folder of videos into tidy bilingual subtitles — entirely on your own computer.
English | 简体中文
You have a semester of recorded lectures, a pile of conference talks, or interviews you keep meaning to go through — and none of them have subtitles, let alone translated ones.
Scripto exists for exactly that: pick a folder, hit Start, walk away. When you come back, every video has its subtitle files sitting right next to it — the original transcript and, if you want, a translation, all named to match:
os-lecture-03.mp4
os-lecture-03.en.srt ← transcript
os-lecture-03.zh.srt ← translation
No uploads, no queues, no subscriptions. Transcription runs on a Whisper model on your machine; translation runs on your local Ollama. Your audio and text never leave your computer — it works with the network cable unplugged.
- 🎓 Students with recorded courses — batch-convert a semester of lectures into searchable, reviewable subtitles and transcripts
- 🗣️ Anyone watching foreign-language talks — audio in one language, side-by-side bilingual subtitles out
- 🎙️ People who transcribe meetings & interviews — drop recordings in, get timestamped text back (srt/txt/vtt/json)
- 🔏 Anyone who cares about privacy — sensitive recordings that must not touch a cloud? There is no cloud here
- Double-click to open — a proper .app on macOS, a one-click launcher on Windows; a two-step wizard (language + model) gets you started, models download in-app
- Drag or paste any mix of files and folders, even from different drives; already-processed files are skipped automatically, so re-feeding your whole library is always safe
- Hit Start — the bottom bar always shows the current file, overall progress, and an ETA; stop anytime without losing finished work
- Flip on Translate and, while file #2 is transcribing, file #1 is already being translated in parallel
- The History page remembers every file: reopen it later, switch between language versions, translate the missing one with a click — and if you've deleted the output, it tells you honestly
The interface switches between English and 中文 live, follows your system's dark mode, and when anything is missing the built-in doctor tells you exactly what to install and which command fixes it — no programming required.
macOS
brew install ffmpeg uv # system deps: audio handling + env manager
brew install ollama # optional — only needed for translation
git clone https://github.com/TN019/scripto.git && cd scripto
bash launchers/macos/build_app.sh # builds dist/Scripto.appDrag dist/Scripto.app into Applications and double-click from now on — or just run uv run scripto.
Windows (PowerShell)
winget install ffmpeg
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# optional translation: winget install Ollama.Ollama
git clone https://github.com/TN019/scripto.git; cd scriptoFrom then on, double-click launchers\Scripto.bat (or Scripto.vbs for no console window).
Everything else installs itself on first launch — no Python wrangling.
The obvious way to batch videos is one at a time, start to finish: pull the audio → transcribe it → translate it → next file. The catch is that each step leans on a different part of your machine — pulling audio is CPU work (ffmpeg), transcribing is GPU / Neural-Engine work (Whisper), translating is a separate model (Ollama). Do them in a line and two of the three sit idle at any moment.
Scripto runs them like an assembly line instead. While the GPU transcribes file #1, the CPU is already pulling audio for file #2, and file #1's transcript is being translated at the same time:
flowchart LR
A[📁 Scan<br/>files & folders] --> B[🎵 Extract audio<br/>ffmpeg · CPU]
B -->|bounded queue| C[🎙️ Transcribe<br/>Whisper · GPU]
C -->|bounded queue| D[🌐 Translate<br/>Ollama · in parallel]
C --> E[📄 lecture.en.srt]
D --> F[📄 lecture.zh.srt]
E & F --> G[🕰️ History index]
The expensive part — the GPU transcribing — almost never waits. That's where the speed comes from. A few deliberate choices keep it fast and stable:
- Transcription stays one-at-a-time, on purpose. Running many Whisper jobs at once thrashes memory and ends up slower — so Scripto overlaps the other stages around one steady transcription stream instead of naively parallelizing everything.
- Models load once. The Whisper model is loaded a single time and reused for the whole batch; Ollama is kept warm between files — no paying the model-load cost per file.
- No wasted work. Files that already have subtitles are skipped instantly; a broken file is logged and stepped over, never stalling the queue.
- Long files don't balloon memory. A three-hour recording is split, transcribed in chunks, and stitched back with seamless timestamps.
- Right engine, automatically. mlx-whisper on Apple Silicon (Metal), faster-whisper on Windows (plain CPU works; NVIDIA GPUs accelerate automatically).
How well does the overlap actually pay off? On a 20-file batch with translation, the whole run finished just 4.6% above the theoretical floor — essentially the time transcription alone would take, with extraction and translation hidden underneath it. Every number below comes from reproducible scripts in benchmarks/:
| Metric | Target | Measured |
|---|---|---|
| Batch wall time (20 files + translation) | approach theoretical floor | only 4.6% above |
| Memory across a 20-file batch | flat | +0.1% |
| Translation batch first-try success | > 95% | 100% |
| UI with 500 files | responsive | < 50 ms/tick refresh |
| Stop → fully idle | < 5 s | ✅ |
Everything the GUI does, scriptable:
uv run scripto-cli run ~/Videos/course --model large-v3-turbo --translate --target zh
uv run scripto-cli doctor # environment check with fixes"Operation not permitted" on macOS — a system privacy permission is missing: System Settings → Privacy & Security → Files and Folders, grant access to your terminal or Scripto (or move files out of Desktop/Documents/Downloads). Scripto detects this case and says so explicitly.
iCloud files fail — the file hasn't been downloaded from the cloud yet: right-click → "Download Now" in Finder, then retry. Scripto identifies and reports this case.
Translation says Ollama is down — start it with ollama serve, then pull a model in Settings → Manage models (qwen3:8b recommended, qwen3:4b for low-RAM machines).
Files with existing subtitles get skipped — that's the default (no wasted work); enable Overwrite in Settings to regenerate.
uv sync && uv run pytest # fast suite, no model downloads
SCRIPTO_ENGINE_SMOKE=1 uv run pytest # + real engine smokes
SCRIPTO_OLLAMA_SMOKE=1 uv run pytest # + real translation smokeArchitecture and design decisions live in docs/PLAN.md. House rules: the core layer never imports UI, the interface only ever applies incremental updates, every subprocess has a timeout, and a failed translation never corrupts a subtitle file.
MIT © 2026 TN019