Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for high-res video. #1292

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions mps_youtube/players/mplayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ def _generate_real_playerargs(self):
util.list_update("-cache", args)
util.list_update("4096", args)

# MPlayer currently only supports audio files local to the filesystem,
# so this will not work with audio streams.
if 'audio_url' in self.stream and self.stream['mtype'] == 'video_only':
util.list_update(f'-audiofile {self.stream["audio_url"]}', args)

return [self.player] + args + [self.stream['url']]

def clean_up(self):
Expand Down
3 changes: 3 additions & 0 deletions mps_youtube/players/mpv.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ def _generate_real_playerargs(self):
util.list_update('--no-video', args)
util.list_update('--vid=no', args)

if 'audio_url' in self.stream and self.stream['mtype'] == 'video_only':
util.list_update(f'--audio-file={self.stream["audio_url"]}', args)

return [self.player] + args + [self.stream['url']]

def clean_up(self):
Expand Down
3 changes: 3 additions & 0 deletions mps_youtube/players/vlc.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ def _generate_real_playerargs(self):
if self.subtitle_path:
args.extend(('--sub-file', self.subtitle_path))

if 'audio_url' in self.stream and self.stream['mtype'] == 'video_only':
util.list_update(f'--input-slave={self.stream["audio_url"]}', args)

util.list_update("--play-and-exit", args)

return [self.player] + args + [self.stream['url']]
Expand Down
53 changes: 49 additions & 4 deletions mps_youtube/streams.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import re
import time
import threading
from urllib.request import urlopen
Expand Down Expand Up @@ -37,6 +38,25 @@ def prune():

def get(vid, force=False, callback=None, threeD=False):
""" Get all streams as a dict. callback function passed to get_pafy. """

def get_mtype(resolution, acodec, url):
"""
Return the media type of the stream as a string.

Returns "audio" for audio only streams, "video_only" for video only
streams, and "video" for video and audio streams (for backward
compatibility with existing code).
"""
if 'audio' in resolution:
return 'audio'
if '//manifest' not in url:
if acodec and acodec != 'none':
return 'video'
else:
return 'video_only'
else:
return '?'

now = time.time()
ytid = vid.ytid
have_stream = g.streams.get(ytid) and (g.streams[ytid]['expiry'] > now if g.streams[ytid]['expiry'] is not None else False)
Expand Down Expand Up @@ -64,14 +84,27 @@ def get(vid, force=False, callback=None, threeD=False):
ps = p.allstreams if threeD else [x for x in p.allstreams
if not x.threed]

# Fetch all the audio only streams. Sort the list by the highest
# quality stream in descending order.
audio_only_streams = [
s for s in ps
if s.get('acodec', 'none') != 'none'
and s.get('resolution', None).lower() == 'audio only'
]
sorted_audio_only_streams = sorted(
audio_only_streams,
key=lambda s: [s['quality'], s['abr']],
reverse=True
)

streams = [{"url": s['url'],
"ext": s['ext'],
"quality": s['resolution'],
"rawbitrate": s.get('bitrate',-1),
"mtype": 'audio' if 'audio' in s['resolution'] else ('video' if s['acodec'] != 'none' else '?'),
"mtype": get_mtype(s['resolution'], s.get('acodec', None), s['url']),
"audio_url": sorted_audio_only_streams[0]['url'] if len(sorted_audio_only_streams) > 0 else '',
"size": int(s.get('filesize') if s.get('filesize') is not None else s.get('filesize_approx', -1))} for s in ps]


if 'manifest' in streams[0]['url']:
expiry = float(streams[0]['url'].split('/expire/')[1].split('/')[0])
else:
Expand Down Expand Up @@ -113,7 +146,15 @@ def getbitrate(x):
streams = [x for x in slist if x['mtype'] == "audio"]
streams = sorted(streams, key=getbitrate, reverse=True)
else:
streams = [x for x in slist if x['mtype'] == "video" and okres(x)]
# Determine whether the player supports video_only files with separate
# audio streams. MPlayer currently only supports audio files local to
# the filesystem.
acceptable_video_types = ['video']
if re.search(r'mpv|vlc', config.PLAYER.get):
acceptable_video_types.append('video_only')

streams = [x for x in slist if x['mtype'] in acceptable_video_types and okres(x)]

if not config.VIDEO_FORMAT.get == "auto":
if config.VIDEO_FORMAT.get == "mp4":
streams = [x for x in streams if x['ext'] == "mp4"]
Expand All @@ -122,7 +163,11 @@ def getbitrate(x):
if config.VIDEO_FORMAT.get == "3gp":
streams = [x for x in streams if x['ext'] == "3gp"]
if not streams:
streams = [x for x in slist if x['mtype'] == "video" and okres(x)]
streams = [
x for x
in slist
if x['mtype'] in acceptable_video_types and okres(x)
]
streams = sorted(streams, key=getq, reverse=True)

util.dbg("select stream, q: %s, audio: %s, len: %s", q, audio, len(streams))
Expand Down