Download audio from URL, trim to DURATION_S, normalize, resample to OGG.
(
ffmpeg: str, url: str, start: str, output: Path, cache_dir: Path
)
| 110 | |
| 111 | |
| 112 | def download_and_trim( |
| 113 | ffmpeg: str, url: str, start: str, output: Path, cache_dir: Path |
| 114 | ) -> bool: |
| 115 | """Download audio from URL, trim to DURATION_S, normalize, resample to OGG.""" |
| 116 | # Cache the raw download |
| 117 | url_hash = hashlib.md5(url.encode()).hexdigest()[:12] |
| 118 | cached = cache_dir / f"raw_{url_hash}.mp3" |
| 119 | |
| 120 | if not cached.exists(): |
| 121 | print(f" Downloading {url[:80]}...") |
| 122 | try: |
| 123 | import urllib.request |
| 124 | |
| 125 | urllib.request.urlretrieve(url, str(cached)) |
| 126 | except KeyboardInterrupt as ki: |
| 127 | import _thread |
| 128 | |
| 129 | _thread.interrupt_main() |
| 130 | raise SystemExit(1) from ki |
| 131 | except Exception as e: |
| 132 | print(f" Download failed: {e}", file=sys.stderr) |
| 133 | return False |
| 134 | |
| 135 | # Trim + normalize + resample + encode |
| 136 | run_ffmpeg( |
| 137 | ffmpeg, |
| 138 | [ |
| 139 | "-ss", |
| 140 | start, |
| 141 | "-t", |
| 142 | str(DURATION_S), |
| 143 | "-i", |
| 144 | str(cached), |
| 145 | "-af", |
| 146 | f"loudnorm=I=-10:LRA=7:TP=-1,aresample={SAMPLE_RATE}", |
| 147 | "-ac", |
| 148 | str(CHANNELS), |
| 149 | "-c:a", |
| 150 | "libvorbis", |
| 151 | "-b:a", |
| 152 | OGG_BITRATE, |
| 153 | str(output), |
| 154 | ], |
| 155 | f"Processing -> {output.name}", |
| 156 | ) |
| 157 | return True |
| 158 | |
| 159 | |
| 160 | def generate_synthetic_stem(ffmpeg: str, stem_type: str, output: Path) -> None: |
no test coverage detected