fix: aac convent vbr to cbr bug

with_status
WorldObservationLog 4 months ago
parent 94a6ab1c8a
commit afd1213e5f
  1. 27
      src/mp4.py
  2. 4
      src/rip.py

@ -87,8 +87,9 @@ def extract_song(raw_song: bytes, codec: str) -> SongInfo:
match codec: match codec:
case Codec.ALAC: case Codec.ALAC:
alac_atom_name = (Path(tmp_dir.name) / Path(mp4_name).with_suffix('.atom')).absolute() alac_atom_name = (Path(tmp_dir.name) / Path(mp4_name).with_suffix('.atom')).absolute()
subprocess.run(f"mp4extract moov/trak/mdia/minf/stbl/stsd/enca[0]/alac {raw_mp4.absolute()} {alac_atom_name}", subprocess.run(
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) f"mp4extract moov/trak/mdia/minf/stbl/stsd/enca[0]/alac {raw_mp4.absolute()} {alac_atom_name}",
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
with open(alac_atom_name, "rb") as f: with open(alac_atom_name, "rb") as f:
decoder_params = f.read() decoder_params = f.read()
case Codec.AAC | Codec.AAC_DOWNMIX | Codec.AAC_BINAURAL: case Codec.AAC | Codec.AAC_DOWNMIX | Codec.AAC_BINAURAL:
@ -209,3 +210,25 @@ def fix_encapsulate(song: bytes) -> bytes:
new_song_name.absolute()], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) new_song_name.absolute()], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
with open(new_song_name.absolute(), "rb") as f: with open(new_song_name.absolute(), "rb") as f:
return f.read() return f.read()
# FFMPEG will overwrite maxBitrate in DecoderConfigDescriptor
# Using raw song's esds box to fix it
# see also https://trac.ffmpeg.org/ticket/4894
def fix_esds_box(raw_song: bytes, song: bytes) -> bytes:
tmp_dir = TemporaryDirectory()
name = uuid.uuid4().hex
esds_name = Path(tmp_dir.name) / Path(f"{name}.atom")
raw_song_name = Path(tmp_dir.name) / Path(f"{name}_raw.m4a")
song_name = Path(tmp_dir.name) / Path(f"{name}.m4a")
final_song_name = Path(tmp_dir.name) / Path(f"{name}_final.m4a")
with open(raw_song_name.absolute(), "wb") as f:
f.write(raw_song)
with open(song_name.absolute(), "wb") as f:
f.write(song)
subprocess.run(
f"mp4extract moov/trak/mdia/minf/stbl/stsd/enca[0]/esds {raw_song_name.absolute()} {esds_name.absolute()}", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocess.run(f"mp4edit --replace moov/trak/mdia/minf/stbl/stsd/mp4a/esds:{esds_name.absolute()} {song_name.absolute()} {final_song_name.absolute()}",
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
with open(final_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, fix_encapsulate from src.mp4 import extract_media, extract_song, encapsulate, write_metadata, fix_encapsulate, fix_esds_box
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
@ -75,6 +75,8 @@ async def rip_song(song: Song, auth_params: GlobalAuthParams, codec: str, config
if not if_raw_atmos(codec, config.download.atmosConventToM4a): if not if_raw_atmos(codec, config.download.atmosConventToM4a):
metadata_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) song = fix_encapsulate(metadata_song)
if codec == Codec.AAC or codec == Codec.AAC_DOWNMIX or codec == Codec.AAC_BINAURAL:
song = fix_esds_box(song_info.raw, 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:

Loading…
Cancel
Save