Compare commits

...

12 Commits

Author SHA1 Message Date
Rafael Moraes 50904e9c08 bump version 2024-09-13 21:20:33 -03:00
Rafael Moraes 66556eac0a update update_playlist_file 2024-09-13 21:20:20 -03:00
Rafael Moraes d97445ec9e check for synced_lyrics_only before saving cover 2024-09-08 00:26:56 -03:00
Rafael Moraes d6f30aa0a2 bump version 2024-09-08 00:21:47 -03:00
Rafael Moraes 42a17ca90f optimize stream_url fetching for music videos 2024-09-08 00:21:35 -03:00
Rafael Moraes 3ee0d28727 add from __future__ import annotations 2024-09-08 00:09:30 -03:00
Rafael Moraes 7b8875250c refactor get_playlist_file_path 2024-09-08 00:08:19 -03:00
Rafael Moraes 16734b8b64 refactor update_playlist_file 2024-09-08 00:07:54 -03:00
Rafael Moraes 475bddb5f7 refactor get_final_path 2024-09-08 00:07:30 -03:00
Rafael Moraes 63ba4b0824 change default value for template_file_playlist 2024-09-08 00:07:07 -03:00
Rafael Moraes 9d67e8f0f0 bump version 2024-08-29 22:50:49 -03:00
Rafael Moraes fcbe596a80 refactor to use webplayback api to get the stream url instead of itunes page 2024-08-29 22:50:19 -03:00
5 changed files with 76 additions and 46 deletions
+1 -1
View File
@@ -1 +1 @@
__version__ = "2.3.2"
__version__ = "2.3.5"
+32 -19
View File
@@ -609,13 +609,24 @@ def main(
itunes_page = itunes_api.get_itunes_page(
"music-video", music_video_id_alt
)
stream_url_master = downloader_music_video.get_stream_url_master(
itunes_page
)
if music_video_id_alt == track_metadata["id"]:
stream_url = (
downloader_music_video.get_stream_url_from_itunes_page(
itunes_page
)
)
else:
logger.debug("Getting webplayback")
webplayback = apple_music_api.get_webplayback(
track_metadata["id"]
)
stream_url = (
downloader_music_video.get_stream_url_from_webplayback(
webplayback
)
)
logger.debug("Getting M3U8 data")
m3u8_master_data = downloader_music_video.get_m3u8_master_data(
stream_url_master
)
m3u8_data = downloader_music_video.get_m3u8_master_data(stream_url)
tags = downloader_music_video.get_tags(
music_video_id_alt,
itunes_page,
@@ -643,12 +654,8 @@ def main(
else:
logger.debug("Getting stream info")
stream_info_video, stream_info_audio = (
downloader_music_video.get_stream_info_video(
m3u8_master_data
),
downloader_music_video.get_stream_info_audio(
m3u8_master_data
),
downloader_music_video.get_stream_info_video(m3u8_data),
downloader_music_video.get_stream_info_audio(m3u8_data),
)
decryption_key_video = downloader.get_decryption_key(
stream_info_video.pssh, track_metadata["id"]
@@ -727,7 +734,7 @@ def main(
)
logger.debug(f'Downloading to "{remuxed_path}"')
downloader.download_ytdlp(remuxed_path, stream_url)
if not save_cover:
if synced_lyrics_only or not save_cover:
pass
elif cover_path.exists() and not overwrite:
logger.debug(f'Cover already exists at "{cover_path}", skipping')
@@ -739,12 +746,18 @@ def main(
downloader.apply_tags(remuxed_path, tags, cover_url)
logger.debug(f'Moving to "{final_path}"')
downloader.move_to_output_path(remuxed_path, final_path)
if save_playlist and download_queue.playlist_attributes:
playlist_file_path = downloader.get_playlist_file_path(tags)
logger.debug(
f'Updating M3U8 playlist from "{playlist_file_path}"'
)
downloader.update_playlist_file(playlist_file_path, final_path)
if (
not synced_lyrics_only
and save_playlist
and download_queue.playlist_attributes
):
playlist_file_path = downloader.get_playlist_file_path(tags)
logger.debug(f'Updating M3U8 playlist from "{playlist_file_path}"')
downloader.update_playlist_file(
playlist_file_path,
final_path,
playlist_track,
)
except Exception as e:
error_count += 1
logger.error(
+32 -20
View File
@@ -51,7 +51,7 @@ class Downloader:
template_file_multi_disc: str = "{disc}-{track:02d} {title}",
template_folder_no_album: str = "{artist}/Unknown Album",
template_file_no_album: str = "{title}",
template_file_playlist: str = "Playlists/{playlist_title}",
template_file_playlist: str = "Playlists/{playlist_artist}/{playlist_title}",
template_date: str = "%Y-%m-%dT%H:%M:%SZ",
exclude_tags: str = None,
cover_size: int = 1200,
@@ -266,34 +266,44 @@ class Downloader:
self,
tags: dict,
):
template_folder = self.template_file_playlist.split("/")
template_file = self.template_file_playlist.split("/")
template_final = template_folder + template_file
return self.output_path.joinpath(
return Path(
self.output_path,
*[
self.get_sanitized_string(i.format(**tags), True)
for i in template_final[0:-1]
]
).joinpath(
for i in template_file[0:-1]
],
*[
self.get_sanitized_string(template_final[-1].format(**tags), False)
self.get_sanitized_string(template_file[-1].format(**tags), False)
+ ".m3u8"
]
],
)
def update_playlist_file(
self,
playlist_file_path: Path,
final_path: Path,
playlist_track: int,
):
playlist_file_path.parent.mkdir(parents=True, exist_ok=True)
with playlist_file_path.open("a", encoding="utf8") as playlist_file:
playlist_file.write(
final_path.relative_to(
playlist_file_path.parent, walk_up=True
).as_posix()
+ "\n"
playlist_file_path_parent_parts_len = len(playlist_file_path.parent.parts)
output_path_parts_len = len(self.output_path.parts)
final_path_relative = Path(
("../" * (playlist_file_path_parent_parts_len - output_path_parts_len)),
*final_path.parts[output_path_parts_len:],
)
playlist_file_lines = (
playlist_file_path.open("r", encoding="utf8").readlines()
if playlist_file_path.exists()
else []
)
if len(playlist_file_lines) < playlist_track:
playlist_file_lines.extend(
"\n" for _ in range(playlist_track - len(playlist_file_lines))
)
playlist_file_lines[playlist_track - 1] = final_path_relative.as_posix() + "\n"
with playlist_file_path.open("w", encoding="utf8") as playlist_file:
playlist_file.writelines(playlist_file_lines)
@staticmethod
def millis_to_min_sec(millis):
@@ -398,14 +408,16 @@ class Downloader:
template_folder = self.template_folder_no_album.split("/")
template_file = self.template_file_no_album.split("/")
template_final = template_folder + template_file
return self.output_path.joinpath(
return Path(
self.output_path,
*[
self.get_sanitized_string(i.format(**tags), True)
for i in template_final[0:-1]
]
).joinpath(
self.get_sanitized_string(template_final[-1].format(**tags), False)
+ file_extension
],
(
self.get_sanitized_string(template_final[-1].format(**tags), False)
+ file_extension
),
)
def get_cover_file_extension(self, cover_url: str) -> str:
+9 -6
View File
@@ -25,17 +25,20 @@ class DownloaderMusicVideo:
self.downloader = downloader
self.codec = codec
def get_stream_url_master(self, itunes_page: dict) -> str:
return itunes_page["offers"][0]["assets"][0]["hlsUrl"]
def get_stream_url_from_webplayback(self, webplayback: dict) -> str:
return webplayback["hls-playlist-url"]
def get_m3u8_master_data(self, stream_url_master: str) -> dict:
url_parts = urllib.parse.urlparse(stream_url_master)
def get_stream_url_from_itunes_page(self, itunes_page: dict) -> dict:
stream_url = itunes_page["offers"][0]["assets"][0]["hlsUrl"]
url_parts = urllib.parse.urlparse(stream_url)
query = urllib.parse.parse_qs(url_parts.query, keep_blank_values=True)
query.update({"aec": "HD", "dsid": "1"})
stream_url_master_new = url_parts._replace(
return url_parts._replace(
query=urllib.parse.urlencode(query, doseq=True)
).geturl()
return m3u8.load(stream_url_master_new).data
def get_m3u8_master_data(self, stream_url_master: str) -> dict:
return m3u8.load(stream_url_master).data
def get_playlist_video(
self,
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
from dataclasses import dataclass