feat: audio_edit_filters helper + optional -af chain on build_audio_clip_command

This commit is contained in:
2026-07-02 14:09:14 +02:00
parent 8f18c7a817
commit f584e54a8c
2 changed files with 53 additions and 2 deletions
+28 -2
View File
@@ -201,12 +201,37 @@ def probe_duration(path: str) -> float | None:
return None
def audio_edit_filters(duration: float, fade_in: float = 0.0,
fade_out: float = 0.0, normalize: bool = False,
gain_db: float = 0.0) -> list[str]:
"""Compose an ffmpeg -af chain for the non-destructive audio edits.
Trim is handled by the caller (it adjusts start/duration), so only
fade / normalize / gain appear here. Returns [] when nothing is set, so
the extract command stays byte-identical to the un-edited case."""
chain: list[str] = []
if fade_in > 0:
chain.append(f"afade=t=in:st=0:d={fade_in}")
if fade_out > 0:
st = round(max(0.0, duration - fade_out), 3)
chain.append(f"afade=t=out:st={st}:d={fade_out}")
if normalize:
# single-pass loudnorm (EBU R128 default target); fine for quick normalize
chain.append("loudnorm")
if gain_db != 0.0:
chain.append(f"volume={gain_db}dB")
return chain
def build_audio_clip_command(input_path: str, start: float, duration: float,
out_path: str) -> list[str]:
out_path: str,
filters: list[str] | None = None) -> list[str]:
"""ffmpeg command to extract exactly *duration* seconds of audio starting
at *start*, re-encoded per *out_path*'s extension (wav/mp3/flac/…)."""
at *start*, re-encoded per *out_path*'s extension (wav/mp3/flac/…).
*filters* (if any) are joined into a single -af chain."""
ext = os.path.splitext(out_path)[1].lower()
codec = _AUDIO_CODEC_BY_EXT.get(ext, [])
af = ["-af", ",".join(filters)] if filters else []
return [
_bin("ffmpeg"), "-y",
"-ss", str(start),
@@ -214,6 +239,7 @@ def build_audio_clip_command(input_path: str, start: float, duration: float,
"-t", str(duration),
"-vn",
*codec,
*af,
out_path,
]