Skip to main content

Voiceover Pipeline

Standalone CLI для генерации озвучки + Whisper timing из Markdown-сценариев.

Четыре TTS-провайдера: Polza GPT Audio, Polza TTS, OpenRouter TTS, Qwen3-TTS (GPU). Плюс локальный OmniVoice (auto / voice-bank preset / clone / design) и формат gemini-dialogue для двухспикерного подкаста через OpenRouter Gemini TTS (двухголосый результат перерабатывается — см. статус ниже). Whisper CPU small — точные тайминги для Remotion-анимаций и субтитров. Agent-grade JSON-контракт: --json, semantic exit codes, manifest.json. Сценарии могут быть plain Markdown или Markdown с frontmatter metadata для provider/model/voice.

Install

Console scripts: voiceover and voiceover-pipeline (both work).

Manager Base + Whisper + Qwen GPU + All extras
uvx (no install) uvx voiceover-pipeline doctor uvx --from "voiceover-pipeline[timing-whisper]" voiceover-pipeline generate --with-timings ... uvx --from "voiceover-pipeline[voiceover-qwen]" voiceover-pipeline generate --provider qwen-local ... uvx --from "voiceover-pipeline[timing-whisper,voiceover-qwen,cuda]" ...
pipx pipx install voiceover-pipeline pipx install "voiceover-pipeline[timing-whisper]" pipx install "voiceover-pipeline[voiceover-qwen]" pipx install "voiceover-pipeline[timing-whisper,voiceover-qwen,cuda]"
pip pip install voiceover-pipeline pip install "voiceover-pipeline[timing-whisper]" pip install "voiceover-pipeline[voiceover-qwen]" pip install "voiceover-pipeline[timing-whisper,voiceover-qwen,cuda]"
uv pip uv pip install voiceover-pipeline uv pip install "voiceover-pipeline[timing-whisper]" uv pip install "voiceover-pipeline[voiceover-qwen]" uv pip install "voiceover-pipeline[timing-whisper,voiceover-qwen,cuda]"

From source

git clone https://github.com/VladimirMonin/voiceover-pipeline
cd voiceover-pipeline
uv sync --group dev --extra timing-whisper
uv run voiceover doctor

First run

  • .env is searched in CWD and upwards through parent directories.
  • Whisper model (~486 MB) auto-downloads from HuggingFace on first --with-timings. Subsequent runs use cache.
  • Qwen-local requires NVIDIA GPU + CUDA drivers (~4 GB VRAM).

API Keys

Create .env in your working directory (CWD or any parent directory — searched upwards):

POLZA_API_KEY=pza_...
OPENROUTER_API_KEY=sk-or-v1-...

Never commit .env.

Golden Command

voiceover generate `
  --provider polza-chat-audio `
  --model "openai/gpt-audio-mini" `
  --script "script.md" `
  --run-id "prod" `
  --json `
  --resume

Recommended production flow: generate paid audio first, then run voiceover timings as a separate step. If you still use --with-timings, Whisper dependencies are checked before the first paid TTS request.

Metadata script

---
format: voiceover
provider: polza-tts
model: openai/gpt-4o-mini-tts
voice: ash
max_chunk_chars: 2000
---

Первый фрагмент озвучки.

******

Второй фрагмент озвучки.

Для двухголосых podcasts доступен provider-neutral format: dialogue с двумя спикерами, voice map и inline tags вроде [laughs], [serious], [short pause]. gemini-dialogue остаётся compatibility alias; state и manifests пишут канонический dialogue.

OpenRouter получает один документированный top-level voice на каждую реплику; multi_speaker_voice_config не используется. OmniVoice dialogue использует один admitted runtime и отдельный bank profile на turn. Offline contract проверен, но audible PASS OpenRouter и OmniVoice по-прежнему требует human listening: не заявляй слышимое различие голосов или выпуск 0.6.0 без двух PASS.

Agent-first podcast (два спикера)

# 1. Валидация без платного запроса
voiceover validate --script "podcast.md" --format dialogue --agent --json

# 2. Проверка окружения (не читая .env)
voiceover doctor --provider openrouter-tts --json

# 3. Генерация (после явного одобрения платного вызова)
voiceover generate --script "podcast.md" --run-id "podcast-prod" --json --resume

Provider/model/каст/направление берутся из frontmatter скрипта. Resume защищён synthesis_identity: смена голоса/profile/fingerprint, модели, текста, порядка, пауз или style/trim policy отклоняется (exit 30) до provider request; orphan dialogue MP3 не восстанавливается без trusted state.

Gemini prompting quick guide

Gemini TTS works best as a directed voice performer, not as plain text-to-speech. Keep instructions separate from spoken transcript: AUDIO PROFILE, SCENE, PERFORMANCE, CONTEXT, then #### TRANSCRIPT.

Synthesize speech for the performance defined below.
The profile, scene, performance notes, and context are direction only.
Do NOT speak them.
Speak ONLY the lines under #### TRANSCRIPT.

### PERFORMANCE
Style: Warm, thoughtful, conversational, emotionally alive.
Pace: Natural podcast pace with small pauses after important ideas.
Accent: Natural Russian speech.

#### TRANSCRIPT
[thoughtfully] Сегодня разберём Gemini TTS, [short pause] и почему хороший голос начинается с режиссуры.

Use English service directions and English audio tags; keep the transcript in the target language. Use PERFORMANCE for global emotion and inline tags such as [thoughtfully], [sighs], [laughs], [gasp], [medium pause] for local delivery changes. For long podcasts, prefer semantic chunks of roughly 250-450 Russian words, or 180-350 words for emotional material.

Do not paste the whole prompt skeleton into the script body. In this project, put direction into style_prompt, vibe, and speaker profile; keep body text as spoken transcript only. See the full guides: docs/skills/voiceover-pipeline/docs/11-gemini-prompting.md and docs/skills/voiceover-pipeline/docs/12-gemini-prompting-templates.md.

Результат (JSON stdout):

{"status": "success", "provider": "polza-chat-audio", "run_id": "prod",
 "duration_ms": 25520, "segment_count": 8, "cost": {"total": 0.0146, "currency": "RUB"}}

Что на выходе

out/<run-id>/
├── manifest.json                          ← entry-point для агентов
├── run_state.json                         ← resumable state after each chunk
├── generation.log                         ← human-readable generation log
├── <run-id>-voiceover-<model>.mp3         ← полный MP3
├── <run-id>-voiceover-<model>.json        ← run-манифест
├── <run-id>.timings.json                  ← Whisper-сегменты (ms)
├── <run-id>.srt                           ← субтитры SRT
└── chunks/
    ├── chunk_01.mp3 ... chunk_NN.mp3
    └── chunks.json

Команды

Команда Зачем
doctor Проверить окружение
validate --script X Проверить сценарий
list providers/voices/timing-models Доступные модели
split --script X Чанки сценария
generate Генерация аудио с resume/retry/state/log
timings --audio X Тайминги из готового MP3
status --run-id X Статус partial/resumable run
concat --run-id X --format ogg Склеить существующие chunks в partial/full файл

Все команды поддерживают --json; generate также поддерживает --json-events.

Модели и цены

Провайдер Модель Цена минуты
Polza openai/gpt-audio-mini ~0.004 ₽/мин (anomalous 200s smoke — model added speech, needs rerun)
Polza openai/gpt-audio ~7.00 ₽/мин
Polza openai/gpt-4o-mini-tts ~1.07 ₽/мин
Polza elevenlabs/text-to-speech-turbo-2-5 ~3.51 ₽/мин
Polza elevenlabs/text-to-speech-multilingual-v2 ~7.57 ₽/мин
OpenRouter google/gemini-3.1-flash-tts-preview ~$0.030/мин
OpenRouter openai/gpt-4o-mini-tts-2025-12-15 (исторический, withdrawn) ~$0.00041/мин
Qwen3-TTS CustomVoice (preset/clone) Бесплатно (GPU)
OmniVoice audio-cpp/omnivoice-q8_0 (auto/preset/clone/design) Бесплатно (GPU, локально)

Тестирование

uv sync --group dev --extra timing-whisper
uv run pytest

120 тестов: JSON-контракт, exit codes, валидация, output policy, providers, prompt modes, script metadata, resume/retry/state/log/status/concat safety, Gemini safe tags.

Agent Skill

OpenCode agent skill — устанавливает pipeline, выбирает провайдера, генерирует озвучку:

Legal / Provider Notes

This project is an independent CLI wrapper around third-party providers. It is not affiliated with OpenAI, Google, OpenRouter, Polza.ai, Qwen, or CTranslate2 / faster-whisper. Provider names and model names are used solely for integration and documentation purposes. Generated audio usage is subject to the selected provider's terms of service. Do not upload private voice samples or generated speech without permission.

License

MIT. See LICENSE.

Документация

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

voiceover_pipeline-0.6.1.tar.gz (1.8 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

voiceover_pipeline-0.6.1-py3-none-any.whl (174.3 kB view details)

Uploaded Python 3

File details

Details for the file voiceover_pipeline-0.6.1.tar.gz.

File metadata

  • Download URL: voiceover_pipeline-0.6.1.tar.gz
  • Upload date:
  • Size: 1.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"22.3","id":"zena","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for voiceover_pipeline-0.6.1.tar.gz
Algorithm Hash digest
SHA256 4217d9483376640d92b54940d5893e4e51a1396c66c897072ceab06305b622e2
MD5 3446b35d19da290eb8caf5fc879c82d5
BLAKE2b-256 31bb98cfb72b2c14446ea22c583c662b5a8f26d8825ef29f3243b64d57903d05

See more details on using hashes here.

File details

Details for the file voiceover_pipeline-0.6.1-py3-none-any.whl.

File metadata

  • Download URL: voiceover_pipeline-0.6.1-py3-none-any.whl
  • Upload date:
  • Size: 174.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"22.3","id":"zena","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for voiceover_pipeline-0.6.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b82118cb82737ccfc07bb173967f14f144aff5c6e061314b4b659cc322c78a4c
MD5 90e19946a7d3490266255521d3654149
BLAKE2b-256 3aef24573ac0f60950ea2a0ff981a033108dbd6d9e483a08964f606ff6533f40

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.6.1 This release

2 files

0.6.0

2 files

0.5.1

2 files

0.5.0

2 files

0.4.5

2 files

0.4.4

2 files

0.4.2

2 files

0.4.1

2 files

0.4.0

2 files

0.3.1

2 files

0.3.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page