mirror of
https://github.com/zhaarey/AppleMusicDecrypt.git
synced 2025-10-23 15:11:06 +00:00
feat: add lock for rip_song to prevent OOM
This commit is contained in:
90
src/rip.py
90
src/rip.py
@@ -16,53 +16,59 @@ from src.types import GlobalAuthParams, Codec
|
|||||||
from src.url import Song, Album, URLType, Artist, Playlist
|
from src.url import Song, Album, URLType, Artist, Playlist
|
||||||
from src.utils import check_song_exists, if_raw_atmos, playlist_write_song_index, get_codec_from_codec_id
|
from src.utils import check_song_exists, if_raw_atmos, playlist_write_song_index, get_codec_from_codec_id
|
||||||
|
|
||||||
|
task_lock = asyncio.Semaphore(16)
|
||||||
|
|
||||||
|
|
||||||
@logger.catch
|
@logger.catch
|
||||||
async def rip_song(song: Song, auth_params: GlobalAuthParams, codec: str, config: Config, device: Device,
|
async def rip_song(song: Song, auth_params: GlobalAuthParams, codec: str, config: Config, device: Device,
|
||||||
force_save: bool = False, specified_m3u8: str = "", playlist: PlaylistInfo = None):
|
force_save: bool = False, specified_m3u8: str = "", playlist: PlaylistInfo = None):
|
||||||
logger.debug(f"Task of song id {song.id} was created")
|
async with task_lock:
|
||||||
token = auth_params.anonymousAccessToken
|
logger.debug(f"Task of song id {song.id} was created")
|
||||||
song_data = await get_song_info(song.id, token, song.storefront, config.region.language)
|
token = auth_params.anonymousAccessToken
|
||||||
song_metadata = SongMetadata.parse_from_song_data(song_data)
|
song_data = await get_song_info(song.id, token, song.storefront, config.region.language)
|
||||||
if playlist:
|
song_metadata = SongMetadata.parse_from_song_data(song_data)
|
||||||
song_metadata.set_playlist_index(playlist.songIdIndexMapping.get(song.id))
|
if playlist:
|
||||||
logger.info(f"Ripping song: {song_metadata.artist} - {song_metadata.title}")
|
song_metadata.set_playlist_index(playlist.songIdIndexMapping.get(song.id))
|
||||||
if not force_save and check_song_exists(song_metadata, config.download, codec, playlist):
|
logger.info(f"Ripping song: {song_metadata.artist} - {song_metadata.title}")
|
||||||
logger.info(f"Song: {song_metadata.artist} - {song_metadata.title} already exists")
|
if not force_save and check_song_exists(song_metadata, config.download, codec, playlist):
|
||||||
return
|
logger.info(f"Song: {song_metadata.artist} - {song_metadata.title} already exists")
|
||||||
await song_metadata.get_cover(config.download.coverFormat, config.download.coverSize)
|
|
||||||
if song_data.attributes.hasTimeSyncedLyrics:
|
|
||||||
lyrics = await get_song_lyrics(song.id, song.storefront, auth_params.accountAccessToken,
|
|
||||||
auth_params.dsid, auth_params.accountToken, config.region.language)
|
|
||||||
song_metadata.lyrics = lyrics
|
|
||||||
if config.m3u8Api.enable and codec == Codec.ALAC and not specified_m3u8:
|
|
||||||
m3u8_url = await get_m3u8_from_api(config.m3u8Api.endpoint, song.id, config.m3u8Api.enable)
|
|
||||||
if m3u8_url:
|
|
||||||
specified_m3u8 = m3u8_url
|
|
||||||
logger.info(f"Use m3u8 from API for song: {song_metadata.artist} - {song_metadata.title}")
|
|
||||||
elif not m3u8_url and config.m3u8Api.force:
|
|
||||||
logger.error(f"Failed to get m3u8 from API for song: {song_metadata.artist} - {song_metadata.title}")
|
|
||||||
return
|
return
|
||||||
if specified_m3u8:
|
await song_metadata.get_cover(config.download.coverFormat, config.download.coverSize)
|
||||||
song_uri, keys, codec_id = await extract_media(specified_m3u8, codec, song_metadata,
|
if song_data.attributes.hasTimeSyncedLyrics:
|
||||||
config.download.codecPriority, config.download.codecAlternative)
|
lyrics = await get_song_lyrics(song.id, song.storefront, auth_params.accountAccessToken,
|
||||||
else:
|
auth_params.dsid, auth_params.accountToken, config.region.language)
|
||||||
song_uri, keys, codec_id = await extract_media(song_data.attributes.extendedAssetUrls.enhancedHls, codec, song_metadata,
|
song_metadata.lyrics = lyrics
|
||||||
config.download.codecPriority, config.download.codecAlternative)
|
if config.m3u8Api.enable and codec == Codec.ALAC and not specified_m3u8:
|
||||||
logger.info(f"Downloading song: {song_metadata.artist} - {song_metadata.title}")
|
m3u8_url = await get_m3u8_from_api(config.m3u8Api.endpoint, song.id, config.m3u8Api.enable)
|
||||||
codec = get_codec_from_codec_id(codec_id)
|
if m3u8_url:
|
||||||
raw_song = await download_song(song_uri)
|
specified_m3u8 = m3u8_url
|
||||||
song_info = extract_song(raw_song, codec)
|
logger.info(f"Use m3u8 from API for song: {song_metadata.artist} - {song_metadata.title}")
|
||||||
decrypted_song = await decrypt(song_info, keys, song_data, device)
|
elif not m3u8_url and config.m3u8Api.force:
|
||||||
song = encapsulate(song_info, decrypted_song, config.download.atmosConventToM4a)
|
logger.error(f"Failed to get m3u8 from API for song: {song_metadata.artist} - {song_metadata.title}")
|
||||||
if not if_raw_atmos(codec, config.download.atmosConventToM4a):
|
return
|
||||||
song = write_metadata(song, song_metadata, config.metadata.embedMetadata, config.download.coverFormat)
|
if specified_m3u8:
|
||||||
filename = save(song, codec, song_metadata, config.download, playlist)
|
song_uri, keys, codec_id = await extract_media(specified_m3u8, codec, song_metadata,
|
||||||
logger.info(f"Song {song_metadata.artist} - {song_metadata.title} saved!")
|
config.download.codecPriority,
|
||||||
if config.download.afterDownloaded:
|
config.download.codecAlternative)
|
||||||
command = config.download.afterDownloaded.format(filename=filename)
|
else:
|
||||||
logger.info(f"Executing command: {command}")
|
song_uri, keys, codec_id = await extract_media(song_data.attributes.extendedAssetUrls.enhancedHls, codec,
|
||||||
subprocess.Popen(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
song_metadata,
|
||||||
|
config.download.codecPriority,
|
||||||
|
config.download.codecAlternative)
|
||||||
|
logger.info(f"Downloading song: {song_metadata.artist} - {song_metadata.title}")
|
||||||
|
codec = get_codec_from_codec_id(codec_id)
|
||||||
|
raw_song = await download_song(song_uri)
|
||||||
|
song_info = extract_song(raw_song, codec)
|
||||||
|
decrypted_song = await decrypt(song_info, keys, song_data, device)
|
||||||
|
song = encapsulate(song_info, decrypted_song, config.download.atmosConventToM4a)
|
||||||
|
if not if_raw_atmos(codec, config.download.atmosConventToM4a):
|
||||||
|
song = write_metadata(song, song_metadata, config.metadata.embedMetadata, config.download.coverFormat)
|
||||||
|
filename = save(song, codec, song_metadata, config.download, playlist)
|
||||||
|
logger.info(f"Song {song_metadata.artist} - {song_metadata.title} saved!")
|
||||||
|
if config.download.afterDownloaded:
|
||||||
|
command = config.download.afterDownloaded.format(filename=filename)
|
||||||
|
logger.info(f"Executing command: {command}")
|
||||||
|
subprocess.Popen(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
|
|
||||||
|
|
||||||
@logger.catch
|
@logger.catch
|
||||||
|
|||||||
Reference in New Issue
Block a user