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