Spaces:
Sleeping
Sleeping
| """ | |
| Audio Engine — voice always wins. BGM auto-ducks under voice via sidechain | |
| compression; everything gets loudness-normalized before mixdown. | |
| """ | |
| def build_audio_filter(has_voice: bool, has_bgm: bool, bgm_volume: float = 0.15) -> dict: | |
| """ | |
| Returns {"extra_inputs": [...], "filter_lines": [...], "audio_out_label": str|None} | |
| Caller is responsible for appending voice/bgm as -i inputs in the same | |
| order this expects (voice first if present, then bgm). | |
| """ | |
| lines = [] | |
| label = None | |
| if has_voice and has_bgm: | |
| lines.append("[voice]loudnorm=I=-16:TP=-1.5:LRA=11[voice_n]") | |
| lines.append(f"[bgm]volume={bgm_volume}[bgm_v]") | |
| # sidechain: bgm ducks whenever voice is present | |
| lines.append( | |
| "[bgm_v][voice_n]sidechaincompress=threshold=0.05:ratio=8:attack=5:release=300[bgm_duck]" | |
| ) | |
| lines.append("[voice_n][bgm_duck]amix=inputs=2:duration=first:dropout_transition=2[aout]") | |
| label = "aout" | |
| elif has_voice: | |
| lines.append("[voice]loudnorm=I=-16:TP=-1.5:LRA=11[aout]") | |
| label = "aout" | |
| elif has_bgm: | |
| lines.append(f"[bgm]volume={bgm_volume},loudnorm=I=-18:TP=-1.5:LRA=11[aout]") | |
| label = "aout" | |
| return {"filter_lines": lines, "audio_out_label": label} | |