| """Bootstrap sample audio for the demo's Sample Library. |
| |
| Strategy (per slot): |
| 1. If file already present and non-empty, leave it alone. |
| 2. For "real" slots: download a small public-domain LibriSpeech clip from |
| HuggingFace's CDN (stable URLs used in their docs for years). Trim, |
| resample to 16 kHz mono, save as PCM_16 WAV. |
| 3. If download fails, fall back to the high-quality source-filter |
| synthesizer in ``speech_synth.py`` — much better than the previous |
| formant-resonator approach. |
| 4. For "fake" slots: always synthesise (these are *meant* to be TTS-like). |
| |
| Result: the Sample Library has actually-real speech for the real slots when |
| the user has internet, gracefully degrading to plausible synthesis offline. |
| """ |
| from __future__ import annotations |
|
|
| import io |
| from pathlib import Path |
| from typing import Optional |
|
|
| import numpy as np |
| import soundfile as sf |
|
|
| from app.features.audio_preprocessor import preprocess_audio |
| from app.logging_setup import get_logger |
| from app.utils.speech_synth import ( |
| synth_real_speech, |
| synth_fake_neural_tts, |
| synth_fake_tts_commercial, |
| synth_fake_voice_clone, |
| ) |
|
|
| logger = get_logger(__name__) |
|
|
| SR = 16000 |
|
|
| |
| |
| |
| _REAL_DOWNLOAD_CANDIDATES: list[tuple[str, str]] = [ |
| ("real_news_excerpt.wav", "https://cdn-media.huggingface.co/speech_samples/sample1.flac"), |
| ("real_conversation.wav", "https://cdn-media.huggingface.co/speech_samples/sample2.flac"), |
| |
| |
| ("real_lecture.wav", "https://cdn-media.huggingface.co/speech_samples/sample1.flac"), |
| ] |
|
|
|
|
| def _try_download_speech(url: str, max_seconds: float, segment: str) -> Optional[np.ndarray]: |
| """Download → decode → trim → resample to 16 kHz mono. Returns None on failure. |
| |
| ``segment`` selects which slice to keep: |
| 'head' -> first max_seconds |
| 'mid' -> middle max_seconds |
| 'tail' -> last max_seconds |
| """ |
| try: |
| import httpx |
|
|
| with httpx.Client(timeout=15.0, follow_redirects=True) as client: |
| r = client.get(url) |
| if r.status_code != 200 or not r.content: |
| logger.warning("download %s -> HTTP %s", url, r.status_code) |
| return None |
| data = r.content |
| except Exception as exc: |
| logger.warning("download %s failed: %s", url, exc) |
| return None |
|
|
| try: |
| loaded = preprocess_audio(data, target_sr=SR, max_seconds=60.0) |
| except Exception as exc: |
| logger.warning("decode of %s failed: %s", url, exc) |
| return None |
|
|
| wav = loaded.waveform.squeeze().detach().cpu().numpy().astype(np.float32) |
| target_len = int(max_seconds * SR) |
| if wav.size <= target_len: |
| return wav |
|
|
| if segment == "head": |
| return wav[:target_len] |
| if segment == "tail": |
| return wav[-target_len:] |
| |
| start = (wav.size - target_len) // 2 |
| return wav[start : start + target_len] |
|
|
|
|
| |
| |
| |
|
|
| def ensure_sample_audios(target_dir: Path) -> int: |
| """Create any missing sample WAV files. Returns number of new files written.""" |
| target_dir.mkdir(parents=True, exist_ok=True) |
| rng = np.random.default_rng(42) |
| created = 0 |
|
|
| |
| real_segments = ["head", "head", "tail"] |
| for (filename, url), seg in zip(_REAL_DOWNLOAD_CANDIDATES, real_segments): |
| path = target_dir / filename |
| if path.exists() and path.stat().st_size > 4096: |
| continue |
| wav = _try_download_speech(url, max_seconds=4.5, segment=seg) |
| if wav is None or wav.size < SR: |
| logger.info("Falling back to synthesised real speech for %s", filename) |
| wav = synth_real_speech(seconds=4.5, rng=rng) |
| else: |
| logger.info("Downloaded real speech for %s (%.1fs)", filename, wav.size / SR) |
| sf.write(str(path), wav, SR, subtype="PCM_16") |
| created += 1 |
|
|
| |
| fake_specs = [ |
| ("fake_tts_commercial.wav", lambda r: synth_fake_tts_commercial(4.5, r)), |
| ("fake_voice_clone.wav", lambda r: synth_fake_voice_clone(4.5, r)), |
| ("fake_neural_tts.wav", lambda r: synth_fake_neural_tts(4.5, r)), |
| ] |
| for filename, gen in fake_specs: |
| path = target_dir / filename |
| if path.exists() and path.stat().st_size > 4096: |
| continue |
| wav = gen(rng) |
| sf.write(str(path), wav, SR, subtype="PCM_16") |
| logger.info("Generated fake sample: %s", filename) |
| created += 1 |
|
|
| if created: |
| logger.info("Sample audio bootstrap complete: %d new files in %s", created, target_dir) |
| return created |
|
|