scripts/record-reference.sh
scripts/record-reference.shBrowse 7 files
1,737 tokens
5,803 bytes
Token encoding: o200k_base
Snapshot 4e55180
← Back to SKILL.md
1#!/usr/bin/env bash2# Record a clean reference clip for OmniVoice voice cloning.3#4# Usage:5# scripts/record-reference.sh [output.wav] [duration_seconds] [mic_index]6#7# Defaults:8# output = ~/Downloads/omnivoice-ref.wav9# duration = 12 seconds raw capture (trimmed to 10 sec of speech)10# mic_index = 1 (typically MacBook built-in; run `ffmpeg -f avfoundation -list_devices true -i ""` to enumerate)11#12# Why this script exists:13# - macOS Terminal buffers stdout — "speak now" prints arrive AFTER the recording finishes.14# This script uses `say` (macOS TTS) + system sound beeps to give the user *audible* cues15# that bypass terminal buffering.16# - 24 kHz mono is what OmniVoice's diffusion model expects internally; recording natively at17# that rate avoids a resample step.18# - silenceremove + atrim crops the user's actual speech window out of a longer raw capture,19# so the user doesn't have to time their start perfectly.20#21# Cross-platform note: macOS-only (relies on avfoundation, `say`, /System/Library/Sounds).22# Linux equivalent would use `arecord` + `espeak` + `aplay`; not implemented here.23#24# Exit codes:25# 0 success26# 2 environment problem (wrong OS, missing tool)27# 3 user-action problem (mic permission denied — captured silence)28# 4 verification failed (trimmed reference too short)29 30set -euo pipefail31 32# Platform guard FIRST — before mktemp / trap / anything else macOS-specific33if [ "$(uname)" != "Darwin" ]; then34 echo "✗ this helper is macOS-only (uses avfoundation, say, /System/Library/Sounds)." >&235 echo " Linux equivalent: arecord + espeak + aplay; not implemented." >&236 exit 237fi38 39if ! command -v ffmpeg >/dev/null 2>&1; then40 echo "✗ ffmpeg not found — install via brew install ffmpeg" >&241 exit 242fi43 44if ! command -v ffprobe >/dev/null 2>&1; then45 echo "✗ ffprobe not found — install via brew install ffmpeg" >&246 exit 247fi48 49OUT="${1:-$HOME/Downloads/omnivoice-ref.wav}"50DUR="${2:-12}"51MIC="${3:-1}"52 53RAW="$(mktemp -t omnivoice-raw-XXXXX).wav"54# Cover all common termination paths so the temp file never leaks55trap 'rm -f "$RAW"' EXIT INT TERM HUP56 57# Beep helper — uses system sound if available, otherwise terminal bell.58beep() {59 local snd="$1"60 if [ -f "$snd" ]; then61 afplay "$snd" &62 else63 printf '\a' >&264 fi65}66 67PING="/System/Library/Sounds/Ping.aiff"68POP="/System/Library/Sounds/Pop.aiff"69 70echo "▶︎ Recording reference for OmniVoice voice cloning"71echo " mic index: $MIC (run \`ffmpeg -f avfoundation -list_devices true -i \"\"\` to list)"72echo " raw window: ${DUR}s · output: $OUT"73echo74 75# Spoken instructions + countdown (heard in real time, bypasses terminal buffering)76say -r 180 "Recording in three seconds. After the high beep, speak your reference phrase. Recording continues for ${DUR} seconds."77sleep 0.378say -r 220 "three"; say -r 220 "two"; say -r 220 "one"79 80# Start cue81beep "$PING"82 83# Capture84ffmpeg -hide_banner -loglevel error -y -f avfoundation -i ":$MIC" -t "$DUR" -ac 1 -ar 24000 "$RAW"85 86# End cue87beep "$POP"88 89echo "✓ raw captured"90 91# Sanity-check levels — bail loudly if the recording is silent (mic permission denied is the92# most common cause: macOS gives the calling process a silent stream and ffmpeg returns 0).93LEVELS=$(ffmpeg -hide_banner -i "$RAW" -af "volumedetect" -f null - 2>&1)94echo "raw levels:"95echo "$LEVELS" | grep -E "mean_volume|max_volume" | sed 's/^/ /'96 97MEAN=$(echo "$LEVELS" | grep -oE "mean_volume:[[:space:]]*-?[0-9.]+" | grep -oE "\-?[0-9.]+$" | head -1)98if [ -z "$MEAN" ]; then99 echo "✗ could not parse audio levels — ffmpeg may have failed to record" >&2100 exit 3101fi102# Compare via awk (bash can't do floating-point natively)103if awk -v m="$MEAN" 'BEGIN { exit !(m < -50) }'; then104 echo "✗ recording is silent (mean ${MEAN} dB < -50 dB)." >&2105 echo " Most likely: macOS denied microphone access to the calling process." >&2106 echo " Fix: System Settings → Privacy & Security → Microphone → enable for your terminal" >&2107 echo " (or for the agent harness). Then re-run this script." >&2108 exit 3109fi110 111# Trim leading silence + take first ~10 seconds of speech (or all of it if shorter)112TARGET=10113ffmpeg -hide_banner -loglevel error -y -i "$RAW" \114 -af "silenceremove=start_periods=1:start_silence=0.05:start_threshold=-40dB,atrim=end=${TARGET}" \115 -ac 1 -ar 24000 "$OUT"116 117# Verify the trim produced a usable reference (≥ 2.0s of speech)118REF_DUR=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$OUT" 2>/dev/null || echo "0")119if awk -v d="$REF_DUR" 'BEGIN { exit !(d < 2.0) }'; then120 echo "✗ trimmed reference is only ${REF_DUR}s (< 2s minimum)." >&2121 echo " silenceremove found very little speech above -40 dB threshold." >&2122 echo " Likely cause: you spoke too softly, or the mic captured mostly background noise." >&2123 echo " Try again, speak closer to the mic." >&2124 exit 4125fi126 127echo "✓ trimmed reference: $OUT"128ffmpeg -hide_banner -i "$OUT" -af "volumedetect" -f null - 2>&1 \129 | grep -E "Duration|mean_volume|max_volume" \130 | sed 's/^/ /'131 132# Auto-play back so the user can verify before POSTing.133# Don't swallow stderr — if playback fails the user should know.134echo135echo "▶︎ playing reference for verification..."136if ! afplay -v 3 "$OUT"; then137 echo "⚠ verification playback failed — afplay exited non-zero. The file may still be valid;" >&2138 echo " try \`afplay $OUT\` manually or open it in a player to confirm." >&2139fi140echo "✓ done"141echo142echo "Next: POST to /profiles to create a voice profile:"143echo " curl -X POST http://127.0.0.1:3900/profiles \\"144echo " -F \"name=my-voice\" \\"145echo " -F \"ref_audio=@$OUT\" \\"146echo " -F \"ref_text=<the exact text you spoke>\" \\"147echo " -F \"language=English\""148 Referenced from SKILL.md
SKILL.mdView in source ↗
Source excerpt starting at line 86.SKILL.mdView in source ↗86```bash87scripts/record-reference.sh ~/Downloads/my-ref.wav 12 188# args: output_path raw_duration_sec mic_index
Source excerpt starting at line 167.167- [scripts/stop-backend.sh](scripts/stop-backend.sh) — Clean shutdown via `kill -TERM` on the bound PID168- [scripts/record-reference.sh](scripts/record-reference.sh) — macOS-only: record + trim + verify a reference clip for cloning, with audible cues (`say` + system beeps) that bypass terminal output buffering