feat: add second-victory relief exploration
This commit is contained in:
101
scripts/build-riverside-day-ambience.py
Normal file
101
scripts/build-riverside-day-ambience.py
Normal file
@@ -0,0 +1,101 @@
|
||||
"""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()
|
||||
Reference in New Issue
Block a user