Add ability to play audio only
This commit is contained in:
parent
6a6b49bfcb
commit
2213e09006
@ -304,13 +304,20 @@ def watch():
|
|||||||
id = request.args.get('v', None)
|
id = request.args.get('v', None)
|
||||||
info = ytvids.get_video_info(id)
|
info = ytvids.get_video_info(id)
|
||||||
hostName = urllib.parse.urlparse(info['video']['url']).netloc
|
hostName = urllib.parse.urlparse(info['video']['url']).netloc
|
||||||
|
audioHostName = urllib.parse.urlparse(info['video']['audio']['url']).netloc
|
||||||
|
|
||||||
# Use nginx
|
# Use nginx
|
||||||
try:
|
try:
|
||||||
url = info['video']['url'].replace(hostName, config['serverName'])+"&hostname="+hostName
|
url = info['video']['url'].replace("https://{}".format(hostName), "")+"?host="+hostName
|
||||||
except:
|
except:
|
||||||
url = "#"
|
url = "#"
|
||||||
|
|
||||||
|
try:
|
||||||
|
audioUrl = info['video']['audio']['url'].replace("https://{}".format(audioHostName), "")+"?host="+audioHostName
|
||||||
|
print(audioUrl)
|
||||||
|
except:
|
||||||
|
audioUrl = False
|
||||||
|
|
||||||
video={
|
video={
|
||||||
'title':info['video']['title'],
|
'title':info['video']['title'],
|
||||||
'description':Markup(markupString(info['video']['description'])),
|
'description':Markup(markupString(info['video']['description'])),
|
||||||
@ -325,7 +332,8 @@ def watch():
|
|||||||
'videoHostName': hostName,
|
'videoHostName': hostName,
|
||||||
'isLive': info['video']['isLive'],
|
'isLive': info['video']['isLive'],
|
||||||
'isUpcoming': info['video']['isUpcoming'],
|
'isUpcoming': info['video']['isUpcoming'],
|
||||||
'thumbnail': info['video']['thumbnail']
|
'thumbnail': info['video']['thumbnail'],
|
||||||
|
'nginxAudioUrl': audioUrl
|
||||||
}
|
}
|
||||||
return render_template("video.html", video=video, title='{}'.format(video['title']), config=config)
|
return render_template("video.html", video=video, title='{}'.format(video['title']), config=config)
|
||||||
|
|
||||||
|
@ -57,6 +57,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="ui raised center aligned segment break-word">
|
||||||
|
<p><i class="grey music icon"></i><b><a href="{{video.nginxAudioUrl}}">Play Only Audio</a></b></p>
|
||||||
|
<audio controls>
|
||||||
|
<source src="{{video.nginxAudioUrl}}">
|
||||||
|
Your browser does not support the audio element.
|
||||||
|
</audio>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="ui raised segment break-word">
|
<div class="ui raised segment break-word">
|
||||||
<p>{{video.description}}</p>
|
<p>{{video.description}}</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"maxInstanceUsers": 60,
|
"maxInstanceUsers": 60,
|
||||||
"serverLocation": "Germany",
|
"serverLocation": "Germany",
|
||||||
"restrictPublicUsage":true,
|
"restrictPublicUsage":true,
|
||||||
"nginxVideoStream":false,
|
"nginxVideoStream":true,
|
||||||
"maintenance_mode":false,
|
"maintenance_mode":false,
|
||||||
"show_admin_message":false,
|
"show_admin_message":false,
|
||||||
"admin_message_title":"Message from the admin",
|
"admin_message_title":"Message from the admin",
|
||||||
|
@ -5,6 +5,114 @@ import urllib.parse
|
|||||||
import requests
|
import requests
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
# from https://github.com/ytdl-org/youtube-dl/blob/master/youtube_dl/extractor/youtube.py
|
||||||
|
_formats = {
|
||||||
|
'5': {'ext': 'flv', 'width': 400, 'height': 240, 'acodec': 'mp3', 'audio_bitrate': 64, 'vcodec': 'h263'},
|
||||||
|
'6': {'ext': 'flv', 'width': 450, 'height': 270, 'acodec': 'mp3', 'audio_bitrate': 64, 'vcodec': 'h263'},
|
||||||
|
'13': {'ext': '3gp', 'acodec': 'aac', 'vcodec': 'mp4v'},
|
||||||
|
'17': {'ext': '3gp', 'width': 176, 'height': 144, 'acodec': 'aac', 'audio_bitrate': 24, 'vcodec': 'mp4v'},
|
||||||
|
'18': {'ext': 'mp4', 'width': 640, 'height': 360, 'acodec': 'aac', 'audio_bitrate': 96, 'vcodec': 'h264'},
|
||||||
|
'22': {'ext': 'mp4', 'width': 1280, 'height': 720, 'acodec': 'aac', 'audio_bitrate': 192, 'vcodec': 'h264'},
|
||||||
|
'34': {'ext': 'flv', 'width': 640, 'height': 360, 'acodec': 'aac', 'audio_bitrate': 128, 'vcodec': 'h264'},
|
||||||
|
'35': {'ext': 'flv', 'width': 854, 'height': 480, 'acodec': 'aac', 'audio_bitrate': 128, 'vcodec': 'h264'},
|
||||||
|
# itag 36 videos are either 320x180 (BaW_jenozKc) or 320x240 (__2ABJjxzNo), audio_bitrate varies as well
|
||||||
|
'36': {'ext': '3gp', 'width': 320, 'acodec': 'aac', 'vcodec': 'mp4v'},
|
||||||
|
'37': {'ext': 'mp4', 'width': 1920, 'height': 1080, 'acodec': 'aac', 'audio_bitrate': 192, 'vcodec': 'h264'},
|
||||||
|
'38': {'ext': 'mp4', 'width': 4096, 'height': 3072, 'acodec': 'aac', 'audio_bitrate': 192, 'vcodec': 'h264'},
|
||||||
|
'43': {'ext': 'webm', 'width': 640, 'height': 360, 'acodec': 'vorbis', 'audio_bitrate': 128, 'vcodec': 'vp8'},
|
||||||
|
'44': {'ext': 'webm', 'width': 854, 'height': 480, 'acodec': 'vorbis', 'audio_bitrate': 128, 'vcodec': 'vp8'},
|
||||||
|
'45': {'ext': 'webm', 'width': 1280, 'height': 720, 'acodec': 'vorbis', 'audio_bitrate': 192, 'vcodec': 'vp8'},
|
||||||
|
'46': {'ext': 'webm', 'width': 1920, 'height': 1080, 'acodec': 'vorbis', 'audio_bitrate': 192, 'vcodec': 'vp8'},
|
||||||
|
'59': {'ext': 'mp4', 'width': 854, 'height': 480, 'acodec': 'aac', 'audio_bitrate': 128, 'vcodec': 'h264'},
|
||||||
|
'78': {'ext': 'mp4', 'width': 854, 'height': 480, 'acodec': 'aac', 'audio_bitrate': 128, 'vcodec': 'h264'},
|
||||||
|
|
||||||
|
|
||||||
|
# 3D videos
|
||||||
|
'82': {'ext': 'mp4', 'height': 360, 'format_note': '3D', 'acodec': 'aac', 'audio_bitrate': 128, 'vcodec': 'h264'},
|
||||||
|
'83': {'ext': 'mp4', 'height': 480, 'format_note': '3D', 'acodec': 'aac', 'audio_bitrate': 128, 'vcodec': 'h264'},
|
||||||
|
'84': {'ext': 'mp4', 'height': 720, 'format_note': '3D', 'acodec': 'aac', 'audio_bitrate': 192, 'vcodec': 'h264'},
|
||||||
|
'85': {'ext': 'mp4', 'height': 1080, 'format_note': '3D', 'acodec': 'aac', 'audio_bitrate': 192, 'vcodec': 'h264'},
|
||||||
|
'100': {'ext': 'webm', 'height': 360, 'format_note': '3D', 'acodec': 'vorbis', 'audio_bitrate': 128, 'vcodec': 'vp8'},
|
||||||
|
'101': {'ext': 'webm', 'height': 480, 'format_note': '3D', 'acodec': 'vorbis', 'audio_bitrate': 192, 'vcodec': 'vp8'},
|
||||||
|
'102': {'ext': 'webm', 'height': 720, 'format_note': '3D', 'acodec': 'vorbis', 'audio_bitrate': 192, 'vcodec': 'vp8'},
|
||||||
|
|
||||||
|
# Apple HTTP Live Streaming
|
||||||
|
'91': {'ext': 'mp4', 'height': 144, 'format_note': 'HLS', 'acodec': 'aac', 'audio_bitrate': 48, 'vcodec': 'h264'},
|
||||||
|
'92': {'ext': 'mp4', 'height': 240, 'format_note': 'HLS', 'acodec': 'aac', 'audio_bitrate': 48, 'vcodec': 'h264'},
|
||||||
|
'93': {'ext': 'mp4', 'height': 360, 'format_note': 'HLS', 'acodec': 'aac', 'audio_bitrate': 128, 'vcodec': 'h264'},
|
||||||
|
'94': {'ext': 'mp4', 'height': 480, 'format_note': 'HLS', 'acodec': 'aac', 'audio_bitrate': 128, 'vcodec': 'h264'},
|
||||||
|
'95': {'ext': 'mp4', 'height': 720, 'format_note': 'HLS', 'acodec': 'aac', 'audio_bitrate': 256, 'vcodec': 'h264'},
|
||||||
|
'96': {'ext': 'mp4', 'height': 1080, 'format_note': 'HLS', 'acodec': 'aac', 'audio_bitrate': 256, 'vcodec': 'h264'},
|
||||||
|
'132': {'ext': 'mp4', 'height': 240, 'format_note': 'HLS', 'acodec': 'aac', 'audio_bitrate': 48, 'vcodec': 'h264'},
|
||||||
|
'151': {'ext': 'mp4', 'height': 72, 'format_note': 'HLS', 'acodec': 'aac', 'audio_bitrate': 24, 'vcodec': 'h264'},
|
||||||
|
|
||||||
|
# DASH mp4 video
|
||||||
|
'133': {'ext': 'mp4', 'height': 240, 'format_note': 'DASH video', 'vcodec': 'h264'},
|
||||||
|
'134': {'ext': 'mp4', 'height': 360, 'format_note': 'DASH video', 'vcodec': 'h264'},
|
||||||
|
'135': {'ext': 'mp4', 'height': 480, 'format_note': 'DASH video', 'vcodec': 'h264'},
|
||||||
|
'136': {'ext': 'mp4', 'height': 720, 'format_note': 'DASH video', 'vcodec': 'h264'},
|
||||||
|
'137': {'ext': 'mp4', 'height': 1080, 'format_note': 'DASH video', 'vcodec': 'h264'},
|
||||||
|
'138': {'ext': 'mp4', 'format_note': 'DASH video', 'vcodec': 'h264'}, # Height can vary (https://github.com/ytdl-org/youtube-dl/issues/4559)
|
||||||
|
'160': {'ext': 'mp4', 'height': 144, 'format_note': 'DASH video', 'vcodec': 'h264'},
|
||||||
|
'212': {'ext': 'mp4', 'height': 480, 'format_note': 'DASH video', 'vcodec': 'h264'},
|
||||||
|
'264': {'ext': 'mp4', 'height': 1440, 'format_note': 'DASH video', 'vcodec': 'h264'},
|
||||||
|
'298': {'ext': 'mp4', 'height': 720, 'format_note': 'DASH video', 'vcodec': 'h264', 'fps': 60},
|
||||||
|
'299': {'ext': 'mp4', 'height': 1080, 'format_note': 'DASH video', 'vcodec': 'h264', 'fps': 60},
|
||||||
|
'266': {'ext': 'mp4', 'height': 2160, 'format_note': 'DASH video', 'vcodec': 'h264'},
|
||||||
|
|
||||||
|
# Dash mp4 audio
|
||||||
|
'139': {'ext': 'm4a', 'format_note': 'DASH audio', 'acodec': 'aac', 'audio_bitrate': 48, 'container': 'm4a_dash'},
|
||||||
|
'140': {'ext': 'm4a', 'format_note': 'DASH audio', 'acodec': 'aac', 'audio_bitrate': 128, 'container': 'm4a_dash'},
|
||||||
|
'141': {'ext': 'm4a', 'format_note': 'DASH audio', 'acodec': 'aac', 'audio_bitrate': 256, 'container': 'm4a_dash'},
|
||||||
|
'256': {'ext': 'm4a', 'format_note': 'DASH audio', 'acodec': 'aac', 'container': 'm4a_dash'},
|
||||||
|
'258': {'ext': 'm4a', 'format_note': 'DASH audio', 'acodec': 'aac', 'container': 'm4a_dash'},
|
||||||
|
'325': {'ext': 'm4a', 'format_note': 'DASH audio', 'acodec': 'dtse', 'container': 'm4a_dash'},
|
||||||
|
'328': {'ext': 'm4a', 'format_note': 'DASH audio', 'acodec': 'ec-3', 'container': 'm4a_dash'},
|
||||||
|
|
||||||
|
# Dash webm
|
||||||
|
'167': {'ext': 'webm', 'height': 360, 'width': 640, 'format_note': 'DASH video', 'container': 'webm', 'vcodec': 'vp8'},
|
||||||
|
'168': {'ext': 'webm', 'height': 480, 'width': 854, 'format_note': 'DASH video', 'container': 'webm', 'vcodec': 'vp8'},
|
||||||
|
'169': {'ext': 'webm', 'height': 720, 'width': 1280, 'format_note': 'DASH video', 'container': 'webm', 'vcodec': 'vp8'},
|
||||||
|
'170': {'ext': 'webm', 'height': 1080, 'width': 1920, 'format_note': 'DASH video', 'container': 'webm', 'vcodec': 'vp8'},
|
||||||
|
'218': {'ext': 'webm', 'height': 480, 'width': 854, 'format_note': 'DASH video', 'container': 'webm', 'vcodec': 'vp8'},
|
||||||
|
'219': {'ext': 'webm', 'height': 480, 'width': 854, 'format_note': 'DASH video', 'container': 'webm', 'vcodec': 'vp8'},
|
||||||
|
'278': {'ext': 'webm', 'height': 144, 'format_note': 'DASH video', 'container': 'webm', 'vcodec': 'vp9'},
|
||||||
|
'242': {'ext': 'webm', 'height': 240, 'format_note': 'DASH video', 'vcodec': 'vp9'},
|
||||||
|
'243': {'ext': 'webm', 'height': 360, 'format_note': 'DASH video', 'vcodec': 'vp9'},
|
||||||
|
'244': {'ext': 'webm', 'height': 480, 'format_note': 'DASH video', 'vcodec': 'vp9'},
|
||||||
|
'245': {'ext': 'webm', 'height': 480, 'format_note': 'DASH video', 'vcodec': 'vp9'},
|
||||||
|
'246': {'ext': 'webm', 'height': 480, 'format_note': 'DASH video', 'vcodec': 'vp9'},
|
||||||
|
'247': {'ext': 'webm', 'height': 720, 'format_note': 'DASH video', 'vcodec': 'vp9'},
|
||||||
|
'248': {'ext': 'webm', 'height': 1080, 'format_note': 'DASH video', 'vcodec': 'vp9'},
|
||||||
|
'271': {'ext': 'webm', 'height': 1440, 'format_note': 'DASH video', 'vcodec': 'vp9'},
|
||||||
|
# itag 272 videos are either 3840x2160 (e.g. RtoitU2A-3E) or 7680x4320 (sLprVF6d7Ug)
|
||||||
|
'272': {'ext': 'webm', 'height': 2160, 'format_note': 'DASH video', 'vcodec': 'vp9'},
|
||||||
|
'302': {'ext': 'webm', 'height': 720, 'format_note': 'DASH video', 'vcodec': 'vp9', 'fps': 60},
|
||||||
|
'303': {'ext': 'webm', 'height': 1080, 'format_note': 'DASH video', 'vcodec': 'vp9', 'fps': 60},
|
||||||
|
'308': {'ext': 'webm', 'height': 1440, 'format_note': 'DASH video', 'vcodec': 'vp9', 'fps': 60},
|
||||||
|
'313': {'ext': 'webm', 'height': 2160, 'format_note': 'DASH video', 'vcodec': 'vp9'},
|
||||||
|
'315': {'ext': 'webm', 'height': 2160, 'format_note': 'DASH video', 'vcodec': 'vp9', 'fps': 60},
|
||||||
|
|
||||||
|
# Dash webm audio
|
||||||
|
'171': {'ext': 'webm', 'acodec': 'vorbis', 'format_note': 'DASH audio', 'audio_bitrate': 128},
|
||||||
|
'172': {'ext': 'webm', 'acodec': 'vorbis', 'format_note': 'DASH audio', 'audio_bitrate': 256},
|
||||||
|
|
||||||
|
# Dash webm audio with opus inside
|
||||||
|
'249': {'ext': 'webm', 'format_note': 'DASH audio', 'acodec': 'opus', 'audio_bitrate': 50},
|
||||||
|
'250': {'ext': 'webm', 'format_note': 'DASH audio', 'acodec': 'opus', 'audio_bitrate': 70},
|
||||||
|
'251': {'ext': 'webm', 'format_note': 'DASH audio', 'acodec': 'opus', 'audio_bitrate': 160},
|
||||||
|
|
||||||
|
# RTMP (unnamed)
|
||||||
|
'_rtmp': {'protocol': 'rtmp'},
|
||||||
|
|
||||||
|
# av01 video only formats sometimes served with "unknown" codecs
|
||||||
|
'394': {'vcodec': 'av01.0.05M.08'},
|
||||||
|
'395': {'vcodec': 'av01.0.05M.08'},
|
||||||
|
'396': {'vcodec': 'av01.0.05M.08'},
|
||||||
|
'397': {'vcodec': 'av01.0.05M.08'},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_renderer_key(renderer, key):
|
def get_renderer_key(renderer, key):
|
||||||
for k in renderer:
|
for k in renderer:
|
||||||
if key in k:
|
if key in k:
|
||||||
@ -26,6 +134,26 @@ def get_video_primary_info(datad, datai):
|
|||||||
ydl = YoutubeDL()
|
ydl = YoutubeDL()
|
||||||
try:
|
try:
|
||||||
data = ydl.extract_info(details['videoId'], False)
|
data = ydl.extract_info(details['videoId'], False)
|
||||||
|
|
||||||
|
## Get audio
|
||||||
|
audio_urls = []
|
||||||
|
for f in data['formats']:
|
||||||
|
for fid in _formats:
|
||||||
|
if f['format_id'] == fid:
|
||||||
|
try:
|
||||||
|
if 'audio' in _formats[fid]['format_note']:
|
||||||
|
aurl = f['url']
|
||||||
|
fnote = _formats[fid]['format_note']
|
||||||
|
bitrate = _formats[fid]['audio_bitrate']
|
||||||
|
audio_inf = {
|
||||||
|
"url":aurl,
|
||||||
|
"id":fnote,
|
||||||
|
"btr": bitrate
|
||||||
|
}
|
||||||
|
audio_urls.append(audio_inf)
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
## Get video
|
||||||
if not details['isLiveContent']:
|
if not details['isLiveContent']:
|
||||||
url = data['formats'][-1]['url']
|
url = data['formats'][-1]['url']
|
||||||
else:
|
else:
|
||||||
@ -47,7 +175,8 @@ def get_video_primary_info(datad, datai):
|
|||||||
"isUpcoming": isUpcoming,
|
"isUpcoming": isUpcoming,
|
||||||
"allowRatings": details['allowRatings'],
|
"allowRatings": details['allowRatings'],
|
||||||
"url":url,
|
"url":url,
|
||||||
"thumbnail": details['thumbnail']['thumbnails'][0]['url']
|
"thumbnail": details['thumbnail']['thumbnails'][0]['url'],
|
||||||
|
"audio": audio_urls[-1]
|
||||||
}
|
}
|
||||||
except:
|
except:
|
||||||
# If error take only most common items
|
# If error take only most common items
|
||||||
@ -65,7 +194,8 @@ def get_video_primary_info(datad, datai):
|
|||||||
"isUpcoming":isUpcoming,
|
"isUpcoming":isUpcoming,
|
||||||
"allowRatings":True,
|
"allowRatings":True,
|
||||||
"url":url,
|
"url":url,
|
||||||
"thumbnail": details['thumbnail']['thumbnails'][0]['url']
|
"thumbnail": details['thumbnail']['thumbnails'][0]['url'],
|
||||||
|
"audio": audio_urls[-1]
|
||||||
}
|
}
|
||||||
return primaryInfo
|
return primaryInfo
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user