#!/usr/bin/env bash # Extracts the latents of a voice from a recording, so the assistant can # speak with it. # # scripts/clone-voice.sh recording.wav transcript.txt [name] # # Produces assets/voices/.{spk,rvq,txt}, which is what the assistant # registers with tts-server at startup. It is done once: on every start the # already extracted latents are sent, not the recording. set -euo pipefail cd "$(dirname "$0")/.." WAV="${1:?usage: clone-voice.sh [name]}" TXT="${2:?missing the transcript of the recording}" NAME="${3:-asistente}" CODEC=vendor/qwentts.cpp/build/qwen-codec TOKENIZER=models/qwen-tokenizer-12hz-Q8_0.gguf for f in "$CODEC" "$TOKENIZER" "$WAV" "$TXT"; do [ -e "$f" ] || { echo "missing: $f" >&2; exit 1; } done OUT="assets/voices" mkdir -p "$OUT" echo "Extracting the voice from $WAV…" # --talker produces the speaker embedding (.spk) and the reference codes # (.rvq); with the transcript, the server enables ICL cloning, which sounds a # lot closer to the original than the embedding alone. "$CODEC" --model "$TOKENIZER" --talker \ --input "$WAV" \ -o "$OUT/$NAME" cp "$TXT" "$OUT/$NAME.txt" echo echo "Done:" ls -la "$OUT/$NAME".{spk,rvq,txt} echo echo "Point config/asistente.toml at this voice:" echo " [tts.reference]" echo " name = \"$NAME\"" echo " speaker = \"../$OUT/$NAME.spk\"" echo " codes = \"../$OUT/$NAME.rvq\"" echo " transcript = \"../$OUT/$NAME.txt\""