mirror of
https://github.com/zhaarey/AppleMusicDecrypt.git
synced 2025-10-23 15:11:06 +00:00
fix: MP4Box encapsulation error
This commit is contained in:
18
src/mp4.py
18
src/mp4.py
@@ -156,7 +156,7 @@ def encapsulate(song_info: SongInfo, decrypted_media: bytes, atmos_convent: bool
|
|||||||
f.write(str(nhml_xml))
|
f.write(str(nhml_xml))
|
||||||
subprocess.run(f"gpac -i {nhml_name.absolute()} nhmlr -o {song_name.absolute()}",
|
subprocess.run(f"gpac -i {nhml_name.absolute()} nhmlr -o {song_name.absolute()}",
|
||||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
subprocess.run(f'mp4box -ipod {song_name.absolute()}',
|
subprocess.run(f'mp4box -brand "M4A " -ab "M4A " -ab "mp42" {song_name.absolute()}',
|
||||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
with open(song_name.absolute(), "rb") as f:
|
with open(song_name.absolute(), "rb") as f:
|
||||||
final_song = f.read()
|
final_song = f.read()
|
||||||
@@ -188,3 +188,19 @@ def write_metadata(song: bytes, metadata: SongMetadata, embed_metadata: list[str
|
|||||||
embed_song = f.read()
|
embed_song = f.read()
|
||||||
tmp_dir.cleanup()
|
tmp_dir.cleanup()
|
||||||
return embed_song
|
return embed_song
|
||||||
|
|
||||||
|
|
||||||
|
# There are suspected errors in M4A files encapsulated by MP4Box and GPAC,
|
||||||
|
# causing some applications to be unable to correctly process Metadata (such as Android.media, Salt Music)
|
||||||
|
# Using FFMPEG re-encapsulating solves this problem
|
||||||
|
def fix_encapsulate(song: bytes) -> bytes:
|
||||||
|
tmp_dir = TemporaryDirectory()
|
||||||
|
name = uuid.uuid4().hex
|
||||||
|
song_name = Path(tmp_dir.name) / Path(f"{name}.m4a")
|
||||||
|
new_song_name = Path(tmp_dir.name) / Path(f"{name}_fixed.m4a")
|
||||||
|
with open(song_name.absolute(), "wb") as f:
|
||||||
|
f.write(song)
|
||||||
|
subprocess.run(["ffmpeg", "-y", "-i", song_name.absolute(), "-fflags", "+bitexact", "-c:a", "copy", "-c:v", "copy",
|
||||||
|
new_song_name.absolute()], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
|
with open(new_song_name.absolute(), "rb") as f:
|
||||||
|
return f.read()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from src.adb import Device
|
|||||||
from src.decrypt import decrypt
|
from src.decrypt import decrypt
|
||||||
from src.metadata import SongMetadata
|
from src.metadata import SongMetadata
|
||||||
from src.models import PlaylistInfo
|
from src.models import PlaylistInfo
|
||||||
from src.mp4 import extract_media, extract_song, encapsulate, write_metadata
|
from src.mp4 import extract_media, extract_song, encapsulate, write_metadata, fix_encapsulate
|
||||||
from src.save import save
|
from src.save import save
|
||||||
from src.types import GlobalAuthParams, Codec
|
from src.types import GlobalAuthParams, Codec
|
||||||
from src.url import Song, Album, URLType, Artist, Playlist
|
from src.url import Song, Album, URLType, Artist, Playlist
|
||||||
@@ -73,7 +73,8 @@ async def rip_song(song: Song, auth_params: GlobalAuthParams, codec: str, config
|
|||||||
decrypted_song = await decrypt(song_info, keys, song_data, device)
|
decrypted_song = await decrypt(song_info, keys, song_data, device)
|
||||||
song = encapsulate(song_info, decrypted_song, config.download.atmosConventToM4a)
|
song = encapsulate(song_info, decrypted_song, config.download.atmosConventToM4a)
|
||||||
if not if_raw_atmos(codec, config.download.atmosConventToM4a):
|
if not if_raw_atmos(codec, config.download.atmosConventToM4a):
|
||||||
song = write_metadata(song, song_metadata, config.metadata.embedMetadata, config.download.coverFormat)
|
metadata_song = write_metadata(song, song_metadata, config.metadata.embedMetadata, config.download.coverFormat)
|
||||||
|
song = fix_encapsulate(metadata_song)
|
||||||
filename = save(song, codec, song_metadata, config.download, playlist)
|
filename = save(song, codec, song_metadata, config.download, playlist)
|
||||||
logger.info(f"Song {song_metadata.artist} - {song_metadata.title} saved!")
|
logger.info(f"Song {song_metadata.artist} - {song_metadata.title} saved!")
|
||||||
if config.download.afterDownloaded:
|
if config.download.afterDownloaded:
|
||||||
|
|||||||
Reference in New Issue
Block a user