Skip to content
Agentmart
Submit a tool

explainer-audio-narrate

Synthesize an existing A:/B: VOICEVOX-kana dialogue script into AAC/m4a with local VOICEVOX and ffmpeg.

Skill by choplin

IndexedMIT★ 1
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/choplin-explainer-audio-narrate

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Synthesize an existing A:/B: VOICEVOX-kana dialogue script into AAC/m4a with local VOICEVOX and ffmpeg. Use when the user wants a validated synthesis script narrated as audio. Use explainer-audio-voicevox when that script does not exist yet.

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found
Runs as
Shell scripts

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/explainer-audio-narrate

What's inside

Skill name
explainer-audio-narrate
Description
Synthesize an existing A:/B: VOICEVOX-kana dialogue script into AAC/m4a with local VOICEVOX and ffmpeg. Use when the user wants a validated synthesis script narrated as audio. Use explainer-audio-voicevox when that script does not exist yet.
License
MIT
Instructions
126 lines in SKILL.md · view on GitHub

Before installing

  • Ships executable scripts
  • Instructions call the network

Files (2)

  • SKILL.md
  • dialogue-to-audio.sh

SKILL.md (first lines)

# Audio Narrate

Turn a two-speaker VOICEVOX-kana dialogue script into a single spoken audio file.
This is the synthesis phase of the audio-guide flow;
[[explainer-audio-voicevox]] writes the content-accepted synthesis script, and
this skill reads only that `.voicevox.txt` file.

Synthesis uses a **local VOICEVOX ENGINE** — natural neural Japanese TTS from a plain HTTP server on `localhost` (no API key, fully offline). Each speaker gets a distinct character voice. The script uses `curl` to call the engine and Python 3 stdlib (`wave`) to stitch turns (no API keys). The stitched audio is then encoded to a compact **AAC/m4a** file with **`ffmpeg`** — cross-platform (Linux/macOS/Windows). `ffmpeg` is a required prerequisite for m4a output: the script checks for it up front and errors out if it is missing (no silent WAV fallback).

The script manages the engine for you: if one is already running it is reused, otherwise the script starts the engine, waits until it is ready, synthesizes, and stops that engine when done (it never stops an engine you were already running).

## When this applies

Use when a VOICEVOX AquesTalk-style kana dialogue in the `A:`/`B:` line format
already exists—produced by [[explainer-audio-voicevox]] or written by hand. A
normal Japanese dialogue is not a synthesis input. If the synthesis script does
not exist yet, run [[explainer-audio-voicevox]] first.

When this skill runs as a source-workflow narration phase, also apply
[[explainer-content-workflow-base]] and read the selected profile. The caller
must provide exact paths and SHA-256 digests for the immutable run request, Run
Manifest, human-readable dialogue Artifact, and paired `voicevox-dialogue`
Artifact, the passing [[explainer-audio-dialogue-review]] Artifact on which that
VOICEVOX dialogue depends, plus the Manifest's unique audio output entry.
Validate that the entry's action is `create` or `replace`, that it names the
supplied `voicevox-dialogue` as its input, that the review identifies the exact
human-readable dialogue digest and has `result: pass`, and that any selected
prerequisite checkpoint has a matching decision Artifact. Stop with a structured missing or
incompatible-input result instead of inferring a current Manifest, dialogue, or
output from conversation history. This phase writes only the planned audio
Artifact and returns its path, digest, duration, acceptance checks, and blocker.

Outside a content workflow, an explicitly supplied `.voicevox.txt` path and output
choice are sufficient; no run request or Manifest is required.

The synthesis script format (also documented in [[explainer-audio-voicevox]]):

- `A:` / `B:` (lowercase and full-width `:` accepted) starts a speaker turn.
- Lines without a prefix continue the current turn.
- `#` lines and blank lines are ignored.
- Spoken fields use valid VOICEVOX AquesTalk-style kana. The script validates
  each complete turn with `/validate_kana` before synthesis and stops on the
  first invalid turn.

## Setup — VOICEVOX ENGINE

This skill's synthesis is done by a **VOICEVOX ENGINE** — a local HTTP server. **It is an essential prerequisite: without it this skill cannot produce audio, and there is no fallback synthesizer.** It is free, offline, and needs no API key. Install it once; the bundled script starts/stops it as needed, and if the engine is neither running nor installable on `PATH` the script exits with an error explaining how to install it — relay that and stop, do not substitute another TTS.

- Install (Nix): `nix profile install nixpkgs#voicevox-engine`. Other install methods (the VOICEVOX app bundles the engine, or a standalone engine download) work too.
- The script auto-starts it via the `voicevox-engine` binary on `PATH` (override with `VOICEVOX_ENGINE_BIN`). If you prefer to keep an engine running yourself (`voicevox-engine` in a terminal), the script detects and reuses it.

## Procedure

Run the bundled script, giving the dialogue script path and an output path:

```sh
explainer-audio-narrate/dialogue-to-audio.sh <script.voicevox.txt> [output.m4a] [--play]
explainer-audio-narrate/dialogue-to-audio.sh <script.voicevox.txt> --validate-only
```

- If the output path is omitted, `<WORK_DIR>/dialogue/<slug>.voicevox.txt` maps to `<WORK_DIR>/audio/<slug>.m4a`; other input locations default beside the script. The output format follows the extension you pass: `.m4a` encodes AAC (requires `ffmpeg`), any other extension writes WAV. Prerequisites (`python3`, `curl`, and `ffmpeg` for m4a) are checked up front, before the engine starts, so a missing tool fails fast.
- In a planned workflow, overwrite only when the immutable Manifest marks this exact path `replace`; `create` must fail if the path already exists. In standalone use, confirm before overwriting an existing target.
- For each turn, validate the notation, obtain engine defaults from `/audio_query`, obtain the intended phrases from `/accent_phrases?is_kana=true`, replace the query's `accent_phrases`, and then synthesize. Never send the human-readable kanji script to VOICEVOX's text parser.
- `--validate-only` checks every complete turn through `/validate_kana` without
  creating audio. [[explainer-audio-voicevox]] uses it before handoff.
- `--play` synthesizes and then plays the result with `afplay` (macOS).

> **Run without the command sandbox.** The script talks to a local VOICEVOX ENGINE over `localhost` (and spawns it when one isn't already running), which a command sandbox blocks. Invoke it with `dangerouslyDisableSandbox: true`. (The `ffmpeg` m4a encoding itself is self-contained and would run fine under a sandbox; it's the engine networking that needs it off.)

Report the output path and duration to the user.

## Voices (cast pairs)

Voices come from a **cast pair**: two casts with the roles assigned—the learner
is speaker `A`, the explainer is speaker `B`—each carrying its own VOICEVOX style
id. The pair is chosen (highest priority first) from the `STYLE` env var, then a
`# style: <pair>` marker preserved by [[explainer-audio-voicevox]], then the
default `zundamon`.

[[explainer-audio-cast-base]] owns the pairs, one file per pair, and defines the
`cast-binding` lines that open each one. The script resolves `<pair>` to
`references/pair-<pair>.md` there and reads its bindings; there is no voice table
in this file or in the script. Add a pair there, not here.

Because [[explainer-audio-voicevox]] preserves the readable script's matching
`# style:` marker, narration resolves the right voices automatically—no need to
pass `STYLE` when narrating its output. An unknown pair id is a hard error that
lists the pairs the directory defines.

## Options

Override per run with environment variables:

```sh
STYLE=formal \
  explainer-audio-narrate/dialogue-to-audio.sh script.voicevox.txt out.m4a
```

| Var | Default | Meaning |
|-----|---------|---------|
| `VOICEVOX_URL` | `http://127.0.0.1:50021` | VOICEVOX ENGINE base URL |
| `VOICEVOX_ENGINE_BIN` | `voicevox-engine` | Engine binary used for auto-start |
| `CASTS_DIR` | `explainer-audio-cast-base/references` | Directory of `pair-<id>.md` definitions |
| `STYLE` | *(marker → `zundamon`)* | Cast pair id — a `pair-<id>.md` in `CASTS_DIR` |
| `SPEAKER_A` | *(from the pair's learner cast)* | Override speaker A **style id** |
| `SPEAKER_B` | *(from the pair's explainer cast)* | Override speaker B **style id** |
| `SPEED` | `1.0` | `speedScale` applied to every turn |
| `PAUSE_MS` | `350` | Silence inserted between turns (ms) |
| `AAC_BITRATE` | `64k` | AAC bitrate for `.m4a` output (ffmpeg `-b:a`) |

`SPEAKER_A` / `SPEAKER_B` override the pair's resolved voices per speaker. List the engine's speakers and style IDs with `curl http://127.0.0.1:50021/speakers`.

## Requirements & notes

- Needs the **VOICEVOX ENGINE** installed (see Setup), plus `curl`, Python 3, and `ffmpeg` (for m4a). The script starts the engine when it is not already running and stops it afterward. `--play` uses macOS `afplay` when present, and the duration readout uses `ffprobe`, falling back to macOS `afinfo`.
- Output is **AAC/m4a** by default, at the engine's own 24 kHz mono. `ffmpeg` is required for it and its absence is a hard error with no WAV fallback; pass an explicit `.wav` output path only when you deliberately want unencoded WAV.
- The human-readable `A:`/`B:` script remains backend-agnostic. The paired `.voicevox.txt` file is deliberately backend-specific and may be regenerated or replaced if the TTS backend changes.

## Success criteria

From choplin/explainer-studio, MIT.

More from choplin/explainer-studio

Signals

Stars
1
Forks
0
Open issues
0
Last commit (this folder)
Sep 8, 2026 (1 month ago)
Last release
Aug 20, 2026 (2 months ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from choplin

Cite this page

explainer-audio-narrate skill. Agent Mart. https://agentmart.dev/skills/choplin-explainer-audio-narrate (last updated 2026-10-24)