Improve video extractor
This commit is contained in:
parent
5d510101ab
commit
ebe1b10c92
@ -372,16 +372,28 @@ def channel(id):
|
|||||||
|
|
||||||
return render_template('channel.html', form=form, btform=button_form, channel=channelData[0], videos=channelData[1], restricted=config['restrictPublicUsage'], config=config)
|
return render_template('channel.html', form=form, btform=button_form, channel=channelData[0], videos=channelData[1], restricted=config['restrictPublicUsage'], config=config)
|
||||||
|
|
||||||
|
def get_best_urls(urls):
|
||||||
|
'''Gets URLS in youtube format (format_id, url, height) and returns best ones for yotter'''
|
||||||
|
best_formats = ["22", "18", "34", "35", "36", "37", "38", "43", "44", "45", "46"]
|
||||||
|
best_urls=[]
|
||||||
|
for url in urls:
|
||||||
|
for f in best_formats:
|
||||||
|
if url['format_id'] == f:
|
||||||
|
best_urls.append(url)
|
||||||
|
return best_urls
|
||||||
|
|
||||||
@app.route('/watch', methods=['GET'])
|
@app.route('/watch', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def watch():
|
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
|
|
||||||
# Use nginx
|
# Use nginx
|
||||||
try:
|
try:
|
||||||
url = info['video']['url'].replace("https://{}".format(hostName), "")+"&host="+hostName
|
for url in info['video']['urls']:
|
||||||
|
hostName = urllib.parse.urlparse(url['url']).netloc
|
||||||
|
url['url'] = url['url'].replace("https://{}".format(hostName), "")+"&host="+hostName
|
||||||
except:
|
except:
|
||||||
|
hostName = "#"
|
||||||
url = "#"
|
url = "#"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -389,6 +401,11 @@ def watch():
|
|||||||
audioUrl = info['video']['audio']['url'].replace("https://{}".format(audioHostName), "")+"&host="+audioHostName
|
audioUrl = info['video']['audio']['url'].replace("https://{}".format(audioHostName), "")+"&host="+audioHostName
|
||||||
except:
|
except:
|
||||||
audioUrl = False
|
audioUrl = False
|
||||||
|
|
||||||
|
if info['video']['isUpcoming']:
|
||||||
|
vid_urls=[]
|
||||||
|
else:
|
||||||
|
vid_urls = get_best_urls(info['video']['urls'])
|
||||||
|
|
||||||
video={
|
video={
|
||||||
'title':info['video']['title'],
|
'title':info['video']['title'],
|
||||||
@ -399,8 +416,6 @@ def watch():
|
|||||||
'channelId': info['owner']['id'],
|
'channelId': info['owner']['id'],
|
||||||
'id':id,
|
'id':id,
|
||||||
'averageRating': str((float(info['video']['rating'])/5)*100),
|
'averageRating': str((float(info['video']['rating'])/5)*100),
|
||||||
'nginxUrl': url,
|
|
||||||
'videoUrl': info['video']['url'],
|
|
||||||
'videoHostName': hostName,
|
'videoHostName': hostName,
|
||||||
'isLive': info['video']['isLive'],
|
'isLive': info['video']['isLive'],
|
||||||
'isUpcoming': info['video']['isUpcoming'],
|
'isUpcoming': info['video']['isUpcoming'],
|
||||||
@ -408,7 +423,7 @@ def watch():
|
|||||||
'nginxAudioUrl': audioUrl,
|
'nginxAudioUrl': audioUrl,
|
||||||
'premieres': info['video']['premieres']
|
'premieres': info['video']['premieres']
|
||||||
}
|
}
|
||||||
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, urls=vid_urls)
|
||||||
|
|
||||||
def markupString(string):
|
def markupString(string):
|
||||||
string = string.replace("\n\n", "<br><br>").replace("\n", "<br>")
|
string = string.replace("\n\n", "<br><br>").replace("\n", "<br>")
|
||||||
|
@ -15,16 +15,25 @@
|
|||||||
<h5 class="ui header">{{video.premieres}}</h5>
|
<h5 class="ui header">{{video.premieres}}</h5>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% elif video.isLive %}
|
||||||
|
<div class="ui center aligned text container">
|
||||||
|
<div class="ui segment">
|
||||||
|
<h4 class="ui header">LIVESTREAM VIDEO</h4>
|
||||||
|
<h5 class="ui header">Livestreams are still not supported on Yotter.</h5>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{%else%}
|
{%else%}
|
||||||
<div class="video-js-responsive-container vjs-hd">
|
<div class="video-js-responsive-container vjs-hd">
|
||||||
<video class="video-js vjs-default-skin"
|
<video class="video-js vjs-default-skin"
|
||||||
data-setup='{ "playbackRates": [0.5, 1, 1.25,1.5, 2] }'
|
data-setup='{ "playbackRates": [0.5, 0.75, 1, 1.25,1.5, 1.75, 2] }'
|
||||||
width="1080"
|
width="1080"
|
||||||
controls
|
controls
|
||||||
buffered
|
buffered
|
||||||
preload="none">
|
preload="none">
|
||||||
{% if config.nginxVideoStream %}
|
{% if config.nginxVideoStream %}
|
||||||
<source src="{{video.nginxUrl}}" type="video/mp4">
|
{% for url in urls %}
|
||||||
|
<source src="{{url.url}}" type="video/{{url.ext}}">
|
||||||
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<source src="{{url_for('stream', url=video.videoUrl.replace('/', 'YotterSlash'))}}" type="video/mp4">
|
<source src="{{url_for('stream', url=video.videoUrl.replace('/', 'YotterSlash'))}}" type="video/mp4">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -122,54 +122,55 @@ def get_video_primary_info(datad, datai):
|
|||||||
contents = datai["contents"]["twoColumnWatchNextResults"]['results']['results']['contents']
|
contents = datai["contents"]["twoColumnWatchNextResults"]['results']['results']['contents']
|
||||||
item = get_renderer_key(contents, "videoPrimaryInfoRenderer")
|
item = get_renderer_key(contents, "videoPrimaryInfoRenderer")
|
||||||
details = datad['videoDetails']
|
details = datad['videoDetails']
|
||||||
try:
|
|
||||||
isUpcoming = details['isUpcoming']
|
|
||||||
views = "Scheduled video"
|
|
||||||
except:
|
|
||||||
isUpcoming = False
|
|
||||||
|
|
||||||
if not isUpcoming:
|
|
||||||
views = details['viewCount']
|
|
||||||
|
|
||||||
if isUpcoming:
|
|
||||||
premieres = item['dateText']['simpleText']
|
|
||||||
else:
|
|
||||||
premieres = False
|
|
||||||
|
|
||||||
ydl = YoutubeDL()
|
ydl = YoutubeDL()
|
||||||
try:
|
data = ydl.extract_info(details['videoId'], False)
|
||||||
|
while not data['formats']:
|
||||||
data = ydl.extract_info(details['videoId'], False)
|
data = ydl.extract_info(details['videoId'], False)
|
||||||
|
|
||||||
## Get audio
|
## Get audio
|
||||||
audio_urls = []
|
audio_urls = []
|
||||||
for f in data['formats']:
|
for f in data['formats']:
|
||||||
for fid in _formats:
|
for fid in _formats:
|
||||||
if f['format_id'] == fid:
|
if f['format_id'] == fid:
|
||||||
try:
|
try:
|
||||||
if 'audio' in _formats[fid]['format_note']:
|
if 'audio' in _formats[fid]['format_note']:
|
||||||
aurl = f['url']
|
aurl = f['url']
|
||||||
fnote = _formats[fid]['format_note']
|
fnote = _formats[fid]['format_note']
|
||||||
bitrate = _formats[fid]['audio_bitrate']
|
bitrate = _formats[fid]['audio_bitrate']
|
||||||
audio_inf = {
|
audio_inf = {
|
||||||
"url":aurl,
|
"url":aurl,
|
||||||
"id":fnote,
|
"id":fnote,
|
||||||
"btr": bitrate
|
"btr": bitrate
|
||||||
}
|
}
|
||||||
audio_urls.append(audio_inf)
|
audio_urls.append(audio_inf)
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
## Get video
|
|
||||||
if not details['isLiveContent']:
|
# Check if is Livestream
|
||||||
url = data['formats'][-1]['url']
|
if details.get('isLive') and details['lengthSeconds'] == '0':
|
||||||
else:
|
isLive = True
|
||||||
url = data['formats'][-1]['url']
|
else:
|
||||||
except:
|
isLive = False
|
||||||
url = "#"
|
|
||||||
try:
|
# Check if is a Scheduled video
|
||||||
if isUpcoming:
|
if details.get('isUpcoming'):
|
||||||
audioURL = False
|
isUpcoming = True
|
||||||
else:
|
views = "Scheduled video"
|
||||||
|
premieres = item['dateText']['simpleText']
|
||||||
|
audioURL = False
|
||||||
|
else:
|
||||||
|
isUpcoming = False
|
||||||
|
premieres = False
|
||||||
|
views = details['viewCount']
|
||||||
|
if not isLive:
|
||||||
audioURL = audio_urls[-1]
|
audioURL = audio_urls[-1]
|
||||||
|
else:
|
||||||
|
audioURL = "#"
|
||||||
|
|
||||||
|
try:
|
||||||
primaryInfo = {
|
primaryInfo = {
|
||||||
"id": details['videoId'],
|
"id": details['videoId'],
|
||||||
"title": details['title'],
|
"title": details['title'],
|
||||||
@ -180,20 +181,17 @@ def get_video_primary_info(datad, datai):
|
|||||||
"rating": details['averageRating'],
|
"rating": details['averageRating'],
|
||||||
"author": details['author'],
|
"author": details['author'],
|
||||||
"isPrivate": details['isPrivate'],
|
"isPrivate": details['isPrivate'],
|
||||||
"isLive": details['isLiveContent'],
|
"isLive": isLive,
|
||||||
"isUpcoming": isUpcoming,
|
"isUpcoming": isUpcoming,
|
||||||
"allowRatings": details['allowRatings'],
|
|
||||||
"url":url,
|
"url":url,
|
||||||
|
"allowRatings": details['allowRatings'],
|
||||||
|
"urls":data['formats'],
|
||||||
"thumbnail": details['thumbnail']['thumbnails'][0]['url'],
|
"thumbnail": details['thumbnail']['thumbnails'][0]['url'],
|
||||||
"audio": audioURL,
|
"audio": audioURL,
|
||||||
"premieres": premieres
|
"premieres": premieres
|
||||||
}
|
}
|
||||||
except:
|
except:
|
||||||
# If error take only most common items
|
# If error take only most common items
|
||||||
if isUpcoming:
|
|
||||||
audioURL = False
|
|
||||||
else:
|
|
||||||
audioURL = audio_urls[-1]
|
|
||||||
primaryInfo = {
|
primaryInfo = {
|
||||||
"id": details['videoId'],
|
"id": details['videoId'],
|
||||||
"title": details['title'],
|
"title": details['title'],
|
||||||
@ -204,10 +202,10 @@ def get_video_primary_info(datad, datai):
|
|||||||
"rating": details['averageRating'],
|
"rating": details['averageRating'],
|
||||||
"author": details['author'],
|
"author": details['author'],
|
||||||
"isPrivate":False,
|
"isPrivate":False,
|
||||||
"isLive":details['isLiveContent'],
|
"isLive":isLive,
|
||||||
"isUpcoming":isUpcoming,
|
"isUpcoming":isUpcoming,
|
||||||
"allowRatings":True,
|
"allowRatings":True,
|
||||||
"url":url,
|
"urls":data['formats'],
|
||||||
"thumbnail": details['thumbnail']['thumbnails'][0]['url'],
|
"thumbnail": details['thumbnail']['thumbnails'][0]['url'],
|
||||||
"audio": audioURL,
|
"audio": audioURL,
|
||||||
"premieres": premieres
|
"premieres": premieres
|
||||||
|
Reference in New Issue
Block a user