mirror of
				https://github.com/KevinMidboe/spotify-downloader.git
				synced 2025-10-29 18:00:15 +00:00 
			
		
		
		
	Accept additional command-line options
This commit is contained in:
		| @@ -16,12 +16,16 @@ def match_arguments(arguments): | |||||||
|                 track_file=arguments.list |                 track_file=arguments.list | ||||||
|             ) |             ) | ||||||
|         else: |         else: | ||||||
|             list_dl = downloader.ListDownloader( |             command_line.helpers.download_tracks_from_file( | ||||||
|                 tracks_file=arguments.list, |                 arguments.list, | ||||||
|                 skip_file=arguments.skip, |                 arguments, | ||||||
|                 write_successful_file=arguments.write_successful, |  | ||||||
|             ) |             ) | ||||||
|             list_dl.download_list() |             # list_dl = downloader.ListDownloader( | ||||||
|  |             #     tracks_file=arguments.list, | ||||||
|  |             #     skip_file=arguments.skip, | ||||||
|  |             #     write_successful_file=arguments.write_successful, | ||||||
|  |             # ) | ||||||
|  |             # list_dl.download_list() | ||||||
|     elif arguments.playlist: |     elif arguments.playlist: | ||||||
|         spotify_tools.write_playlist( |         spotify_tools.write_playlist( | ||||||
|             playlist_url=arguments.playlist, text_file=arguments.write_to |             playlist_url=arguments.playlist, text_file=arguments.write_to | ||||||
|   | |||||||
| @@ -134,6 +134,7 @@ def get_arguments(argv=None, to_merge=True): | |||||||
|         "-e", |         "-e", | ||||||
|         "--encoder", |         "--encoder", | ||||||
|         default=config["encoder"], |         default=config["encoder"], | ||||||
|  |         choices={"ffmpeg", "avconv", "null"}, | ||||||
|         help="use this encoder for conversion", |         help="use this encoder for conversion", | ||||||
|     ) |     ) | ||||||
|     parser.add_argument( |     parser.add_argument( | ||||||
| @@ -145,21 +146,29 @@ def get_arguments(argv=None, to_merge=True): | |||||||
|     parser.add_argument( |     parser.add_argument( | ||||||
|         "--overwrite", |         "--overwrite", | ||||||
|         default=config["overwrite"], |         default=config["overwrite"], | ||||||
|         help="change the overwrite policy", |  | ||||||
|         choices={"prompt", "force", "skip"}, |         choices={"prompt", "force", "skip"}, | ||||||
|  |         help="change the overwrite policy", | ||||||
|  |     ) | ||||||
|  |     parser.add_argument( | ||||||
|  |         "-q", | ||||||
|  |         "--quality", | ||||||
|  |         default=config["quality"], | ||||||
|  |         choices={"best", "worst"}, | ||||||
|  |         help="preferred audio quality", | ||||||
|     ) |     ) | ||||||
|     parser.add_argument( |     parser.add_argument( | ||||||
|         "-i", |         "-i", | ||||||
|         "--input-ext", |         "--input-ext", | ||||||
|         default=config["input-ext"], |         default=config["input-ext"], | ||||||
|         help="preferred input format 'm4a' or 'webm' (Opus)", |         choices={"automatic", "m4a", "opus"}, | ||||||
|         choices={"m4a", "webm"}, |         help="preferred input format", | ||||||
|     ) |     ) | ||||||
|     parser.add_argument( |     parser.add_argument( | ||||||
|         "-o", |         "-o", | ||||||
|         "--output-ext", |         "--output-ext", | ||||||
|         default=config["output-ext"], |         default=config["output-ext"], | ||||||
|         help="preferred output format: 'mp3', 'm4a' (AAC), 'flac', etc.", |         choices={"mp3", "m4a", "flac"}, | ||||||
|  |         help="preferred output format", | ||||||
|     ) |     ) | ||||||
|     parser.add_argument( |     parser.add_argument( | ||||||
|         "--write-to", |         "--write-to", | ||||||
| @@ -310,7 +319,7 @@ def run_errands(parser, parsed): | |||||||
|     if not encoder_exists: |     if not encoder_exists: | ||||||
|         # log.warn("Specified encoder () was not found. Will not encode to specified " |         # log.warn("Specified encoder () was not found. Will not encode to specified " | ||||||
|         #          "output format".format(parsed.encoder)) |         #          "output format".format(parsed.encoder)) | ||||||
|         parsed.output_ext = parsed.input_ext |         parsed.encoder = "null" | ||||||
|  |  | ||||||
|     song_parameter_passed = parsed.song is not None and parsed.tracks is None |     song_parameter_passed = parsed.song is not None and parsed.tracks is None | ||||||
|     if song_parameter_passed: |     if song_parameter_passed: | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| from spotdl.metadata.providers import ProviderSpotify | from spotdl.metadata.providers import ProviderSpotify | ||||||
| from spotdl.metadata.providers import ProviderYouTube | from spotdl.metadata.providers import ProviderYouTube | ||||||
| from spotdl.metadata.embedders import EmbedderDefault | from spotdl.metadata.embedders import EmbedderDefault | ||||||
|  | from spotdl.encode.encoders import EncoderFFmpeg, EncoderAvconv | ||||||
| from spotdl.lyrics.providers import LyricWikia | from spotdl.lyrics.providers import LyricWikia | ||||||
| from spotdl.lyrics.providers import Genius | from spotdl.lyrics.providers import Genius | ||||||
|  |  | ||||||
| @@ -8,6 +9,7 @@ from spotdl.track import Track | |||||||
|  |  | ||||||
| import spotdl.util | import spotdl.util | ||||||
|  |  | ||||||
|  | import os | ||||||
| import urllib.request | import urllib.request | ||||||
| import threading | import threading | ||||||
|  |  | ||||||
| @@ -46,34 +48,57 @@ def download_track_from_metadata(metadata, arguments): | |||||||
|     track = Track(metadata, cache_albumart=(not arguments.no_metadata)) |     track = Track(metadata, cache_albumart=(not arguments.no_metadata)) | ||||||
|     # log.info(log_fmt) |     # log.info(log_fmt) | ||||||
|  |  | ||||||
|  |     stream = metadata["streams"].get( | ||||||
|  |         quality=arguments.quality, | ||||||
|  |         preftype=arguments.input_ext, | ||||||
|  |     ) | ||||||
|  |     # log.info(stream) | ||||||
|  |  | ||||||
|  |     Encoder = { | ||||||
|  |         "ffmpeg": EncoderFFmpeg, | ||||||
|  |         "avconv": EncoderAvconv, | ||||||
|  |     }.get(arguments.encoder) | ||||||
|  |  | ||||||
|  |     if Encoder is None: | ||||||
|  |         output_extension = stream["encoding"] | ||||||
|  |     else: | ||||||
|  |         output_extension = arguments.output_ext | ||||||
|  |  | ||||||
|     filename = spotdl.util.format_string( |     filename = spotdl.util.format_string( | ||||||
|         arguments.file_format, |         arguments.file_format, | ||||||
|         metadata, |         metadata, | ||||||
|         output_extension=arguments.output_ext |         output_extension=output_extension | ||||||
|     ) |     ) | ||||||
|  |     # log.info(filename) | ||||||
|  |  | ||||||
|     if arguments.dry_run: |     to_skip = arguments.dry_run | ||||||
|         return |     if not to_skip and os.path.isfile(filename): | ||||||
|  |         if arguments.overwrite == "force": | ||||||
|     if os.path.isfile(filename): |             to_skip = False | ||||||
|         if arguments.overwrite == "skip": |  | ||||||
|             to_skip = True |  | ||||||
|         elif arguments.overwrite == "prompt": |         elif arguments.overwrite == "prompt": | ||||||
|             to_skip = not input("overwrite? (y/N)").lower() == "y" |             to_skip = not input("overwrite? (y/N)").lower() == "y" | ||||||
|  |         else: | ||||||
|  |             to_skip = True | ||||||
|  |  | ||||||
|     if to_skip: |     if to_skip: | ||||||
|         return |         return | ||||||
|  |  | ||||||
|     if arguments.no_encode: |     if Encoder is None: | ||||||
|         track.download(filename) |         track.download(stream, filename) | ||||||
|     else: |     else: | ||||||
|         track.download_while_re_encoding( |         track.download_while_re_encoding( | ||||||
|  |             stream, | ||||||
|             filename, |             filename, | ||||||
|             target_encoding=arguments.output_ext |             target_encoding=output_extension, | ||||||
|  |             encoder=Encoder() | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     if not arguments.no_metadata: |     if not arguments.no_metadata: | ||||||
|         track.apply_metadata(filename, encoding=arguments.output_ext) |         try: | ||||||
|  |             track.apply_metadata(filename, encoding=output_extension) | ||||||
|  |         except TypeError: | ||||||
|  |             # log.warning("Cannot write metadata to given file") | ||||||
|  |             pass | ||||||
|  |  | ||||||
|  |  | ||||||
| def download_tracks_from_file(path, arguments): | def download_tracks_from_file(path, arguments): | ||||||
| @@ -142,9 +167,9 @@ def download_tracks_from_file(path, arguments): | |||||||
|             # log.warning("Failed. Will retry after other songs\n") |             # log.warning("Failed. Will retry after other songs\n") | ||||||
|             tracks.append(current_track) |             tracks.append(current_track) | ||||||
|         else: |         else: | ||||||
|             # TODO: CONFIG.YML |             if arguments.write_successful: | ||||||
|             #       Write track to config.write_sucessful |                 with open(arguments.write_successful, "a") as fout: | ||||||
|             pass |                     fout.write(current_track) | ||||||
|         finally: |         finally: | ||||||
|             with open(path, "w") as fout: |             with open(path, "w") as fout: | ||||||
|                 fout.writelines(tracks) |                 fout.writelines(tracks) | ||||||
|   | |||||||
| @@ -14,7 +14,8 @@ DEFAULT_CONFIGURATION = { | |||||||
|         "encoder": "ffmpeg", |         "encoder": "ffmpeg", | ||||||
|         "directory": spotdl.util.get_music_dir(), |         "directory": spotdl.util.get_music_dir(), | ||||||
|         "overwrite": "prompt", |         "overwrite": "prompt", | ||||||
|         "input-ext": "m4a", |         "quality": "best", | ||||||
|  |         "input-ext": "automatic", | ||||||
|         "output-ext": "mp3", |         "output-ext": "mp3", | ||||||
|         "write-to": None, |         "write-to": None, | ||||||
|         "trim-silence": False, |         "trim-silence": False, | ||||||
| @@ -22,8 +23,8 @@ DEFAULT_CONFIGURATION = { | |||||||
|         "dry-run": False, |         "dry-run": False, | ||||||
|         "music-videos-only": False, |         "music-videos-only": False, | ||||||
|         "no-spaces": False, |         "no-spaces": False, | ||||||
|         "file-format": "{artist} - {track_name}.{output_ext}", |         "file-format": "{artist} - {track-name}.{output-ext}", | ||||||
|         "search-format": "{artist} - {track_name} lyrics", |         "search-format": "{artist} - {track-name} lyrics", | ||||||
|         "youtube-api-key": None, |         "youtube-api-key": None, | ||||||
|         "skip": None, |         "skip": None, | ||||||
|         "write-successful": None, |         "write-successful": None, | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ from spotdl.encode.exceptions import FFmpegNotFoundError | |||||||
| RULES = { | RULES = { | ||||||
|     "m4a": { |     "m4a": { | ||||||
|         "mp3": "-codec:v copy -codec:a libmp3lame -ar 48000", |         "mp3": "-codec:v copy -codec:a libmp3lame -ar 48000", | ||||||
|         "webm": "-codec:a libopus -vbr on", |         "opus": "-codec:a libopus -vbr on", | ||||||
|         "m4a": "-acodec copy", |         "m4a": "-acodec copy", | ||||||
|         "flac": "-codec:a flac -ar 48000", |         "flac": "-codec:a flac -ar 48000", | ||||||
|     }, |     }, | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ class TestEncodingDefaults: | |||||||
|  |  | ||||||
|     @pytest.mark.parametrize("files, expected_command", [ |     @pytest.mark.parametrize("files, expected_command", [ | ||||||
|         (("test.m4a", "test.mp3"), encode_command("test.m4a", "test.mp3")), |         (("test.m4a", "test.mp3"), encode_command("test.m4a", "test.mp3")), | ||||||
|         (("abc.m4a", "cba.webm"), encode_command("abc.m4a", "cba.webm")), |         (("abc.m4a", "cba.opus"), encode_command("abc.m4a", "cba.opus")), | ||||||
|         (("bla bla.m4a", "ble ble.m4a"), encode_command("bla bla.m4a", "ble ble.m4a")), |         (("bla bla.m4a", "ble ble.m4a"), encode_command("bla bla.m4a", "ble ble.m4a")), | ||||||
|         (("😛.m4a", "• tongue.flac"), encode_command("😛.m4a", "• tongue.flac")), |         (("😛.m4a", "• tongue.flac"), encode_command("😛.m4a", "• tongue.flac")), | ||||||
|     ]) |     ]) | ||||||
| @@ -47,7 +47,7 @@ class TestEncodingInDebugMode: | |||||||
|  |  | ||||||
|     @pytest.mark.parametrize("files, expected_command", [ |     @pytest.mark.parametrize("files, expected_command", [ | ||||||
|         (("test.m4a", "test.mp3"), debug_encode_command("test.m4a", "test.mp3")), |         (("test.m4a", "test.mp3"), debug_encode_command("test.m4a", "test.mp3")), | ||||||
|         (("abc.m4a", "cba.webm"), debug_encode_command("abc.m4a", "cba.webm")), |         (("abc.m4a", "cba.opus"), debug_encode_command("abc.m4a", "cba.opus")), | ||||||
|         (("bla bla.m4a", "ble ble.m4a"), debug_encode_command("bla bla.m4a", "ble ble.m4a")), |         (("bla bla.m4a", "ble ble.m4a"), debug_encode_command("bla bla.m4a", "ble ble.m4a")), | ||||||
|         (("😛.m4a", "• tongue.flac"), debug_encode_command("😛.m4a", "• tongue.flac")), |         (("😛.m4a", "• tongue.flac"), debug_encode_command("😛.m4a", "• tongue.flac")), | ||||||
|     ]) |     ]) | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ class TestEncodingDefaults: | |||||||
|         ] |         ] | ||||||
|         return command |         return command | ||||||
|  |  | ||||||
|     def m4a_to_webm_encoder(input_path, target_path): |     def m4a_to_opus_encoder(input_path, target_path): | ||||||
|         command = [ |         command = [ | ||||||
|             'ffmpeg', '-y', '-nostdin', '-hide_banner', '-nostats', '-v', 'panic', |             'ffmpeg', '-y', '-nostdin', '-hide_banner', '-nostats', '-v', 'panic', | ||||||
|             '-i', input_path, |             '-i', input_path, | ||||||
| @@ -36,7 +36,7 @@ class TestEncodingDefaults: | |||||||
|             '-vbr', 'on', |             '-vbr', 'on', | ||||||
|             '-b:a', '192k', |             '-b:a', '192k', | ||||||
|             '-vn', |             '-vn', | ||||||
|             '-f', 'webm', |             '-f', 'opus', | ||||||
|             target_path |             target_path | ||||||
|         ] |         ] | ||||||
|         return command |         return command | ||||||
| @@ -68,7 +68,7 @@ class TestEncodingDefaults: | |||||||
|  |  | ||||||
|     @pytest.mark.parametrize("files, expected_command", [ |     @pytest.mark.parametrize("files, expected_command", [ | ||||||
|         (("test.m4a", "test.mp3"), m4a_to_mp3_encoder("test.m4a", "test.mp3")), |         (("test.m4a", "test.mp3"), m4a_to_mp3_encoder("test.m4a", "test.mp3")), | ||||||
|         (("abc.m4a", "cba.webm"), m4a_to_webm_encoder("abc.m4a", "cba.webm")), |         (("abc.m4a", "cba.opus"), m4a_to_opus_encoder("abc.m4a", "cba.opus")), | ||||||
|         (("bla bla.m4a", "ble ble.m4a"), m4a_to_m4a_encoder("bla bla.m4a", "ble ble.m4a")), |         (("bla bla.m4a", "ble ble.m4a"), m4a_to_m4a_encoder("bla bla.m4a", "ble ble.m4a")), | ||||||
|         (("😛.m4a", "• tongue.flac"), m4a_to_flac_encoder("😛.m4a", "• tongue.flac")), |         (("😛.m4a", "• tongue.flac"), m4a_to_flac_encoder("😛.m4a", "• tongue.flac")), | ||||||
|     ]) |     ]) | ||||||
| @@ -92,7 +92,7 @@ class TestEncodingInDebugMode: | |||||||
|         ] |         ] | ||||||
|         return command |         return command | ||||||
|  |  | ||||||
|     def m4a_to_webm_encoder_with_debug(input_path, target_path): |     def m4a_to_opus_encoder_with_debug(input_path, target_path): | ||||||
|         command = [ |         command = [ | ||||||
|             'ffmpeg', '-y', '-nostdin', '-loglevel', 'debug', |             'ffmpeg', '-y', '-nostdin', '-loglevel', 'debug', | ||||||
|             '-i', input_path, |             '-i', input_path, | ||||||
| @@ -100,7 +100,7 @@ class TestEncodingInDebugMode: | |||||||
|             '-vbr', 'on', |             '-vbr', 'on', | ||||||
|             '-b:a', '192k', |             '-b:a', '192k', | ||||||
|             '-vn', |             '-vn', | ||||||
|             '-f', 'webm', |             '-f', 'opus', | ||||||
|              target_path |              target_path | ||||||
|         ] |         ] | ||||||
|         return command |         return command | ||||||
| @@ -132,7 +132,7 @@ class TestEncodingInDebugMode: | |||||||
|  |  | ||||||
|     @pytest.mark.parametrize("files, expected_command", [ |     @pytest.mark.parametrize("files, expected_command", [ | ||||||
|         (("test.m4a", "test.mp3"), m4a_to_mp3_encoder_with_debug("test.m4a", "test.mp3")), |         (("test.m4a", "test.mp3"), m4a_to_mp3_encoder_with_debug("test.m4a", "test.mp3")), | ||||||
|         (("abc.m4a", "cba.webm"), m4a_to_webm_encoder_with_debug("abc.m4a", "cba.webm")), |         (("abc.m4a", "cba.opus"), m4a_to_opus_encoder_with_debug("abc.m4a", "cba.opus")), | ||||||
|         (("bla bla.m4a", "ble ble.m4a"), m4a_to_m4a_encoder_with_debug("bla bla.m4a", "ble ble.m4a")), |         (("bla bla.m4a", "ble ble.m4a"), m4a_to_m4a_encoder_with_debug("bla bla.m4a", "ble ble.m4a")), | ||||||
|         (("😛.m4a", "• tongue.flac"), m4a_to_flac_encoder_with_debug("😛.m4a", "• tongue.flac")), |         (("😛.m4a", "• tongue.flac"), m4a_to_flac_encoder_with_debug("😛.m4a", "• tongue.flac")), | ||||||
|     ]) |     ]) | ||||||
| @@ -158,7 +158,7 @@ class TestEncodingAndTrimSilence: | |||||||
|         ] |         ] | ||||||
|         return command |         return command | ||||||
|  |  | ||||||
|     def m4a_to_webm_encoder_and_trim_silence(input_path, target_path): |     def m4a_to_opus_encoder_and_trim_silence(input_path, target_path): | ||||||
|         command = [ |         command = [ | ||||||
|             'ffmpeg', '-y', '-nostdin', '-hide_banner', '-nostats', '-v', 'panic', |             'ffmpeg', '-y', '-nostdin', '-hide_banner', '-nostats', '-v', 'panic', | ||||||
|             '-i', input_path, |             '-i', input_path, | ||||||
| @@ -167,7 +167,7 @@ class TestEncodingAndTrimSilence: | |||||||
|             '-b:a', '192k', |             '-b:a', '192k', | ||||||
|             '-vn', |             '-vn', | ||||||
|             '-af', 'silenceremove=start_periods=1', |             '-af', 'silenceremove=start_periods=1', | ||||||
|             '-f', 'webm', |             '-f', 'opus', | ||||||
|             target_path |             target_path | ||||||
|         ] |         ] | ||||||
|         return command |         return command | ||||||
| @@ -201,7 +201,7 @@ class TestEncodingAndTrimSilence: | |||||||
|  |  | ||||||
|     @pytest.mark.parametrize("files, expected_command", [ |     @pytest.mark.parametrize("files, expected_command", [ | ||||||
|         (("test.m4a", "test.mp3"), m4a_to_mp3_encoder_and_trim_silence("test.m4a", "test.mp3")), |         (("test.m4a", "test.mp3"), m4a_to_mp3_encoder_and_trim_silence("test.m4a", "test.mp3")), | ||||||
|         (("abc.m4a", "cba.webm"), m4a_to_webm_encoder_and_trim_silence("abc.m4a", "cba.webm")), |         (("abc.m4a", "cba.opus"), m4a_to_opus_encoder_and_trim_silence("abc.m4a", "cba.opus")), | ||||||
|         (("bla bla.m4a", "ble ble.m4a"), m4a_to_m4a_encoder_and_trim_silence("bla bla.m4a", "ble ble.m4a")), |         (("bla bla.m4a", "ble ble.m4a"), m4a_to_m4a_encoder_and_trim_silence("bla bla.m4a", "ble ble.m4a")), | ||||||
|         (("😛.m4a", "• tongue.flac"), m4a_to_flac_encoder_and_trim_silence("😛.m4a", "• tongue.flac")), |         (("😛.m4a", "• tongue.flac"), m4a_to_flac_encoder_and_trim_silence("😛.m4a", "• tongue.flac")), | ||||||
|     ]) |     ]) | ||||||
|   | |||||||
| @@ -77,7 +77,7 @@ class TestMethods: | |||||||
|     @pytest.mark.parametrize("filename, encoding", [ |     @pytest.mark.parametrize("filename, encoding", [ | ||||||
|         ("example.m4a", "m4a"), |         ("example.m4a", "m4a"), | ||||||
|         ("exampley.mp3", "mp3"), |         ("exampley.mp3", "mp3"), | ||||||
|         ("test 123.webm", "webm"), |         ("test 123.opus", "opus"), | ||||||
|         ("flakey.flac", "flac"), |         ("flakey.flac", "flac"), | ||||||
|     ]) |     ]) | ||||||
|     def test_get_encoding(self, encoderkid, filename, encoding): |     def test_get_encoding(self, encoderkid, filename, encoding): | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ class EmbedderBase(ABC): | |||||||
|     The subclass must define the supported media file encoding |     The subclass must define the supported media file encoding | ||||||
|     formats here using a static variable - such as: |     formats here using a static variable - such as: | ||||||
|  |  | ||||||
|     >>> supported_formats = ("mp3", "opus", "flac") |     >>> supported_formats = ("mp3", "m4a", "flac") | ||||||
|     """ |     """ | ||||||
|     supported_formats = () |     supported_formats = () | ||||||
|  |  | ||||||
| @@ -72,9 +72,9 @@ class EmbedderBase(ABC): | |||||||
|         """ |         """ | ||||||
|         raise NotImplementedError |         raise NotImplementedError | ||||||
|  |  | ||||||
|     def as_opus(self, path, metadata, cached_albumart=None): |     def as_m4a(self, path, metadata, cached_albumart=None): | ||||||
|         """ |         """ | ||||||
|         Method for opus support. This method might be defined in |         Method for m4a support. This method might be defined in | ||||||
|         a subclass. |         a subclass. | ||||||
|  |  | ||||||
|         Other methods for additional supported formats must also |         Other methods for additional supported formats must also | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ for key in M4A_TAG_PRESET.keys(): | |||||||
|  |  | ||||||
|  |  | ||||||
| class EmbedderDefault(EmbedderBase): | class EmbedderDefault(EmbedderBase): | ||||||
|     supported_formats = ("mp3", "opus", "flac") |     supported_formats = ("mp3", "m4a", "flac") | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         super().__init__() |         super().__init__() | ||||||
| @@ -102,10 +102,10 @@ class EmbedderDefault(EmbedderBase): | |||||||
|  |  | ||||||
|         audiofile.save(v2_version=3) |         audiofile.save(v2_version=3) | ||||||
|  |  | ||||||
|     def as_opus(self, path, cached_albumart=None): |     def as_m4a(self, path, metadata, cached_albumart=None): | ||||||
|         """ Embed metadata to M4A files. """ |         """ Embed metadata to M4A files. """ | ||||||
|         audiofile = MP4(path) |         audiofile = MP4(path) | ||||||
|         self._embed_basic_metadata(audiofile, metadata, "opus", preset=M4A_TAG_PRESET) |         self._embed_basic_metadata(audiofile, metadata, "m4a", preset=M4A_TAG_PRESET) | ||||||
|         if metadata["year"]: |         if metadata["year"]: | ||||||
|             audiofile[M4A_TAG_PRESET["year"]] = metadata["year"] |             audiofile[M4A_TAG_PRESET["year"]] = metadata["year"] | ||||||
|         provider = metadata["provider"] |         provider = metadata["provider"] | ||||||
|   | |||||||
| @@ -117,11 +117,27 @@ class YouTubeStreams(StreamsBase): | |||||||
|             request.add_header(*header) |             request.add_header(*header) | ||||||
|         return urllib.request.urlopen(request) |         return urllib.request.urlopen(request) | ||||||
|  |  | ||||||
|     def getbest(self): |     def get(self, quality="best", preftype="automatic"): | ||||||
|         return self.all[0] |         if quality == "best": | ||||||
|  |             return self.getbest(preftype=preftype) | ||||||
|  |         elif quality == "worst": | ||||||
|  |             return self.getworst(preftype=preftype) | ||||||
|  |         else: | ||||||
|  |             return None | ||||||
|  |  | ||||||
|     def getworst(self): |     def getbest(self, preftype="automatic"): | ||||||
|         return self.all[-1] |         if preftype == "automatic": | ||||||
|  |             return self.all[0] | ||||||
|  |         for stream in self.all: | ||||||
|  |             if stream["encoding"] == preftype: | ||||||
|  |                 return stream | ||||||
|  |  | ||||||
|  |     def getworst(self, preftype="automatic"): | ||||||
|  |         if preftype == "automatic": | ||||||
|  |             return self.all[-1] | ||||||
|  |         for stream in self.all[::-1]: | ||||||
|  |             if stream["encoding"] == preftype: | ||||||
|  |                 return stream | ||||||
|  |  | ||||||
|  |  | ||||||
| class ProviderYouTube(ProviderBase): | class ProviderYouTube(ProviderBase): | ||||||
|   | |||||||
| @@ -62,7 +62,7 @@ class TestMethods: | |||||||
|  |  | ||||||
|     @pytest.mark.parametrize("fmt_method_suffix", ( |     @pytest.mark.parametrize("fmt_method_suffix", ( | ||||||
|         "as_mp3", |         "as_mp3", | ||||||
|         "as_opus", |         "as_m4a", | ||||||
|         "as_flac", |         "as_flac", | ||||||
|     )) |     )) | ||||||
|     def test_embed_formats(self, fmt_method_suffix, embedderkid): |     def test_embed_formats(self, fmt_method_suffix, embedderkid): | ||||||
|   | |||||||
| @@ -37,9 +37,8 @@ class Track: | |||||||
|     def _calculate_total_chunks(self, filesize): |     def _calculate_total_chunks(self, filesize): | ||||||
|         return (filesize // self._chunksize) + 1 |         return (filesize // self._chunksize) + 1 | ||||||
|  |  | ||||||
|     def download_while_re_encoding(self, target_path, target_encoding=None, |     def download_while_re_encoding(self, stream, target_path, target_encoding=None, | ||||||
|                                    encoder=EncoderFFmpeg(), show_progress=True): |                                    encoder=EncoderFFmpeg(), show_progress=True): | ||||||
|         stream = self.metadata["streams"].getbest() |  | ||||||
|         total_chunks = self._calculate_total_chunks(stream["filesize"]) |         total_chunks = self._calculate_total_chunks(stream["filesize"]) | ||||||
|         process = encoder.re_encode_from_stdin( |         process = encoder.re_encode_from_stdin( | ||||||
|             stream["encoding"], |             stream["encoding"], | ||||||
| @@ -54,8 +53,7 @@ class Track: | |||||||
|         process.stdin.close() |         process.stdin.close() | ||||||
|         process.wait() |         process.wait() | ||||||
|  |  | ||||||
|     def download(self, target_path, show_progress=True): |     def download(self, stream, target_path, show_progress=True): | ||||||
|         stream = self.metadata["streams"].getbest() |  | ||||||
|         total_chunks = self._calculate_total_chunks(stream["filesize"]) |         total_chunks = self._calculate_total_chunks(stream["filesize"]) | ||||||
|         response = stream["connection"] |         response = stream["connection"] | ||||||
|         with open(target_path, "wb") as fout: |         with open(target_path, "wb") as fout: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user