speech

Platformneta/speech
Use it in Cohub

Paste this into your agent's chat — it fetches the skill and follows it.

Use the skill: speech. Run `npx -y @neta-art/neta-search-cli@latest skills use neta/speech --via site` and follow what it prints. Read its complete output, redirecting it to a temporary file first if necessary, and resolve relative paths from the skill directory it prints.
Use in Neta Studio Open it in Neta Studio and see what people made with it.
Install from a terminal
npx -y @neta-art/neta-search-cli@latest skills use neta/speech
Summary

Give a character a voice, change it, add languages, or have them speak your lines out loud.

  • Make a voice for any character from their card, or remake it if you don't like the first result.
  • Change how it sounds: reading style, speed, emotion, dialect or accent, and keep different setups to switch between.
  • Add another language so the same character can speak lines in it.
  • Have the character speak lines, a scene or a narration, with one audio per line that you can keep as a work.
  • Ask what a character's voice is right now: its version, the setup in use and what has been adjusted.
SKILL.md
# Speech

A character's voice is a voice pack of the **voice-pack** skill, in `world/media/studio/<folder>/<name>/voice-pack/` for the card `world/<folder>/<name>.md`; the character has a voice exactly when that folder exists. `<atom>` in every command is the card's path in the world, `world/<folder>/<name>.md`.

```bash
S=/mods/neta/.agents/skills
CV="node $S/speech/scripts/character-voice.mjs"    # the files side of a voice, from any folder in the world; --help lists every command
V=$($CV voice-pack)                                # voice-pack's command line: node $V/cli.mjs help
```

Two models speak, behind Studio's adapter: flash designs a voice from a description, as raw material only; scene 3 speaks everything else by default, and flash dubs too when it is the creator's pick or scene 3 is not available ([`models.md`](models.md)).

## Where to go

Find the request below and read its file before the first command; its last step says when the work is done.

| The request | Read |
|---|---|
| Make or remake a voice: the creator asks, a background run for the card's Retry, a change of voice | [`make-voice.md`](make-voice.md) |
| The card's Edit chat, or a change asked for without its details | [`edit-session.md`](edit-session.md) |
| A change with its details: a reading, a pin, a setup, a voice base, remove, restore | [`voice-edits.md`](voice-edits.md) |
| Add a language, or a line in another language than the voice | [`add-language.md`](add-language.md) |
| Update a voice to the new voice-pack (a background run) | [`update.md`](update.md) |
| Dub lines: in the chat, a scene, a narration, one audio for each line, kept as a work | [`dub.md`](dub.md) |
| What a voice is now | "A question about a voice", below |

Every text you write for a voice (the description and lines of a voice, a passage for a language, a card line) follows [`voice-texts.md`](voice-texts.md); every word a model speaks, dubbed lines too, is written as [`how-it-is-said.md`](how-it-is-said.md) says.

## Replies

- **The creator's language.** Give every `$CV` command `--reply-language <reply-tag>`: the language the creator writes to you in (Studio's prompt names it), not the voice's. The templates in these files leave it out. `begin`, `make`, `update`, `card-line`, `add-language`, `dub` and any command given `--expect` refuse to run without it (`input_invalid`, nothing done): run it again with it. Reply in that language.
- **Verbatim.** Where a command prints a `reply` (`runEnded`, a `make`'s own, `voice_changed`, `voice_busy`, `voice_removed`, `turn_answered`), or `$CV options` prints a question and its block, that is what you say for it, verbatim: the whole of it as printed, nothing added before, inside or after it (a `make`'s `reply` is the whole reply, and only what make-voice.md, step 6, allows can follow it). A dub's `sceneTogether` and `add-language`'s `cut` are said verbatim too, as one part of the longer reply their files describe.
- **Between commands.** The creator sees what you write between commands when they open the steps. Between commands, write a few words on what you do next. The voice and the recording are described, in a reply and between commands alike, only by the sentences the script gives.
- **Plain words.** The creator sees sentences, with no command, JSON, path, file name, pack id or error code. What voice-pack's `check` and `quality` found is told the same way. The texts that go into a pack or a script name no model, platform or tool.
- **Voice base.** A reference a voice speaks from is its *voice base* to the creator, in a reply, a question, an option and a message of voice-pack's you pass on: 音色基底 (zh, zh-Hant), voice base (en), 音色ベース (ja), 음색 베이스 (ko), Stimmbasis (de), base de voz (es), and in another language its plain words for "voice base". In Chinese it has this one name, 音色基底. The creator never sees the word for reference, in any language; the code's names (`referenceTag`, `--reference-tag`, `use-reference`) stay in the commands. A held-out recording is a recording kept aside to hear how alike the voice sounds. A tag `state` lists in `unnamed` is a voice base not named yet (还没起名的那段音色基底), told apart from another such by its language (`bases`), never by its tag or a number. Studio's card names no voice base.

## Guardrails every branch keeps

**The answer is acted on only while the voice is as it was when you asked.** Another chat can remove, bring back or remake the voice while the creator answers. So the command that acts on an answer takes the `state` you read when you asked, as `--expect <state>`: `begin` (`--replace-removed` too), every edit of voice-edits.md, `card-line`, `use-reference`, `add-reference`; remove and restore are checked first with `state --expect` (voice-edits.md, "Remove and restore"). Before any question a command will act on, run `$CV state <atom>` and keep its `state`. `voice_changed` (`details.now`, the state now) means nothing was done: the reply is its `details.reply`, verbatim, and the turn ends there. For the rest of that turn `$CV` answers `options`, `state --expect` and every change with `turn_answered`, the same sentence. The creator's next message is a new request: read the voice again and ask again. A chat stopped before `make` changes nothing; the next request starts at `begin`.

**The creator's picks are theirs.** The version and the setup in use (or 自动, `use-setup --auto`) are what the creator picked, on the card or in this chat, and they take effect at once, even while a chat runs. Act on the version and setup they picked; change either (`use-setup`, `use-reference`, a version of your own) only when the creator's request in this chat asks for that change. To hear a line another way, name it for that dub only, when the creator said so (dub.md, "Which voice base speaks").

**The voice's files are the script's.** The pack, its earlier versions, and every `voice-*` file and `.voice-*` marker beside it are written only through `$CV` and `neta atom voice`; voice-pack's `make-pack` puts no pack in place here. A change none of their commands makes is not made: say so in one sentence. Whether another run is going, and whose, is `state`'s `running` (`thisChat: true` is this run's own): reply and stop rather than wait for it.

**After a run made a version, it acts only on that version.** Each command that makes one prints its `version` (`make`, `add-language`, `update`, `card-line`, an edit). Every later command of the run on this voice but `$CV dub`, an answer to a block after it too, takes `--expect pack@<version>`, the last version the run made itself. A later version is another chat's or the creator's, whatever its card line says.

**A background run** is a chat Studio opens with nobody in it: the card's Retry of a first voice that failed, an update. It asks nothing and offers nothing, and goes straight through one round. It ends when its own steps are done (a `card-line` its `make` calls for included): the last command prints `runEnded`, and the whole reply is its `reply`, verbatim; after that it runs nothing more. On `voice_changed`, `pack_changed` or `voice_busy` it says nothing of it and ends, even where the code has a reply for a chat. Its sentences name only what its own commands printed (a version with `madeHere: false` is another chat's). Stopped with no `runEnded` for any other reason: one short sentence, in the creator's language, says why.

## When it does not work

`$CV` ends with `{"error":{"code","message","transient"}}` as the last line of stderr, its own, the adapter's or voice-pack's. A failure of a call already shows on the card; a refusal before any call does not.

- **A refusal before anything is done** (its message says nothing was done, called or spoken: `input_invalid`, `images_not_seen`, `design_line_length`, `acted_too_long`, a card-line check, and the like): do what its message says and run the command again. The run stays open.
- **A failure of a call**: report it once, with the reason in the creator's words when it is theirs to fix (a recording too long to be written down, a line the service refused). A second attempt is the creator's call. `transient: true`: they can ask again later.
- `credentials_rejected` (or Cohub's 401, `cohub_unauthorized`): the creator signs in again.
- `pack_changed` from any command but `design` and `make` (those two: make-voice.md, "Make's own codes"): the creator picked another version on the card while the command ran, so nothing was put in place. A run the creator asked for says in one sentence that the change was not made because another version was picked, offers to make it on that one, and runs nothing again by itself.
- `voice_busy`: the voice is being made or changed in another run, and nothing was done. The reply is its `details.reply`, verbatim, and the run stops there.
- `run_ended`: this turn's run is over; the reply is its `reply`, verbatim. The chat's next turn starts afresh.
- A branch's own codes are in its file.

## A question about a voice

The creator asking what a character's voice is now is answered from `$CV state <atom>` alone: its version in `state`, the voice bases and their languages in `bases`, the one every dub speaks from in `speaksFrom`, the saved setups and the one in use in `setups` (with each one's `emotion` and `voiceBase`; no setup is in use while `auto` is `true`, which is 自动), what is pinned (emotion, speed, expressiveness, dialect, accent) in `pins`, the card's line in `cardLine`. Done when the reply says what was asked, in the creator's words.