vv-synth
vv-synth is a small CLI that sends text to VOICEVOX Engine and writes the synthesized audio as a local WAV file.
The project intentionally stays thin:
vv-synthtalks to a separately prepared VOICEVOX Engine over HTTP.- VOICEVOX Engine, voice libraries, model files, Docker images, official binaries, and generated WAV files are not bundled in this repository or the PyPI package.
- Runtime behavior is centered in
vv_synth/engine_client.py,vv_synth/output_paths.py, andmain.py.
Documentation
- Users: Quick Start / Install / Usage
- VOICEVOX terms: OSS Publication And VOICEVOX Terms
- Maintainers: Architecture / Maintenance / Release
- AI coding agents (Codex CLI / Claude Code recommended):
AGENTS.md/CLAUDE.md/.claude/rules//skills/README.md - Agent Skills:
skills/vv-synth/for portable TTS,skills/vv-synth-dev/for this repository
Requirements
| Requirement | Purpose |
|---|---|
| Python 3.14+ | Runtime |
| uv | Dependency and tool management |
| Docker | Optional way to run VOICEVOX Engine |
| VOICEVOX Engine | HTTP API on http://127.0.0.1:50021, prepared with Docker or an official binary |
Windows is supported as long as Python, uv, and a reachable VOICEVOX Engine are available. For Windows NVIDIA GPU usage, see Windows + NVIDIA GPU.
VOICEVOX CORE (voicevox_core/) is not required by vv-synth.
OSS Publication And VOICEVOX Terms
vv-synth is open source under the MIT License. This repository and the PyPI package contain only the small HTTP client CLI. It does not vendor VOICEVOX Engine itself, voice libraries, model files, Docker images, official Windows/macOS/Linux binaries, or generated WAV files.
Users are responsible for checking and following the latest official VOICEVOX terms. Using generated audio requires credit identifying VOICEVOX and compliance with each voice library / speaker's own terms. The required credit may be omitted only where an applicable license explicitly permits it. If generated audio is embedded in an application or redistributed, the final distribution must also satisfy those terms and credit requirements.
When granting others permission to use generated audio, you must require them to comply with the applicable voice library terms and to pass on these same obligations whenever they grant further permission to use the audio, as required by items 2 and 3 of the official VOICEVOX software terms.
References:
- VOICEVOX official software terms
- voicevox/voicevox_engine on Docker Hub
- VOICEVOX Engine Releases
- VOICEVOX Q&A
Maintainer checklist for every change and release:
- Confirm the code license in
LICENSE(MIT) matches thepyproject.tomllicense metadata. - Confirm
versioninpyproject.toml,metadata.versionin bothskills/*/SKILL.mdfiles, the release tagv<version>(created bygh skill publish --tag), and the version on PyPI match. - Confirm the VOICEVOX official links in this README are current.
- Confirm VOICEVOX Engine, voice libraries, model files, and generated WAV files are neither tracked by Git nor included in the PyPI sdist / wheel.
- If sample audio is ever distributed, confirm speaker-specific terms and credit notation first.
Prepare VOICEVOX Engine
vv-synth only needs an HTTP Engine listening on http://127.0.0.1:50021. The VOICEVOX desktop GUI is not required.
Docker users should use the official image. If you do not want Docker, use an official Engine binary from VOICEVOX Engine Releases.
Sources: voicevox/voicevox_engine on Docker Hub, Docker Desktop GPU support, VOICEVOX Q&A
Docker CPU
Pull the image:
docker pull voicevox/voicevox_engine:cpu-latest
Run in the foreground:
docker run --rm -it -p '127.0.0.1:50021:50021' voicevox/voicevox_engine:cpu-latest
Run in the background:
docker run --rm -d -p '127.0.0.1:50021:50021' voicevox/voicevox_engine:cpu-latest
Stop a background container with docker ps, then docker stop <id>.
Windows + NVIDIA GPU (Docker Desktop)
Windows GPU usage with Docker requires:
- Windows 10 / 11 with an NVIDIA GPU
- Docker Desktop with the WSL2 backend enabled
- A current NVIDIA driver that supports WSL2 GPU usage
- A current WSL2 Linux kernel (
wsl --updatein PowerShell)
Check whether Docker can see the GPU:
docker run --rm -it --gpus=all nvcr.io/nvidia/k8s/cuda-sample:nbody nbody -gpu -benchmark
Run the NVIDIA GPU Engine image:
docker pull voicevox/voicevox_engine:nvidia-latest
docker run --rm -it --gpus all -p '127.0.0.1:50021:50021' voicevox/voicevox_engine:nvidia-latest
Background:
docker run --rm -d --gpus all -p '127.0.0.1:50021:50021' voicevox/voicevox_engine:nvidia-latest
After the Engine is listening, vv-synth usage is the same as CPU mode. GPU selection is an Engine concern; vv-synth does not need a GPU-specific option.
Official Engine Binaries
If you do not use Docker, download an official binary for your OS from VOICEVOX Engine Releases. Windows builds include CPU, GPU/DirectML, and GPU/CUDA variants.
Once http://127.0.0.1:50021/version responds, vv-synth can use the binary Engine exactly like the Docker Engine. If you change the port, pass --engine-url or set VOICEVOX_ENGINE_URL.
Verify The Engine
In another terminal:
curl -sSf http://127.0.0.1:50021/version
If JSON is returned, the Engine is ready. Speaker style IDs are available from /speakers in http://127.0.0.1:50021/docs.
Engine Troubleshooting
| Symptom | Check |
|---|---|
Cannot connect to the Docker daemon |
Start Docker Desktop, or use an official Engine binary |
port is already allocated on 50021 |
Stop other Engine containers or the VOICEVOX desktop app |
| GPU container cannot select a driver | Confirm Docker Desktop WSL2 backend, NVIDIA driver, and wsl --update |
vv-synth cannot connect |
Confirm curl .../version works and the port is 127.0.0.1:50021 |
| HTTP 4xx for speaker | Pick a valid style ID from /speakers |
Do not run multiple Engines on port 50021 at the same time.
Quick Start
Install from PyPI:
uv tool install vv-synth
vv-synth --help
After starting VOICEVOX Engine with Docker or an official binary:
vv-synth "こんにちは、音声合成のテストです。"
The default output is output/YYYYMMDD-HHMMSS.wav (local time) under the directory where you run the command. The output/ directory is created automatically on first run. Set VV_SYNTH_OUTPUT_DIR to change the default directory globally.
Install
From PyPI (Recommended)
uv tool install vv-synth
Two commands are installed and behave identically:
vv-synth— the canonical namevvs— short alias
Upgrade or uninstall:
uv tool upgrade vv-synth
uv tool uninstall vv-synth
Run once without installing (uv fetches the package into a temporary environment):
uvx vv-synth "テストです"
If ~/.local/bin is not on PATH:
uv tool update-shell
# or
export PATH="$HOME/.local/bin:$PATH"
From Source
Install the latest main from GitHub:
uv tool install git+https://github.com/ru-461/vv-synth
Or from a local clone (editable):
git clone https://github.com/ru-461/vv-synth.git
cd vv-synth
uv tool install --editable .
If the repository path changes after an editable install, reinstall:
uv tool uninstall vv-synth
cd /path/to/vv-synth
uv tool install --editable .
To work on the code itself, see Maintenance.
Agent Skill Local Install
The portable vv-synth Agent Skill lets coding agents use this CLI from other projects. gh skill is the recommended installation path; npx skills (Vercel Labs) is a supported alternative.
Recommended: gh skill
Requires GitHub CLI v2.90+:
cd /path/to/vv-synth
gh skill install . vv-synth --from-local --scope user --agent universal
Use a specific agent target if you only want the skill installed for one host:
gh skill install . vv-synth --from-local --scope user --agent codex
gh skill install . vv-synth --from-local --scope user --agent claude-code
Preview the published skill before installing (reads from GitHub; in a local clone, read skills/vv-synth/SKILL.md directly):
gh skill preview ru-461/vv-synth vv-synth
Alternative: npx skills
Requires Node.js; no global install needed. --global targets your user directory (omit it for the current project only):
cd /path/to/vv-synth
npx skills@latest add . --skill vv-synth --global
Target one agent, or list the repository's skills before installing:
npx skills@latest add . --skill vv-synth --global --agent claude-code
npx skills@latest add . --list
See skills/README.md for publishing, updates, and project-scoped installs.
Usage
vv-synth MESSAGE [OPTIONS]
vv-synth --help is written in English.
A successful run prints INFO: wrote <absolute-path> to stdout. Synthesis and file I/O errors print one English line to stderr and exit with code 1. Invalid arguments or options produce a Typer usage error on stderr and exit with code 2.
| Option | Short | Default | Description |
|---|---|---|---|
MESSAGE |
- | required | Text to synthesize |
--output |
-o |
automatic timestamp | Output WAV file name or path |
--output-dir |
- | output |
Directory for WAV files when --output is a basename; can also be set with VV_SYNTH_OUTPUT_DIR |
--speaker |
-s |
2 |
VOICEVOX speaker style ID |
--speed |
- | 1.0 |
Finite speech speed from 0.01 to 10.0 (1.0 is normal; larger is faster) |
--engine-url |
- | http://127.0.0.1:50021 |
Engine URL; can also be set with VOICEVOX_ENGINE_URL |
Examples:
vv-synth "テストです" -o hello.wav
vv-synth "テストです" --output-dir artifacts
vv-synth "テストです" -s 3 --speed 1.5
Speaker style IDs: http://127.0.0.1:50021/docs, /speakers
Architecture
Component Layout
Keep this diagram aligned with the implementation when module boundaries change.
flowchart TB
subgraph cli["vv-synth CLI"]
main["main.py\nTyper"]
paths["vv_synth/output_paths.py"]
client["vv_synth/engine_client.py"]
end
subgraph external["External"]
engine["VOICEVOX Engine\nDocker or binary / :50021"]
end
subgraph fs["Filesystem"]
outdir["./output/\n(current working directory)"]
end
user(["User / Agent"]) --> main
main --> paths
main --> client
paths --> outdir
client -->|"POST /audio_query"| engine
client -->|"POST /synthesis"| engine
client --> outdir
| Path | Responsibility |
|---|---|
main.py |
Typer CLI and vv-synth entry point |
vv_synth/output_paths.py |
Output path resolution (output/, -o, timestamp names) |
vv_synth/engine_client.py |
Engine HTTP calls, speech rate, WAV saving |
Synthesis Flow
Update this sequence if the Engine API call order changes.
sequenceDiagram
actor U as User
participant M as main.py
participant P as output_paths
participant C as engine_client
participant E as VOICEVOX Engine
U->>M: vv-synth MESSAGE [options]
M->>P: resolve_output_file()
P-->>M: Path
M->>C: synthesize_text_to_file()
C->>E: POST /audio_query?text&speaker
E-->>C: AudioQuery (JSON)
C->>C: apply_speed_scale()
C->>E: POST /synthesis?speaker
E-->>C: WAV bytes
C->>C: save_wav()
C-->>M: Path
M-->>U: INFO wrote path (stdout)
Project Layout
vv-synth/
├── main.py
├── vv_synth/
│ ├── engine_client.py
│ └── output_paths.py
├── tests/ # pytest suite (Engine mocked; no running Engine needed)
├── output/ # Git-ignored WAV output, except .gitkeep
├── docs/ # Japanese project overview (OVERVIEW.ja.md)
├── skills/ # Agent Skills (vv-synth, vv-synth-dev)
├── .claude/rules/ # Agent rules referenced by AGENTS.md
├── .github/ # CI workflow, Dependabot, issue / PR templates, and Code of Conduct
├── pyproject.toml # vv-synth package and [project.scripts]
├── AGENTS.md # Shared agent guidance
├── CLAUDE.md # Claude Code summary
├── CONTRIBUTING.md # Contribution guide
├── SECURITY.md # Security policy
├── README.md # English main README
├── README.ja.md # Japanese README
├── LICENSE # MIT (code only; generated audio follows VOICEVOX terms)
└── uv.lock
Output Directory
By default, WAV files are written under output/ relative to the command's current working directory.
| Invocation | Output example |
|---|---|
no -o |
output/20260521-143052.wav |
-o hello.wav |
output/hello.wav |
-o path/to/a.wav |
path/to/a.wav |
--output-dir artifacts |
artifacts/... |
VOICEVOX CORE
vv-synth only uses the VOICEVOX Engine HTTP API. VOICEVOX CORE, voice libraries, and model files are not bundled with this CLI and are not part of its setup flow.
Maintenance
Environment
uv sync --group dev
Start VOICEVOX Engine with Docker or an official binary, then confirm:
curl -sSf http://127.0.0.1:50021/version
Change Map
| Change | Primary files | Also update |
|---|---|---|
| CLI options/help | main.py |
Usage, vv-synth --help wording |
| Output path rules | vv_synth/output_paths.py |
Output Directory |
| Engine API/speed/errors | vv_synth/engine_client.py |
Mermaid diagrams |
| Global command name | pyproject.toml [project.scripts] |
install instructions |
| Dependency versions | pyproject.toml |
uv lock / uv.lock |
| Release version | pyproject.toml version |
skills/*/SKILL.md metadata.version, uv.lock, Release |
| Agent rules/boundaries | AGENTS.md, CLAUDE.md, .claude/rules/*.md |
Architecture tables |
| Engine setup or VOICEVOX terms guidance | README files, skills/*/SKILL.md |
official links and Docker/binary parity |
Mermaid Updates
The canonical architecture diagrams live in this README. Update them when:
- modules are added, renamed, or change responsibility;
- Engine API endpoints or call order change;
- CLI dependencies on the filesystem or external services change.
Keep the copies in README.ja.md and docs/OVERVIEW.ja.md aligned when diagram content changes.
Quality Checks
uv run ruff check .
uv run ruff format .
uv run ty check
uv run pytest
pytest runs the unit test suite in tests/. Tests mock the Engine over urllib, so no
running VOICEVOX Engine is required.
Manual smoke test with Engine running:
uv run vv-synth "maintenance smoke test"
ls -la output/
If package entry points changed:
uv tool install --editable .
vv-synth --help
Release
Each release publishes one version to PyPI, as the GitHub Release tag v<version>, and as the Agent Skills release. PyPI never accepts the same version twice.
-
Set
versioninpyproject.tomlandmetadata.versionin bothskills/*/SKILL.mdfiles to the new value, then runuv lock(CI usesuv sync --locked). -
Run the quality checks, then commit and push
main. -
Build fresh distributions and confirm they contain only the CLI code (no VOICEVOX assets or WAV files):
uv build --clear tar -tzf dist/vv_synth-<version>.tar.gz unzip -l dist/vv_synth-<version>-py3-none-any.whl
-
Create the GitHub Release and tag, which also publishes the Agent Skills:
gh skill publish --tag v<version>. -
Upload to PyPI with
uv publish. It uploadsdist/*and needs PyPI credentials, such as an API token inUV_PUBLISH_TOKEN.
PyPI shows the README.md from the uploaded release, so README changes reach the PyPI page only with the next release.
Documentation Sync Checklist
-
README.mdandREADME.ja.mddescribe the same user-facing behavior. - Links from
README.mdto repository files are absolute GitHub URLs, because it is also the PyPI project description. - Mermaid diagrams match the implementation.
-
AGENTS.md/CLAUDE.mdand Agent Skills are current. - CLI option tables match
vv-synth --help. - VOICEVOX Engine / voice library terms links and the "do not vendor external assets" policy remain intact.
-
LICENSEand thepyproject.tomllicense metadata still match.
Commit Policy
- Commit only when explicitly requested.
- Use an English one-line message:
prefix: message. - Examples:
feat: add pitch option,docs: update engine setup. - Do not commit
output/*.wav,voicevox_core/,download, VOICEVOX Engine binaries, models, voice libraries, or virtual environments.
Troubleshooting
| Symptom | Check |
|---|---|
command not found: vv-synth |
uv tool install vv-synth and PATH (~/.local/bin) |
Connection refused |
Start Engine with Docker or an official binary; confirm port 50021 |
| HTTP 4xx | Check the --speaker style ID |
| WAV is not saved | Current working directory, --output-dir, and write permissions |
| Mermaid does not render | Markdown fence must be ```mermaid |
Metadata
Release files for vv-synth 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| vv_synth-0.1.1.tar.gz | 36.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vv_synth-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 49.7 kB
Release files / vv_synth-0.1.1.tar.gz
| Download URL | vv_synth-0.1.1.tar.gz |
|---|---|
| Size | 36.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8e0e018d13dd4a6910384cddad7071e49e716bddf4a5acf9c9b774def0c778b5
|
|
BLAKE2b-256 checksum How to use checksums |
c6d03b7db3808b933d0251daae2ed8d24c2eb573a95984219aaf169d7471e9a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / vv_synth-0.1.1-py3-none-any.whl
| Download URL | vv_synth-0.1.1-py3-none-any.whl |
|---|---|
| Size | 13.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3ac5004a78d36850da5dbc0084d09591849093cbaab5a5522d05730e6f7bc217
|
|
BLAKE2b-256 checksum How to use checksums |
f6552b48138000312cd4f9d2541d376b1f20175b4f408bc305279c29065c749c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|