mirror of
https://github.com/KevinMidboe/spotify-downloader.git
synced 2025-10-29 18:00:15 +00:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d53a6ea471 | ||
|
|
c1b3949edb | ||
|
|
6288e3c6e5 | ||
|
|
2aa7dce4a4 | ||
|
|
b13f12f1fe | ||
|
|
19ae8fd408 | ||
|
|
89735c2bbb | ||
|
|
debe7ee902 | ||
|
|
9c97f33aa2 | ||
|
|
046e7e9d3c | ||
|
|
29b1f31a26 |
28
CHANGES.md
28
CHANGES.md
@@ -8,17 +8,41 @@ The release dates mentioned follow the format `DD-MM-YYYY`.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2.0.5] - 20-05-2020
|
||||
### Fixed
|
||||
- In some cases when using `-f` to create sub-directories from metadata, where the
|
||||
full slugified download filename and the non-slugified download directory happen
|
||||
to differ, the download would fail. The download directory will now be derived from
|
||||
filename itself so that the sub-directory name always overlaps.
|
||||
([@ritiek](https://github.com/ritiek/spotify-downloader))
|
||||
(2aa7dce4a42feb5cd3ceb9324e58da524cdb4b6f)
|
||||
|
||||
### Changed
|
||||
- Disable unneeded logs from `chardet`. ([@ritiek](https://github.com/ritiek))
|
||||
(c1b3949edb943cc21a63c34d6a01ed59e9b6536d)
|
||||
|
||||
## [2.0.4] - 19-05-2020
|
||||
### Fixed
|
||||
- Do not remove the currently downloading track from file on `KeyboardInterrupt`
|
||||
when `--list` is passed. ([@ritiek](https://github.com/ritiek/spotify-downloader)) (#722)
|
||||
- Failure on invoking spotdl if FFmpeg isn't found. It should now warn about missing
|
||||
FFmpeg and move ahead without encoding. ([@ritiek](https://github.com/ritiek))
|
||||
(debe7ee9024e2ec65eed9935460c62f4eecd03ea)
|
||||
|
||||
## [2.0.3] (Hotfix Release) - 18-05-2020
|
||||
### Fixed
|
||||
- Genius would sometimes return invalid lyrics. Retry a few times in such a case.
|
||||
([@ritiek](https://github.com/ritiek)) (29b1f31a2622f749df83c3072c4cbb22615bff95)
|
||||
|
||||
## [2.0.2] (Hotfix Release) - 18-05-2020
|
||||
### Fixed
|
||||
- Skipping tracks with `-m` would crash.
|
||||
- Skipping tracks with `-m` would crash. ([@ritiek](https://github.com/ritiek))
|
||||
(bbe43da191093302726ddc9a48f0fa0a55be6fb6)
|
||||
|
||||
## [2.0.1] (Hotfix Release) - 18-05-2020
|
||||
### Fixed
|
||||
- `-o m4a` would always fail.
|
||||
- `-o m4a` would always fail. ([@ritiek](https://github.com/ritiek))
|
||||
(cd5f224e379f3feefc95e338ec50674f976e2e89)
|
||||
|
||||
## [2.0.0] - 18-05-2020
|
||||
### Migrating from v1.2.6 to v2.0.0
|
||||
|
||||
@@ -9,7 +9,7 @@ from spotdl.command_line.exceptions import ArgumentError
|
||||
|
||||
# hardcode loglevel for dependencies so that they do not spew generic
|
||||
# log messages along with spotdl.
|
||||
for module in ("urllib3", "spotipy", "pytube"):
|
||||
for module in ("chardet", "urllib3", "spotipy", "pytube"):
|
||||
logging.getLogger(module).setLevel(logging.CRITICAL)
|
||||
|
||||
coloredlogs.DEFAULT_FIELD_STYLES = {
|
||||
|
||||
@@ -261,16 +261,7 @@ class Spotdl:
|
||||
if not self.arguments["no_metadata"]:
|
||||
metadata["lyrics"].start()
|
||||
|
||||
filter_space_chars = self.output_filename_filter(not self.arguments["no_spaces"])
|
||||
directory = os.path.dirname(
|
||||
spotdl.metadata.format_string(
|
||||
self.arguments["output_file"],
|
||||
metadata,
|
||||
output_extension=output_extension,
|
||||
sanitizer=filter_space_chars
|
||||
)
|
||||
)
|
||||
os.makedirs(directory or ".", exist_ok=True)
|
||||
os.makedirs(os.path.dirname(filename) or ".", exist_ok=True)
|
||||
|
||||
logger.info('Downloading to "{filename}"'.format(filename=filename))
|
||||
if self.arguments["no_encode"]:
|
||||
@@ -321,7 +312,7 @@ class Spotdl:
|
||||
|
||||
def download_tracks_from_file(self, path):
|
||||
logger.info(
|
||||
"Checking and removing any duplicate tracks in {}.".format(path)
|
||||
'Checking and removing any duplicate tracks in "{}".'.format(path)
|
||||
)
|
||||
tracks = spotdl.util.readlines_from_nonbinary_file(path)
|
||||
tracks = self.strip_and_filter_duplicates(tracks)
|
||||
@@ -346,12 +337,12 @@ class Spotdl:
|
||||
yt_search_format=self.arguments["search_format"],
|
||||
yt_manual=self.arguments["manual"]
|
||||
)
|
||||
log_track_query = '{position}. Downloading "{track}"'.format(
|
||||
position=position,
|
||||
track=track
|
||||
)
|
||||
logger.info(log_track_query)
|
||||
try:
|
||||
log_track_query = '{position}. Downloading "{track}"'.format(
|
||||
position=position,
|
||||
track=track
|
||||
)
|
||||
logger.info(log_track_query)
|
||||
metadata = search_metadata.on_youtube_and_spotify()
|
||||
self.download_track_from_metadata(metadata)
|
||||
except (urllib.request.URLError, TypeError, IOError) as e:
|
||||
@@ -363,6 +354,11 @@ class Spotdl:
|
||||
tracks.append(track)
|
||||
except (NoYouTubeVideoFoundError, NoYouTubeVideoMatchError) as e:
|
||||
logger.error("{err}".format(err=e.args[0]))
|
||||
except KeyboardInterrupt:
|
||||
# The current track hasn't been downloaded completely.
|
||||
# Make sure we continue from here the next the program runs.
|
||||
tracks.insert(0, track)
|
||||
raise
|
||||
else:
|
||||
if self.arguments["write_successful_file"]:
|
||||
with open(self.arguments["write_successful_file"], "a") as fout:
|
||||
|
||||
@@ -37,12 +37,12 @@ class EncoderBase(ABC):
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self, encoder_path, loglevel, additional_arguments=[]):
|
||||
def __init__(self, encoder_path, must_exist, loglevel, additional_arguments=[]):
|
||||
"""
|
||||
This method must make sure whether specified encoder
|
||||
is available under PATH.
|
||||
"""
|
||||
if shutil.which(encoder_path) is None:
|
||||
if must_exist and shutil.which(encoder_path) is None:
|
||||
raise EncoderNotFoundError(
|
||||
"{} executable does not exist or was not found in PATH.".format(
|
||||
encoder_path
|
||||
|
||||
@@ -27,11 +27,11 @@ RULES = {
|
||||
|
||||
|
||||
class EncoderFFmpeg(EncoderBase):
|
||||
def __init__(self, encoder_path="ffmpeg"):
|
||||
def __init__(self, encoder_path="ffmpeg", must_exist=True):
|
||||
_loglevel = "-hide_banner -nostats -v panic"
|
||||
_additional_arguments = ["-b:a", "192k", "-vn"]
|
||||
try:
|
||||
super().__init__(encoder_path, _loglevel, _additional_arguments)
|
||||
super().__init__(encoder_path, must_exist, _loglevel, _additional_arguments)
|
||||
except EncoderNotFoundError as e:
|
||||
raise FFmpegNotFoundError(e.args[0])
|
||||
self._rules = RULES
|
||||
|
||||
@@ -121,7 +121,7 @@ class Genius(LyricBase):
|
||||
result.
|
||||
"""
|
||||
lyric_url = self.guess_lyric_url_from_artist_and_track(artist, track)
|
||||
return self.from_url(lyric_url, linesep, timeout)
|
||||
return self.from_url(lyric_url, linesep, timeout=timeout)
|
||||
|
||||
def from_url(self, url, linesep="\n", retries=5, timeout=None):
|
||||
"""
|
||||
|
||||
@@ -44,7 +44,7 @@ class Track:
|
||||
return progress_bar
|
||||
|
||||
def download_while_re_encoding(self, stream, target_path, target_encoding=None,
|
||||
encoder=EncoderFFmpeg(), show_progress=True):
|
||||
encoder=EncoderFFmpeg(must_exist=False), show_progress=True):
|
||||
total_chunks = self.calculate_total_chunks(stream["filesize"])
|
||||
process = encoder.re_encode_from_stdin(
|
||||
stream["encoding"],
|
||||
@@ -80,7 +80,7 @@ class Track:
|
||||
writer(response, progress_bar, file_io)
|
||||
|
||||
def re_encode(self, input_path, target_path, target_encoding=None,
|
||||
encoder=EncoderFFmpeg(), show_progress=True):
|
||||
encoder=EncoderFFmpeg(must_exist=False), show_progress=True):
|
||||
stream = self.metadata["streams"].getbest()
|
||||
total_chunks = self.calculate_total_chunks(stream["filesize"])
|
||||
process = encoder.re_encode_from_stdin(
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
__version__ = "2.0.3"
|
||||
__version__ = "2.0.5"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user