print errors, provide an additional audio-only formatStream
This commit is contained in:
@@ -85,9 +85,31 @@ def safeTraverse(obj: dict, path: list, default=None):
|
||||
result = result[x]
|
||||
except KeyError:
|
||||
result = default
|
||||
print(f"error reading: {' -> '.join(path)} - returning: {default}")
|
||||
finally:
|
||||
return result
|
||||
|
||||
def getError(idata: dict):
|
||||
unknown_error = {"status": "Unknown error", "reason": "This is a generic ythdd error."}
|
||||
error = ""
|
||||
|
||||
try:
|
||||
playabilityStatus = safeTraverse(idata, ['stage1', 'playabilityStatus'], default=unknown_error)
|
||||
print(playabilityStatus)
|
||||
error += f"({playabilityStatus['status']}) {playabilityStatus['reason']}"
|
||||
except:
|
||||
error += f"Generic error"
|
||||
|
||||
try:
|
||||
errorScreen = safeTraverse(idata, ['stage1', 'playabilityStatus', 'errorScreen', 'playerErrorMessageRenderer', 'subreason', 'runs'], default=[])
|
||||
error += " - "
|
||||
for x in errorScreen:
|
||||
error += f"{x['text']} "
|
||||
except:
|
||||
pass
|
||||
|
||||
return error
|
||||
|
||||
def genThumbs(videoId: str):
|
||||
|
||||
result = []
|
||||
@@ -115,7 +137,8 @@ def genThumbs(videoId: str):
|
||||
def rebuildFormats(data):
|
||||
result = [{} for x in data]
|
||||
formatStreams = []
|
||||
best_bitrate = 0
|
||||
best_bitrate_video = 0
|
||||
best_bitrate_audio = -1
|
||||
|
||||
for x in range(len(data)):
|
||||
|
||||
@@ -142,6 +165,11 @@ def rebuildFormats(data):
|
||||
except:
|
||||
pass
|
||||
|
||||
if "audio" == data[x]['mimeType'][:5]:
|
||||
isAudio = 1
|
||||
else:
|
||||
isAudio = 0
|
||||
|
||||
if isVideo:
|
||||
result[x]['fps'] = str(data[x]['fps'])
|
||||
else:
|
||||
@@ -164,29 +192,46 @@ def rebuildFormats(data):
|
||||
pass
|
||||
|
||||
# we assume here that a stream with the highest bitrate must be a video stream- that may not be the case
|
||||
if data[x]['averageBitrate'] > data[best_bitrate]['averageBitrate'] and isVideo:
|
||||
best_bitrate = x
|
||||
if data[x]['averageBitrate'] > data[best_bitrate_video]['averageBitrate'] and isVideo:
|
||||
best_bitrate_video = x
|
||||
if data[x]['averageBitrate'] > data[best_bitrate_audio]['averageBitrate'] and isAudio:
|
||||
best_bitrate_audio = x
|
||||
|
||||
# makes FreeTube work, unfortunately it's a video-only stream
|
||||
formatStreams = [
|
||||
{
|
||||
"url": data[best_bitrate]['url'],
|
||||
"itag": str(data[best_bitrate]['itag']),
|
||||
"type": data[best_bitrate]['mimeType'],
|
||||
"quality": data[best_bitrate]['quality'],
|
||||
"bitrate": str(data[best_bitrate]['averageBitrate']),
|
||||
"fps": data[best_bitrate]['fps'],
|
||||
"url": data[best_bitrate_video]['url'],
|
||||
"itag": str(data[best_bitrate_video]['itag']),
|
||||
"type": data[best_bitrate_video]['mimeType'],
|
||||
"quality": data[best_bitrate_video]['quality'],
|
||||
"bitrate": str(data[best_bitrate_video]['averageBitrate']),
|
||||
"fps": data[best_bitrate_video]['fps'],
|
||||
"size": "", # workaround for clipious, which requires ANYTHING to be passed, or else it will throw and error and won't load the video
|
||||
"resolution": str(invidious_formats.FORMATS[data[best_bitrate]['itag']]['height']) + "p",
|
||||
"qualityLabel": str(invidious_formats.FORMATS[data[best_bitrate]['itag']]['height']) + "p",
|
||||
"container": invidious_formats.FORMATS[data[best_bitrate]['itag']]['ext'],
|
||||
"encoding": invidious_formats.FORMATS[data[best_bitrate]['itag']]['vcodec']
|
||||
"resolution": str(invidious_formats.FORMATS[data[best_bitrate_video]['itag']]['height']) + "p",
|
||||
"qualityLabel": str(invidious_formats.FORMATS[data[best_bitrate_video]['itag']]['height']) + "p",
|
||||
"container": invidious_formats.FORMATS[data[best_bitrate_video]['itag']]['ext'],
|
||||
"encoding": invidious_formats.FORMATS[data[best_bitrate_video]['itag']]['vcodec']
|
||||
},
|
||||
{
|
||||
"audioChannels": data[best_bitrate_audio]['audioChannels'],
|
||||
"init": result[best_bitrate_audio]['init'],
|
||||
"index": result[best_bitrate_audio]['index'],
|
||||
"bitrate": str(data[best_bitrate_audio]['averageBitrate']),
|
||||
"url": data[best_bitrate_audio]['url'],
|
||||
"itag": str(data[best_bitrate_audio]['itag']),
|
||||
"type": data[best_bitrate_audio]['mimeType'],
|
||||
"clen": result[best_bitrate_audio]['clen'],
|
||||
"lmt": result[best_bitrate_audio]['lmt'],
|
||||
"projectionType": result[best_bitrate_audio]['projectionType'],
|
||||
"audioQuality": result[best_bitrate_audio]['audioQuality'],
|
||||
"audioSampleRate": result[best_bitrate_audio]['audioSampleRate'],
|
||||
"qualityLabel": "audio"
|
||||
}
|
||||
]
|
||||
|
||||
# not all itags have width and/or height
|
||||
try:
|
||||
formatStreams["size"] = str(invidious_formats.FORMATS[data[best_bitrate]['itag']]['width']) + "x" + str(invidious_formats.FORMATS[data[best_bitrate]['itag']]['height'])
|
||||
formatStreams[0]["size"] = str(invidious_formats.FORMATS[data[best_bitrate]['itag']]['width']) + "x" + str(invidious_formats.FORMATS[data[best_bitrate]['itag']]['height'])
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -201,6 +246,13 @@ def videos(data):
|
||||
|
||||
#print("requesting idata from IOSextract")
|
||||
idata = ythdd_extractor.IOSextract(data[3])
|
||||
|
||||
hls_url = safeTraverse(idata, ['stage1', 'streamingData', 'hlsManifestUrl'], default="")
|
||||
adaptive_formats = safeTraverse(idata, ['stage1', 'streamingData', 'adaptiveFormats'], default=[])
|
||||
if not hls_url:
|
||||
print(f"serious error: couldn't get hls_url or adaptive_formats!\ndumping idata:\n{idata}")
|
||||
return send(500, {'error': getError(idata)})
|
||||
|
||||
wdata = ythdd_extractor.WEBextractSinglePage(data[3])
|
||||
|
||||
#return send(200, {'idata': idata, 'wdata': wdata})
|
||||
@@ -303,9 +355,6 @@ def videos(data):
|
||||
# that is - without making another request
|
||||
author_verified = False
|
||||
|
||||
|
||||
hls_url = safeTraverse(idata, ['stage1', 'streamingData', 'hlsManifestUrl'], default="")
|
||||
adaptive_formats = safeTraverse(idata, ['stage1', 'streamingData', 'adaptiveFormats'], default=[])
|
||||
format_streams = []
|
||||
adaptive_formats, format_streams = rebuildFormats(adaptive_formats)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user