aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/clone-voice.sh
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/clone-voice.sh')
-rwxr-xr-xscripts/clone-voice.sh47
1 files changed, 47 insertions, 0 deletions
diff --git a/scripts/clone-voice.sh b/scripts/clone-voice.sh
new file mode 100755
index 0000000..348b076
--- /dev/null
+++ b/scripts/clone-voice.sh
@@ -0,0 +1,47 @@
+#!/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/<name>.{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 <recording.wav> <transcript.txt> [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\""