Sandbox
@shang-zhu/violin

Video translation skill for Claude Code

Violin turns a source video into a translated dub by chaining transcription, translation, text-to-speech, and video remuxing. The same pipeline is exposed as a Claude Code skill, a CLI, and a FastAPI web app, so you can use it from a terminal session or through an API.

1,058 stars156 forksPythonUpdated 14d ago
Who it's for

Builders who use Claude Code and want to turn videos into translated versions with aligned voice-over and subtitles.

What it delivers

You can translate a video into another language and get a dubbed output instead of redoing the workflow by hand.

What it does

Video transcription and translation

Extracts audio, runs transcription, then translates each segment into the target language.

Dubbed voice-over generation

Synthesizes a native-sounding voice-over and aligns it back to the video.

Optional subtitles

Writes an SRT file alongside the translated video when you want subtitles.

Claude Code skill install

Ships a skill that can be copied into `~/.claude/skills/` with the install command.

Pluggable model stack

Supports Together, OpenAI, and ElevenLabs across transcription, translation, chat, and TTS stages through YAML config.

In-video Q&A

Lets you ask questions about moments in the dubbed video using nearby subtitles and sampled frames.

Style profiles

Includes built-in style profiles like standard, kids, academic, casual, storyteller, and news.

How to get it

  1. 1Requires Python 3.10+ and ffmpeg on PATH.
    curl -LsSf https://astral.sh/uv/install.sh | sh   # install uv if you don't have it
    uv tool install violin                            # recommended — faster, isolated
    # or: pip install violin                          # if you'd rather install into your current Python env
    
    export TOGETHER_API_KEY=...                       # get one at https://api.together.ai (add to ~/.zshrc to persist)
  2. 21. CLI — translate one file
    violin lecture.mp4 lecture_zh.mp4 --language Chinese
  3. 32. Web app — full REST API + browser UI
    violin-api
    # → http://127.0.0.1:8000           (browser UI)
    # → http://127.0.0.1:8000/docs      (interactive API docs)
  4. 43. Claude Code skill — invoke from any Claude Code session
    violin --install-skill          # one-time: copies the skill into ~/.claude/skills/
    claude
    > please use the violin skill to translate path/to/video.mp4 into Chinese
  5. 5Run
    git clone https://github.com/shang-zhu/violin.git
    cd violin
    uv sync
    cp .env.example .env             # then fill in TOGETHER_API_KEY
    uv run main.py lecture.mp4 lecture_zh.mp4 --language Chinese
  6. 6To use the violin / violin-api commands globally while edits to your local source…
    uv tool uninstall violin     # if you've installed the PyPI version
    uv tool install --editable .

README

🎻 Violin

Open-source Video Translation Skill.

🌐 Live demo · 📝 Blog post · 📜 MIT License

Violin logo

Upload a video. Violin transcribes the speech, translates it, synthesizes a native-sounding voice-over in the target language, and remuxes it back into the video — fully aligned, with optional SRT subtitles.

Available as a CLI, a FastAPI web app, and a Claude Code skill.


✨ Features

  • 33 target languages with handpicked native-speaker voices for the 16 most-used ones (Cartesia Sonic 3 + ElevenLabs)
  • In-video Q&A — ask questions about any moment in the dubbed video; answers use nearby subtitles plus sampled frames
  • Natural-language voice picker — describe the voice you want, an LLM picks from the catalog
  • 6 style profiles (experimental) — standard / kids / academic / casual / storyteller / news
  • Pluggable stack — Together / OpenAI / ElevenLabs interchangeable for every stage, one YAML

🚀 Quick start

Try it without installing anything

The live demo runs at https://www.violin-ai.com — drop a short clip in, get a dubbed video out in a few minutes.

Run locally

Requires Python 3.10+ and ffmpeg on PATH.

curl -LsSf https://astral.sh/uv/install.sh | sh   # install uv if you don't have it
uv tool install violin                            # recommended — faster, isolated
# or: pip install violin                          # if you'd rather install into your current Python env

export TOGETHER_API_KEY=...                       # get one at https://api.together.ai (add to ~/.zshrc to persist)

Three ways to use it:

1. CLI — translate one file:

violin lecture.mp4 lecture_zh.mp4 --language Chinese

2. Web app — full REST API + browser UI:

violin-api
# → http://127.0.0.1:8000           (browser UI)
# → http://127.0.0.1:8000/docs      (interactive API docs)

3. Claude Code skill — invoke from any Claude Code session:

violin --install-skill          # one-time: copies the skill into ~/.claude/skills/
claude
> please use the violin skill to translate path/to/video.mp4 into Chinese
Run from source (for hacking on the pipeline)
git clone https://github.com/shang-zhu/violin.git
cd violin
uv sync
cp .env.example .env             # then fill in TOGETHER_API_KEY
uv run main.py lecture.mp4 lecture_zh.mp4 --language Chinese

To use the violin / violin-api commands globally while edits to your local source reflect immediately, install editable:

uv tool uninstall violin     # if you've installed the PyPI version
uv tool install --editable .

After this, violin / violin-api run from your local checkout — edit any file and the next invocation picks it up; no rebuild needed. To switch back to PyPI: uv tool uninstall violin && uv tool install violin.


📝 To Do List

  • [-] support voice cloning.
  • [-] lip sync generation.

🎬 How Violin works

Video
  │
  ├─ ffmpeg ─────────────────────► Extract audio (16 kHz WAV)
  │
  ├─ Whisper Large v3 ────────────► Word-level timestamps → sentence segments
  │
  ├─ LLM (DeepSeek V4 Pro by default) ──► Translate each segment, respecting style profile
  │
  ├─ TTS (Cartesia Sonic 3 by default) ─► Synthesize dubbed audio per segment
  │
  └─ ffmpeg ─────────────────────► Speed-align video to dubbed audio,
                                    concat with freeze-frame fallback,
                                    single-pass AAC encode the audio track,
                                    write output mp4 + optional SRT

⚙️ Configuration

Override any default by writing your own YAML and passing it with --config my.yaml — only the keys you want to change need to appear; values deep-merge with the built-in defaults.

Switch providers

# config/default.yaml — pick the stack you want
models:
  transcription:
    provider: together                  # together | openai
    model: openai/whisper-large-v3      # together → openai/whisper-large-v3 | openai → whisper-1
  translation:
    provider: together                       # together | openai
    model: deepseek-ai/DeepSeek-V4-Pro-0813  # together → deepseek-ai/DeepSeek-V4-Pro-0813 | openai → gpt-5.5
  tts:
    provider: together                       # together | elevenlabs | openai
    model: cartesia/sonic-3                  # together → cartesia/sonic-3 | elevenlabs → eleven_v3 | openai → tts-1-hd
  chat:
    provider: together                       # together | openai — must be vision-capable
    model: zai-org/GLM-5.3-Flash             # together → zai-org/GLM-5.3-Flash | openai → gpt-5.5

The chat stage is a reasoning model by default, and it spends part of chat.max_tokens on thinking before it answers. If you point it at a different model, keep that budget generous (the shipped default is 4096) — too tight and the API returns an empty answer with finish_reason: length.

Production overrides

A starter config/prod.yaml is included for public deployments. It adds upload limits, serializes jobs, and caps ffmpeg concurrency. The included Dockerfile + docker-compose.yml + Caddyfile are how the live demo is hosted — docker compose up -d --build after filling .env is enough to put a copy of Violin behind auto-HTTPS on any Docker host.

Environment variables

VariableWhen requiredDescription
TOGETHER_API_KEYRecommended — covers every stage with the default configTogether AI API key
OPENAI_API_KEYAny stage uses provider: openaiCovers whisper-1, GPT models, and tts-1
ELEVENLABS_API_KEYTTS uses provider: elevenlabsElevenLabs API key
CORS_ORIGINSOptionalComma-separated allowed origins (default: *)

You only need keys for the providers you actually pick. Pure-OpenAI deployments (all stages on openai) work too — OPENAI_API_KEY alone is enough. Same idea for ElevenLabs.


🎭 Style profiles

Six built-in profiles tune both the translation LLM prompt and the TTS delivery. Use --style <name> on the CLI or pass style in API requests.

StyleToneTTS speedEmotion
standardFaithful translation, natural voice1.0×
kidsRewritten for a 7-year-old, plain language1.0×excited
academicFormal register, preserves jargon and honorifics0.95×calm
casualSpoken slang, contractions, friendly1.1×content
storytellerVivid, dramatic narration0.9×enthusiastic
newsConcise, declarative, broadcast-style1.0×neutral

Add your own by editing prompts/styles.yaml.

See all available styles: violin --style list.


💻 CLI usage

Examples use the PyPI-installed violin command. If you're running from a git checkout, substitute uv run main.py for violin (and uv run run_api.py for violin-api).

# Basic
violin lecture.mp4 lecture_es.mp4 --language Spanish

# Pick a style
violin talk.mp4 talk_zh.mp4 --language Chinese --style kids

# Pick a specific voice
violin lecture.mp4 lecture_fr.mp4 --language French --voice "french narrator man"

# Skip SRT
violin lecture.mp4 lecture_ja.mp4 --language Japanese --no-subtitles

# Full replacement (no original audio underneath)
violin lecture.mp4 lecture_ko.mp4 --language Korean --no-voiceover

# Custom config (e.g. switch to OpenAI/ElevenLabs)
violin lecture.mp4 lecture_it.mp4 --language Italian --config config/other_api.yaml

CLI flags

FlagDefaultDescription
--language / -l(required)Target language name (e.g. Spanish, Japanese)
--voice / -vautoTTS voice. Defaults to the primary native voice for the target language
--source-languageauto-detectSource language hint for translation
--no-subtitlesoffSkip SRT generation
--voiceover / --no-voiceovervoiceover onKeep original audio underneath the dub, or full replacement
--style / -sstandardStyle profile name. Use --style list to see all
--config / -cconfig/default.yamlPath to a YAML override file
--timings-outoffWrite per-step wall-clock timings + cost as JSON

🛰️ Web app & REST API

violin-api                              # default dev mode
violin-api --host 0.0.0.0 --port 8080   # bind everywhere
violin-api --config config/prod.yaml    # production overrides (requires a git checkout for config/prod.yaml)

Core flow: POST /jobs to start, GET /jobs/{id} to poll, GET /jobs/{id}/video and /srt to download, POST /jobs/{id}/chat for in-video Q&A. Full list with request/response schemas at /docs.

Example

# Submit
JOB=$(curl -s -X POST http://localhost:8000/jobs \
  -F "file=@lecture.mp4" \
  -F "language=Spanish" \
  -F "style=academic" | jq -r .id)

# Poll
curl -s http://localhost:8000/jobs/$JOB | jq '{status, progress}'

# Download
curl -OJ http://localhost:8000/jobs/$JOB/video
curl -OJ http://localhost:8000/jobs/$JOB/srt

Job data lives under jobs/{id}/. Set api.job_ttl_hours to auto-delete jobs older than N hours (default 0 = disabled; config/prod.yaml uses 24h for the public demo).


🌍 Supported languages

Violin supports 33 target languages. The 16 below ship with handpicked native-speaker voices for each provider; the rest fall back to the English voice catalog (which is multilingual under both Cartesia Sonic 3 and ElevenLabs eleven_v3).

Ordered by native-speaker population.

LanguageCartesia native voice (M / F)ElevenLabs native voice (M / F)
Chinesechinese commercial man / chinese female conversationalLin / Lingyue
Spanishspanish narrator man / spanish narrator ladyCarlos / Valeria
Englishtutorial man / helpful womanAdam / Sarah
Hindihindi narrator man / hindi narrator womanYatin / Madhusmita
Arabicmiddle eastern womanFaris / Haneen
Portuguesefriendly brazilian man / pleasant brazilian ladyMedeiros / Luna
Russianrussian narrator man 1 / russian narrator womanIvo / Xenia
Japanesejapanese male conversational / japanese woman conversationalShohei / Maiko
Turkishturkish narrator man / turkish calm manSinan / Aura
Germangerman reporter man / german conversational womanDaniel / Sina
Koreankorean narrator man / korean calm womanJoon-ho / Soo
Frenchfrench narrator man / french narrator ladyLior / Virginie
Italianitalian narrator man / italian narrator womanRaffaele / Chiara
Polishpolish confident man / polish narrator womanGregor / Jola
Dutchdutch confident man / dutch manRonald / Jolanda
Swedishswedish narrator man / swedish calm ladyAndreas / Louise

The 17 fallback languages (using the English voice catalog), also ordered by native speakers: Vietnamese, Tamil, Indonesian, Malay, Ukrainian, Romanian, Thai, Greek, Hungarian, Catalan, Czech, Bulgarian, Danish, Slovak, Croatian, Finnish, Norwegian.


🤝 Contributing

PRs welcome. Got questions or hit a bug? Email heyviolinai@gmail.com or open an issue.


⚠️ Disclaimer

This is a personal open-source project, not a Together AI product. Users are responsible for ensuring they have the right to download and translate any content they process. Designed for Creative Commons, public domain, your own recordings, and other content you have permission to use.


📜 License

MIT — use it freely, including commercially.


🙏 Acknowledgements

Built on top of Together AI, Whisper, Cartesia Sonic 3, ElevenLabs, FastAPI, and ffmpeg.

Files in the repo

Repository payload20 top-level entries
  • .claude
  • api
  • assets
  • config
  • pipeline
  • prompts
  • .dockerignore
  • .env.example
  • .gitignore
  • .python-version
  • Caddyfile
  • CHANGELOG.md
  • docker-compose.yml
  • Dockerfile
  • LICENSE
  • main.py
  • pyproject.toml
  • README.md
  • run_api.py
  • uv.lock

Discussion (0)

Ask about usage, or say what you built with it

Sign in to join the discussion.

No comments yet. Be the first to say what this is good for.

More skills

Open-source AI job search: scan job portals, evaluate listings into a structured A-H report with a global 1-5 score, tailor your CV, track applications — runs locally in your AI coding CLI (Claude Code, Codex, OpenCode, Antigravity…)

71k
ayghri/
i-have-adhd

A skill to stop your coding agent from burying the answer. ADHD-friendly output.

38k
mvanhorn/
last30days-skill

AI agent skill that researches any topic across Reddit, X, YouTube, HN, Polymarket, and the web - then synthesizes a grounded summary

62k
Nanako0129/
sepia

De-AI writing skill for any Agent Skills-compatible agent (77+ via the Skills CLI), with native plugins for Claude Code, Codex, Grok Build, and Antigravity. Narrative-architecture repair for fiction, venue-matched rules for professional prose. Based on StoryScope (arXiv:2604.03136).

2.5k
Imbad0202/
academic-research-skills

Academic Research Skills for Claude Code: research → write → review → revise → finalize

48k

Agent skill that removes signs of AI-generated writing from text

46k