diff --git a/README.md b/README.md index ed18dd3..d3912db 100644 --- a/README.md +++ b/README.md @@ -295,6 +295,8 @@ For more information on the options (`[options]`) available, run `ffmpeg-normali Will use input sample rate by default, except for EBU normalization, which will change the input sample rate to 192 kHz. +- `-ac`, `--audio-channels`: Set the number of audio channels. If not specified, the input channel layout will be used. This is equivalent to `-ac` in ffmpeg. + - `-koa, --keep-original-audio`: Copy original, non-normalized audio streams to output file - `-prf PRE_FILTER, --pre-filter PRE_FILTER`: Add an audio filter chain before applying normalization. diff --git a/ffmpeg_normalize/__main__.py b/ffmpeg_normalize/__main__.py index f45e6b4..b589937 100644 --- a/ffmpeg_normalize/__main__.py +++ b/ffmpeg_normalize/__main__.py @@ -303,6 +303,17 @@ def create_parser() -> argparse.ArgumentParser: """ ), ) + group_acodec.add_argument( + "-ac", + "--audio-channels", + type=int, + help=textwrap.dedent( + """\ + Set the number of audio channels. + If not specified, the input channel layout will be used. + """ + ), + ) group_acodec.add_argument( "-koa", "--keep-original-audio", @@ -506,6 +517,7 @@ def _split_options(opts: str) -> list[str]: audio_codec=cli_args.audio_codec, audio_bitrate=cli_args.audio_bitrate, sample_rate=cli_args.sample_rate, + audio_channels=cli_args.audio_channels, keep_original_audio=cli_args.keep_original_audio, pre_filter=cli_args.pre_filter, post_filter=cli_args.post_filter, diff --git a/ffmpeg_normalize/_ffmpeg_normalize.py b/ffmpeg_normalize/_ffmpeg_normalize.py index 048bead..a1d3caa 100644 --- a/ffmpeg_normalize/_ffmpeg_normalize.py +++ b/ffmpeg_normalize/_ffmpeg_normalize.py @@ -63,6 +63,7 @@ class FFmpegNormalize: audio_codec (str, optional): Audio codec. Defaults to "pcm_s16le". audio_bitrate (float, optional): Audio bitrate. Defaults to None. sample_rate (int, optional): Sample rate. Defaults to None. + audio_channels (int | None, optional): Audio channels. Defaults to None. keep_original_audio (bool, optional): Keep original audio. Defaults to False. pre_filter (str, optional): Pre filter. Defaults to None. post_filter (str, optional): Post filter. Defaults to None. @@ -98,6 +99,7 @@ def __init__( audio_codec: str = "pcm_s16le", audio_bitrate: float | None = None, sample_rate: float | int | None = None, + audio_channels: int | None = None, keep_original_audio: bool = False, pre_filter: str | None = None, post_filter: str | None = None, @@ -170,6 +172,7 @@ def __init__( self.dual_mono = dual_mono self.dynamic = dynamic self.sample_rate = None if sample_rate is None else int(sample_rate) + self.audio_channels = None if audio_channels is None else int(audio_channels) self.audio_codec = audio_codec self.audio_bitrate = audio_bitrate diff --git a/ffmpeg_normalize/_media_file.py b/ffmpeg_normalize/_media_file.py index c64d1a3..f682818 100644 --- a/ffmpeg_normalize/_media_file.py +++ b/ffmpeg_normalize/_media_file.py @@ -355,6 +355,8 @@ def _second_pass(self) -> Iterator[float]: cmd.extend(["-b:a", str(self.ffmpeg_normalize.audio_bitrate)]) if self.ffmpeg_normalize.sample_rate: cmd.extend(["-ar", str(self.ffmpeg_normalize.sample_rate)]) + if self.ffmpeg_normalize.audio_channels: + cmd.extend(["-ac", str(self.ffmpeg_normalize.audio_channels)]) # ... and subtitles if not self.ffmpeg_normalize.subtitle_disable: diff --git a/test/test.py b/test/test.py index 11dec8e..2b08f94 100644 --- a/test/test.py +++ b/test/test.py @@ -460,3 +460,18 @@ def test_quiet(self): ["test/test.mp4", "-ext", "wav", "-vn", "-f", "q"] ) assert "only supports one stream" not in stderr + + def test_audio_channels(self): + ffmpeg_normalize_call( + ["test/test.mp4", "-ac", "1", "-o", "normalized/test.wav"] + ) + assert os.path.isfile("normalized/test.wav") + stream_info = _get_stream_info("normalized/test.wav")[0] + assert stream_info["channels"] == 1 + + ffmpeg_normalize_call( + ["test/test.mp4", "-ac", "2", "-o", "normalized/test2.wav"] + ) + assert os.path.isfile("normalized/test2.wav") + stream_info = _get_stream_info("normalized/test2.wav")[0] + assert stream_info["channels"] == 2