1e51ef7def
- Konzept/, didaktik_geografie/, didaktik_simulation/, v2-modules/, v2-platform/ - 12 code-workspace-Files - STATUS-*.md - viele M/D/R-Änderungen an bereits getrackten Files - .gitignore verstärkt: **/.humaninput/, **/secret_keys.txt Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
93 lines
2.5 KiB
Bash
93 lines
2.5 KiB
Bash
#!/usr/bin/env bash
|
|
# Busfahrt UI-Sounds via ElevenLabs Sound Effects API.
|
|
#
|
|
# Aufruf:
|
|
# set -a; source App/.env.local; set +a
|
|
# App/sims/busfahrt/scripts/generate-sounds.sh # alle fehlenden
|
|
# App/sims/busfahrt/scripts/generate-sounds.sh hit-ok # gezielt
|
|
#
|
|
# FORCE=1 ./generate-sounds.sh hit-ok # ueberschreiben
|
|
set -e
|
|
: "${ELEVENLABS_API_KEY:?ELEVENLABS_API_KEY env var nicht gesetzt}"
|
|
|
|
cd "$(dirname "$0")/.."
|
|
mkdir -p assets/sounds
|
|
OUT_DIR="$(pwd)/assets/sounds"
|
|
|
|
mapfile -t LINES < <(python -c "
|
|
import json
|
|
data = json.load(open('scripts/sounds-list.json', encoding='utf-8'))
|
|
for s in data['sounds']:
|
|
print(s['file'] + '|||' + str(s['duration']) + '|||' + str(s.get('influence', 0.5)) + '|||' + s['prompt'])
|
|
")
|
|
|
|
TARGETS=("$@")
|
|
TOTAL=${#LINES[@]}
|
|
i=0
|
|
ok=0
|
|
fail=0
|
|
|
|
for line in "${LINES[@]}"; do
|
|
i=$((i+1))
|
|
IFS='|||' read -r file dur infl prompt <<< "$line"
|
|
# Bash split mit ||| → gibt nur ersten Token, wir brauchen split via tr/awk
|
|
file=$(echo "$line" | awk -F'\\|\\|\\|' '{print $1}')
|
|
dur=$(echo "$line" | awk -F'\\|\\|\\|' '{print $2}')
|
|
infl=$(echo "$line" | awk -F'\\|\\|\\|' '{print $3}')
|
|
prompt=$(echo "$line" | awk -F'\\|\\|\\|' '{print $4}')
|
|
id="${file%.mp3}"
|
|
|
|
if [ ${#TARGETS[@]} -gt 0 ]; then
|
|
skip=1
|
|
for t in "${TARGETS[@]}"; do
|
|
[ "$t" = "$id" ] || [ "$t" = "$file" ] && { skip=0; break; }
|
|
done
|
|
[ $skip -eq 1 ] && continue
|
|
fi
|
|
|
|
out="$OUT_DIR/$file"
|
|
if [ -f "$out" ] && [ -z "$FORCE" ]; then
|
|
echo "[$i/$TOTAL] $file: skip (existiert)"
|
|
continue
|
|
fi
|
|
|
|
echo -n "[$i/$TOTAL] $file (${dur}s): "
|
|
payload=$(PROMPT="$prompt" DUR="$dur" INFL="$infl" python -c '
|
|
import json, os
|
|
print(json.dumps({
|
|
"text": os.environ["PROMPT"],
|
|
"duration_seconds": float(os.environ["DUR"]),
|
|
"prompt_influence": float(os.environ["INFL"]),
|
|
}))')
|
|
|
|
http_code=$(curl -s -o "$out" -w "%{http_code}" --max-time 60 -X POST \
|
|
https://api.elevenlabs.io/v1/sound-generation \
|
|
-H "xi-api-key: $ELEVENLABS_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-H "Accept: audio/mpeg" \
|
|
-d "$payload")
|
|
|
|
if [ "$http_code" = "200" ]; then
|
|
sz=$(stat -c%s "$out" 2>/dev/null || stat -f%z "$out" 2>/dev/null)
|
|
if [ "$sz" -gt 200 ]; then
|
|
echo "ok ($((sz/1024)) KB)"
|
|
ok=$((ok+1))
|
|
else
|
|
echo "x file too small ($sz bytes)"
|
|
cat "$out"
|
|
rm -f "$out"
|
|
fail=$((fail+1))
|
|
fi
|
|
else
|
|
echo "x HTTP $http_code"
|
|
head -c 300 "$out"
|
|
echo ""
|
|
rm -f "$out"
|
|
fail=$((fail+1))
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
echo ""
|
|
echo "Fertig: $ok ok, $fail Fehler"
|