"""Prepare the licensed daytime riverside ambience used by exploration.""" from __future__ import annotations import argparse import os from pathlib import Path import shutil import subprocess SOURCE_URL = ( "https://pixabay.com/sound-effects/" "nature-stream-water-with-birds-459511/" ) TARGET_DURATION_SECONDS = 32 SOURCE_OFFSET_SECONDS = 7 LOOP_CROSSFADE_SECONDS = 2 def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser() parser.add_argument("--input", required=True, type=Path) parser.add_argument("--output", required=True, type=Path) return parser.parse_args() def main() -> None: args = parse_args() source_path = args.input.resolve() output_path = args.output.resolve() if not source_path.is_file(): raise FileNotFoundError(source_path) ffmpeg = os.environ.get("FFMPEG_PATH") or shutil.which("ffmpeg") if not ffmpeg: raise RuntimeError("ffmpeg is required to build the ambience track.") output_path.parent.mkdir(parents=True, exist_ok=True) loop_end = SOURCE_OFFSET_SECONDS + TARGET_DURATION_SECONDS head_end = SOURCE_OFFSET_SECONDS + LOOP_CROSSFADE_SECONDS body_start = head_end tail_start = loop_end tail_end = loop_end + LOOP_CROSSFADE_SECONDS filter_graph = ( "[0:a]asplit=3[tailSource][headSource][bodySource];" f"[tailSource]atrim=start={tail_start}:end={tail_end}," f"asetpts=PTS-STARTPTS,afade=t=out:st=0:" f"d={LOOP_CROSSFADE_SECONDS}[tail];" f"[headSource]atrim=start={SOURCE_OFFSET_SECONDS}:end={head_end}," f"asetpts=PTS-STARTPTS,afade=t=in:st=0:" f"d={LOOP_CROSSFADE_SECONDS}[head];" "[tail][head]amix=inputs=2:normalize=0:duration=first[seam];" f"[bodySource]atrim=start={body_start}:end={loop_end}," "asetpts=PTS-STARTPTS[body];" "[seam][body]concat=n=2:v=0:a=1," "loudnorm=I=-24:TP=-3:LRA=7[out]" ) command = [ ffmpeg, "-hide_banner", "-loglevel", "error", "-y", "-i", str(source_path), "-filter_complex", filter_graph, "-map", "[out]", "-ar", "44100", "-ac", "2", "-codec:a", "libmp3lame", "-b:a", "128k", "-metadata", "title=Riverside Village Day Ambience", "-metadata", "artist=loswin23", "-metadata", ( "comment=Derived from Stream Water with Birds; " f"Pixabay Content License; {SOURCE_URL}" ), str(output_path), ] subprocess.run(command, check=True) if output_path.stat().st_size <= 0: raise RuntimeError(f"Empty ambience output: {output_path}") print( f"Built {output_path} ({TARGET_DURATION_SECONDS}s target, " f"{output_path.stat().st_size} bytes)." ) if __name__ == "__main__": main()