ISM Atmos fix for Amazon
This commit is contained in:
parent
999c73d1e6
commit
11108223bc
Binary file not shown.
BIN
binaries/ffmpeg-6.1.1-essentials_build.7z
Normal file
BIN
binaries/ffmpeg-6.1.1-essentials_build.7z
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
linux_binaries/ffmpeg-n6.1-latest-linux64-gpl-6.1.tar.xz
Normal file
BIN
linux_binaries/ffmpeg-n6.1-latest-linux64-gpl-6.1.tar.xz
Normal file
Binary file not shown.
@ -405,17 +405,6 @@ def result(ctx, service, quality, closest_resolution, range_, wanted, alang, sla
|
|||||||
log.warning(f" - No {quality}p resolution available, using closest available: {closest_res}p")
|
log.warning(f" - No {quality}p resolution available, using closest available: {closest_res}p")
|
||||||
quality = closest_res
|
quality = closest_res
|
||||||
|
|
||||||
# Modified video track selection to choose lowest bitrate if vbitrate == min
|
|
||||||
if isinstance(vbitrate, str) and vbitrate.lower() == "min":
|
|
||||||
if not quality:
|
|
||||||
quality = 1080
|
|
||||||
available_bitrate = [int(track.bitrate) for track in title.tracks.videos if track.height == quality]
|
|
||||||
if available_bitrate == []:
|
|
||||||
log.error(" - No video tracks available")
|
|
||||||
continue
|
|
||||||
vbitrate = min(available_bitrate) / 1000
|
|
||||||
log.warning(f" - Choosing minimum bitrate: {vbitrate}")
|
|
||||||
|
|
||||||
title.tracks.select_videos(by_quality=quality, by_vbitrate=vbitrate, by_range=range_, one_only=True)
|
title.tracks.select_videos(by_quality=quality, by_vbitrate=vbitrate, by_range=range_, one_only=True)
|
||||||
title.tracks.select_audios(by_language=alang, by_bitrate=abitrate, with_descriptive=audio_description)
|
title.tracks.select_audios(by_language=alang, by_bitrate=abitrate, with_descriptive=audio_description)
|
||||||
title.tracks.select_subtitles(by_language=slang, with_forced=True)
|
title.tracks.select_subtitles(by_language=slang, with_forced=True)
|
||||||
@ -639,7 +628,9 @@ def result(ctx, service, quality, closest_resolution, range_, wanted, alang, sla
|
|||||||
if not executable:
|
if not executable:
|
||||||
raise log.exit(" - Unable to find mp4decrypt binary")
|
raise log.exit(" - Unable to find mp4decrypt binary")
|
||||||
dec = os.path.splitext(track.locate())[0] + ".dec.mp4"
|
dec = os.path.splitext(track.locate())[0] + ".dec.mp4"
|
||||||
|
os.makedirs(directories.temp, exist_ok=True)
|
||||||
try:
|
try:
|
||||||
|
os.makedirs(directories.temp, exist_ok=True)
|
||||||
subprocess.run([
|
subprocess.run([
|
||||||
executable,
|
executable,
|
||||||
"--show-progress",
|
"--show-progress",
|
||||||
@ -657,6 +648,24 @@ def result(ctx, service, quality, closest_resolution, range_, wanted, alang, sla
|
|||||||
if keys:
|
if keys:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if isinstance(track, AudioTrack) and track.descriptor == Track.Descriptor.ISM and track.atmos:
|
||||||
|
#--enable-libmfx is the only difference between 6.1.1 and 7.X.
|
||||||
|
#FFMPEG 6.1.1 is necessary as that version correctly puts in place an init.mp4 for EAC-3-JOC ie Atmos
|
||||||
|
#https://github.com/GyanD/codexffmpeg/releases/tag/6.1.1
|
||||||
|
#https://github.com/BtbN/FFmpeg-Builds/releases/tag/latest
|
||||||
|
executable = shutil.which("ffmpeg")
|
||||||
|
if not executable:
|
||||||
|
raise log.exit(" - Unable to find ffmpeg binary")
|
||||||
|
eac3 = os.path.splitext(track.locate())[0] + ".eac3"
|
||||||
|
os.makedirs(directories.temp, exist_ok=True)
|
||||||
|
try:
|
||||||
|
os.makedirs(directories.temp, exist_ok=True)
|
||||||
|
exec_string = f"{executable} -i {track.locate()} -hide_banner -loglevel error -map 0 -c:a copy {eac3}"
|
||||||
|
subprocess.run(exec_string)
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
raise log.exit(" - Failed!")
|
||||||
|
track.swap(eac3)
|
||||||
|
log.info(" + Fixed ISM Atmos")
|
||||||
|
|
||||||
if track.needs_repack or (config.decrypter == "mp4decrypt" and isinstance(track, (VideoTrack, AudioTrack))):
|
if track.needs_repack or (config.decrypter == "mp4decrypt" and isinstance(track, (VideoTrack, AudioTrack))):
|
||||||
log.info("Repackaging stream with FFmpeg (to fix malformed streams)")
|
log.info("Repackaging stream with FFmpeg (to fix malformed streams)")
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@ -237,10 +237,8 @@ class Track:
|
|||||||
self.psshPR = str(x).split("\"")[1].split(",")[-1]
|
self.psshPR = str(x).split("\"")[1].split(",")[-1]
|
||||||
break
|
break
|
||||||
|
|
||||||
try:
|
|
||||||
xml_str = base64.b64decode(self.psshPR).decode("utf-16-le", "ignore")
|
xml_str = base64.b64decode(self.psshPR).decode("utf-16-le", "ignore")
|
||||||
xml_str = xml_str[xml_str.index("<"):]
|
xml_str = xml_str[xml_str.index("<"):]
|
||||||
|
|
||||||
xml = load_xml(xml_str).find("DATA") # root: WRMHEADER
|
xml = load_xml(xml_str).find("DATA") # root: WRMHEADER
|
||||||
|
|
||||||
self.kid = xml.findtext("KID") # v4.0.0.0
|
self.kid = xml.findtext("KID") # v4.0.0.0
|
||||||
@ -251,8 +249,6 @@ class Track:
|
|||||||
|
|
||||||
self.kid = uuid.UUID(base64.b64decode(self.kid).hex()).bytes_le.hex()
|
self.kid = uuid.UUID(base64.b64decode(self.kid).hex()).bytes_le.hex()
|
||||||
|
|
||||||
except: pass
|
|
||||||
|
|
||||||
if self.source == "NF":
|
if self.source == "NF":
|
||||||
self.kid = "{}{}{}".format(
|
self.kid = "{}{}{}".format(
|
||||||
self.kid[:8],
|
self.kid[:8],
|
||||||
@ -366,6 +362,8 @@ class Track:
|
|||||||
save_path = save_path_orig.replace(".mp4", f".m4a")
|
save_path = save_path_orig.replace(".mp4", f".m4a")
|
||||||
if not Path(save_path).is_file():
|
if not Path(save_path).is_file():
|
||||||
save_path = save_path_orig.replace(".mp4", f".{str(self.language)[:2]}.m4a")
|
save_path = save_path_orig.replace(".mp4", f".{str(self.language)[:2]}.m4a")
|
||||||
|
if not Path(save_path).is_file():
|
||||||
|
save_path = save_path_orig.replace(".mp4", f".eng.m4a") # This is a hack as only english atmos audio is available in Amazon
|
||||||
if not Path(save_path).is_file():
|
if not Path(save_path).is_file():
|
||||||
save_path = save_path_orig
|
save_path = save_path_orig
|
||||||
if not Path(save_path).is_file():
|
if not Path(save_path).is_file():
|
||||||
@ -1134,8 +1132,17 @@ class Tracks:
|
|||||||
if not videos_quality:
|
if not videos_quality:
|
||||||
raise ValueError(f"There's no {by_quality}p resolution video track. Aborting.")
|
raise ValueError(f"There's no {by_quality}p resolution video track. Aborting.")
|
||||||
self.videos = videos_quality
|
self.videos = videos_quality
|
||||||
if by_vbitrate:
|
|
||||||
|
# Modified video track selection to choose lowest bitrate if by_vbitrate == min
|
||||||
|
if isinstance(by_vbitrate, str) and by_vbitrate.lower() == "min":
|
||||||
|
available_bitrate = [int(track.bitrate) for track in self.videos]
|
||||||
|
bitrate = min(available_bitrate) / 1001
|
||||||
|
#if bitrate < 99999:
|
||||||
|
# bitrate = bitrate / 1000
|
||||||
|
self.videos = [x for x in self.videos if int(x.bitrate) <= int(bitrate * 1001)]
|
||||||
|
elif by_vbitrate:
|
||||||
self.videos = [x for x in self.videos if int(x.bitrate) <= int(by_vbitrate * 1001)]
|
self.videos = [x for x in self.videos if int(x.bitrate) <= int(by_vbitrate * 1001)]
|
||||||
|
|
||||||
if by_codec:
|
if by_codec:
|
||||||
codec_videos = list(filter(lambda x: any(y for y in self.VIDEO_CODEC_MAP[by_codec] if y in x.codec), self.videos))
|
codec_videos = list(filter(lambda x: any(y for y in self.VIDEO_CODEC_MAP[by_codec] if y in x.codec), self.videos))
|
||||||
if not codec_videos and not should_fallback:
|
if not codec_videos and not should_fallback:
|
||||||
|
|||||||
@ -217,9 +217,9 @@ def parse(*, url=None, data=None, source, session=None, downloader=None):
|
|||||||
# extra
|
# extra
|
||||||
extra=(list(quality_level), list(stream_info),) # Either set size as a attribute of VideoTrack or append to extra here.
|
extra=(list(quality_level), list(stream_info),) # Either set size as a attribute of VideoTrack or append to extra here.
|
||||||
))
|
))
|
||||||
"""
|
|
||||||
elif type_info == 'audio':
|
elif type_info == 'audio':
|
||||||
atmos = ( str( quality_level.get('@HasAtmos', 'N/A') ).lower() == "true" ) or ( "ATM" in stream_info.get('@Name', 'N/A') )
|
atmos = ( str( quality_level.get('@HasAtmos', 'N/A') ).lower() == "true" ) or ( "ATM" in stream_info.get('@Name', 'N/A') )
|
||||||
|
if atmos: # Only appending Atmos streams -> Other audios can be obtained from Amazon MPD
|
||||||
tracks.append(AudioTrack(
|
tracks.append(AudioTrack(
|
||||||
id_=track_id,
|
id_=track_id,
|
||||||
source=source,
|
source=source,
|
||||||
@ -235,10 +235,10 @@ def parse(*, url=None, data=None, source, session=None, downloader=None):
|
|||||||
# decryption
|
# decryption
|
||||||
needs_repack=True, # Necessary
|
needs_repack=True, # Necessary
|
||||||
encrypted=encrypted,
|
encrypted=encrypted,
|
||||||
pssh=pssh,
|
psshPR=pssh,
|
||||||
kid=kid,
|
kid=kid,
|
||||||
# extra
|
# extra
|
||||||
extra=(dict(quality_level), dict(stream_info),)
|
extra=(dict(quality_level), dict(stream_info),)
|
||||||
))
|
))
|
||||||
"""
|
|
||||||
return tracks
|
return tracks
|
||||||
|
|||||||
@ -296,8 +296,8 @@ async def m3u8dl(uri, out, track, headers=None, proxy=None):
|
|||||||
"-dv", "all",
|
"-dv", "all",
|
||||||
"-ds", "all",
|
"-ds", "all",
|
||||||
])
|
])
|
||||||
if track.source != "HS":
|
#if track.source != "HS":
|
||||||
arguments.extend(["-M", "format=mp4"])
|
# arguments.extend(["-M", "format=mp4"])
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"{track.__class__.__name__} not supported yet!")
|
raise ValueError(f"{track.__class__.__name__} not supported yet!")
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user