From cd5f224e379f3feefc95e338ec50674f976e2e89 Mon Sep 17 00:00:00 2001 From: Ritiek Malhotra Date: Mon, 18 May 2020 14:01:01 +0530 Subject: [PATCH] Bugfix: -o m4a would fail [Fixes #720] In FFmpeg, a given encoding may not always point to the same format string. --- spotdl/encode/encode_base.py | 16 ++++++++++++++++ spotdl/encode/encoders/ffmpeg.py | 2 +- spotdl/encode/encoders/tests/test_ffmpeg.py | 6 +++--- spotdl/encode/tests/test_encode_base.py | 9 +++++++++ spotdl/metadata/providers/youtube.py | 3 ++- 5 files changed, 31 insertions(+), 5 deletions(-) diff --git a/spotdl/encode/encode_base.py b/spotdl/encode/encode_base.py index e033d4b..6add514 100644 --- a/spotdl/encode/encode_base.py +++ b/spotdl/encode/encode_base.py @@ -21,6 +21,13 @@ from spotdl.encode.exceptions import EncoderNotFoundError """ +_TARGET_FORMATS_FROM_ENCODING = { + "m4a": "mp4", + "mp3": "mp3", + "opus": "opus", + "flac": "flac" +} + class EncoderBase(ABC): """ @@ -44,6 +51,7 @@ class EncoderBase(ABC): self.encoder_path = encoder_path self._loglevel = loglevel self._additional_arguments = additional_arguments + self._target_formats_from_encoding = _TARGET_FORMATS_FROM_ENCODING def set_argument(self, argument): """ @@ -94,6 +102,14 @@ class EncoderBase(ABC): """ pass + def target_format_from_encoding(self, encoding): + """ + This method generates the target stream format from given + input encoding. + """ + target_format = self._target_formats_from_encoding[encoding] + return target_format + def re_encode_from_stdin(self, input_encoding, target_path): """ This method must invoke the encoder to encode stdin to a diff --git a/spotdl/encode/encoders/ffmpeg.py b/spotdl/encode/encoders/ffmpeg.py index b34ba07..c511383 100644 --- a/spotdl/encode/encoders/ffmpeg.py +++ b/spotdl/encode/encoders/ffmpeg.py @@ -76,7 +76,7 @@ class EncoderFFmpeg(EncoderBase): + ["-i", input_path] \ + arguments.split() \ + self._additional_arguments \ - + ["-f", target_encoding] \ + + ["-f", self.target_format_from_encoding(target_encoding)] \ + [target_file] return command diff --git a/spotdl/encode/encoders/tests/test_ffmpeg.py b/spotdl/encode/encoders/tests/test_ffmpeg.py index d44ce82..cb49767 100644 --- a/spotdl/encode/encoders/tests/test_ffmpeg.py +++ b/spotdl/encode/encoders/tests/test_ffmpeg.py @@ -48,7 +48,7 @@ class TestEncodingDefaults: '-acodec', 'copy', '-b:a', '192k', '-vn', - '-f', 'm4a', + '-f', 'mp4', target_path ] return command @@ -112,7 +112,7 @@ class TestEncodingInDebugMode: '-acodec', 'copy', '-b:a', '192k', '-vn', - '-f', 'm4a', + '-f', 'mp4', target_path ] return command @@ -180,7 +180,7 @@ class TestEncodingAndTrimSilence: '-b:a', '192k', '-vn', '-af', 'silenceremove=start_periods=1', - '-f', 'm4a', + '-f', 'mp4', target_path ] return command diff --git a/spotdl/encode/tests/test_encode_base.py b/spotdl/encode/tests/test_encode_base.py index 46d00bc..8c58bdb 100644 --- a/spotdl/encode/tests/test_encode_base.py +++ b/spotdl/encode/tests/test_encode_base.py @@ -86,3 +86,12 @@ class TestMethods: def test_encoder_not_found_error(self): with pytest.raises(EncoderNotFoundError): self.EncoderKid("/a/nonexistent/path", "0", []) + + @pytest.mark.parametrize("encoding, target_format", [ + ("m4a", "mp4"), + ("mp3", "mp3"), + ("opus", "opus"), + ("flac", "flac"), + ]) + def test_target_format_from_encoding(self, encoderkid, encoding, target_format): + assert encoderkid.target_format_from_encoding(encoding) == target_format diff --git a/spotdl/metadata/providers/youtube.py b/spotdl/metadata/providers/youtube.py index a7fc453..5a4bb70 100644 --- a/spotdl/metadata/providers/youtube.py +++ b/spotdl/metadata/providers/youtube.py @@ -138,6 +138,7 @@ class YouTubeStreams(StreamsBase): self.all = [] for stream in audiostreams: + encoding = "m4a" if "mp4a" in stream.audio_codec else stream.audio_codec standard_stream = { # Store only the integer part for bitrate. For example # the given bitrate would be "192kbps", we store only @@ -145,7 +146,7 @@ class YouTubeStreams(StreamsBase): "bitrate": int(stream.abr[:-4]), "connection": None, "download_url": stream.url, - "encoding": stream.audio_codec, + "encoding": encoding, "filesize": None, } establish_connection = threading.Thread(