Files
rustytorch/crates/models/rtx-csm/scripts/fetch_audio.sh
T
osobhandClaude Opus 4.7 7e37e45df7 rtx-csm: scripts/fetch_audio.sh — yt-dlp + ffmpeg → 24kHz mono WAV
Wrapper that pulls audio from any yt-dlp-supported URL (YouTube,
LibriVox, archive.org, podcast feeds) and converts to the 24 kHz mono
16-bit PCM format examples/audio_to_manifest ingests. Slugifies the
output filename so manifest paths stay shell-safe.

Prints the next-step audio_to_manifest command with all the right
flags (--auto-emotion-tag --use-emotion2vec --stage audiobook), so a
new user can copy-paste the printed line straight into a terminal.

Requires external tools (yt-dlp, ffmpeg); install on macOS via
`brew install yt-dlp ffmpeg`.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-04-28 08:48:02 -07:00

94 lines
2.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Fetch audio from a URL (YouTube, archive.org, LibriVox, podcast feed,
# anything yt-dlp supports) and convert to the 24 kHz mono WAV format
# our data-prep pipeline expects.
#
# Output is suitable as direct input to `examples/audio_to_manifest`.
#
# Requires: yt-dlp, ffmpeg (install via `brew install yt-dlp ffmpeg`).
#
# Usage:
# scripts/fetch_audio.sh <url> [output_dir]
#
# Examples:
# # Single LibriVox chapter
# scripts/fetch_audio.sh \
# "https://librivox.org/.../alice-in-wonderland-chapter-1.mp3" \
# /tmp/voice_corpus
#
# # YouTube talk
# scripts/fetch_audio.sh \
# "https://www.youtube.com/watch?v=XXXXXXXXX" \
# /tmp/voice_corpus
#
# # Multiple URLs from a file (one per line)
# while read url; do
# scripts/fetch_audio.sh "$url" /tmp/voice_corpus
# done < urls.txt
#
# Tips for good training audio:
# - Single dominant speaker per clip (use diarize step if mixed)
# - At least 10-30 minutes total per persona
# - Studio-quality > phone > YouTube > heavily-compressed
# - Emotional variety beats raw duration
set -euo pipefail
if [[ $# -lt 1 ]]; then
echo "usage: $0 <url> [output_dir]" >&2
exit 1
fi
URL="$1"
OUT_DIR="${2:-./fetched_audio}"
mkdir -p "$OUT_DIR"
# yt-dlp emits the title as the filename. Strip whitespace + special
# chars in a post-rename so the manifest's `wav` paths stay shell-safe.
TMP_DIR="$(mktemp -d)"
trap "rm -rf '$TMP_DIR'" EXIT
echo "→ downloading audio from: $URL"
yt-dlp \
--extract-audio \
--audio-format wav \
--audio-quality 0 \
--no-playlist \
--output "$TMP_DIR/%(title).100s.%(ext)s" \
"$URL"
# Find what we just downloaded.
SRC_WAV="$(find "$TMP_DIR" -maxdepth 1 -name '*.wav' | head -n1)"
if [[ -z "$SRC_WAV" ]]; then
echo "error: yt-dlp produced no .wav file" >&2
exit 2
fi
# Slugify the basename: lowercase, replace non-alphanumeric with `_`,
# collapse runs, trim.
BASE="$(basename "$SRC_WAV" .wav)"
SLUG="$(echo "$BASE" \
| tr '[:upper:]' '[:lower:]' \
| sed -E 's/[^a-z0-9]+/_/g; s/^_+|_+$//g')"
DST_WAV="$OUT_DIR/${SLUG}.wav"
echo "→ converting to 24 kHz mono 16-bit PCM: $DST_WAV"
ffmpeg -y -loglevel error \
-i "$SRC_WAV" \
-ac 1 -ar 24000 -sample_fmt s16 \
"$DST_WAV"
# Print duration so the user sees what they got.
DURATION="$(ffmpeg -i "$DST_WAV" 2>&1 | grep Duration | awk '{print $2}' | tr -d ',')"
SIZE_MB="$(du -m "$DST_WAV" | awk '{print $1}')"
echo
echo "✓ wrote $DST_WAV (${DURATION}, ${SIZE_MB} MB)"
echo
echo "Next step:"
echo " cargo run -p rtx-csm --release --features metal --example audio_to_manifest -- \\"
echo " --in $DST_WAV \\"
echo " --out-dir ${OUT_DIR}_manifest \\"
echo " --wavlm-sv-weights /tmp/wavlm_sv.safetensors \\"
echo " --auto-emotion-tag --use-emotion2vec --stage audiobook"