Files
heros_web/scripts/build-riverside-day-ambience.py

102 lines
2.9 KiB
Python

"""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()