← back to Voice Clone
clone.sh
68 lines
#!/bin/bash
# clone.sh — upload sample.wav to ElevenLabs as Instant Voice Clone "Steve",
# capture the voice_id, route it through the secrets manager so every skill
# (app-demo-video, reviewed-demo-video, use-voice) can grab it from env.
#
# Free tier: 10 voice slots, IVC enabled, ~90K chars/mo TTS budget.
set -euo pipefail
SAMPLE=${1:-$HOME/Projects/voice-clone/sample.wav}
NAME=${2:-Steve}
[ -f "$SAMPLE" ] || { echo "[abort] sample not found: $SAMPLE (run ./record.sh first)"; exit 1; }
KEY=$(grep '^ELEVENLABS_API_KEY=' ~/Projects/secrets-manager/.env | cut -d= -f2)
[ -z "$KEY" ] && { echo "[abort] ELEVENLABS_API_KEY missing in secrets-manager .env"; exit 1; }
echo "Uploading $(basename $SAMPLE) ($(du -h $SAMPLE | awk '{print $1}')) as voice '$NAME'..."
RESP=$(curl -s -X POST https://api.elevenlabs.io/v1/voices/add \
-H "xi-api-key: $KEY" \
-F "name=$NAME" \
-F "description=Steve Abrams narrator voice — used for project walkthroughs and reviewed-demo-videos" \
-F "files=@$SAMPLE" \
-F 'labels={"use_case":"narration","style":"editorial"}')
VOICE_ID=$(echo "$RESP" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('voice_id',''))" 2>/dev/null || echo "")
if [ -z "$VOICE_ID" ]; then
echo "[fail] no voice_id in response:"
echo "$RESP"
exit 2
fi
echo "✓ Voice created — id: $VOICE_ID"
echo ""
# Persist to .env (master + desktop copy)
for ENVFILE in ~/Projects/secrets-manager/.env ~/Desktop/site-factory.env; do
if [ -f "$ENVFILE" ]; then
grep -v '^ELEVENLABS_VOICE_STEVE=' "$ENVFILE" > "$ENVFILE.tmp" || true
echo "ELEVENLABS_VOICE_STEVE=$VOICE_ID" >> "$ENVFILE.tmp"
mv "$ENVFILE.tmp" "$ENVFILE"
echo " wrote ELEVENLABS_VOICE_STEVE → $ENVFILE"
fi
done
# Run a quick sanity TTS to verify the clone
SAMPLE_TEXT="This is Steve, narrating a walkthrough. Open the archive for every house."
echo ""
echo "Test render (8 words, ~3 sec audio):"
curl -s -X POST "https://api.elevenlabs.io/v1/text-to-speech/$VOICE_ID" \
-H "xi-api-key: $KEY" -H "Content-Type: application/json" \
-d "$(python3 -c "import json,sys; print(json.dumps({'text':'$SAMPLE_TEXT','model_id':'eleven_multilingual_v2','voice_settings':{'stability':0.5,'similarity_boost':0.85}}))")" \
-o ~/Projects/voice-clone/test.mp3
if [ -s ~/Projects/voice-clone/test.mp3 ]; then
echo "✓ Test MP3: ~/Projects/voice-clone/test.mp3"
echo " Listen: afplay ~/Projects/voice-clone/test.mp3"
else
echo "✗ Test render failed"
fi
echo ""
echo "═══════════════════════════════════════════════════════════"
echo " Voice ID saved as ELEVENLABS_VOICE_STEVE in .env files"
echo " Use in any script: export VOICE_ID=\$ELEVENLABS_VOICE_STEVE"
echo " Generate narration: ./say.sh \"some text\" out.mp3"
echo "═══════════════════════════════════════════════════════════"