[vevo] Support 1080p videos (Fixes #3656)

This commit is contained in:
Philipp Hagemeister 2014-09-24 14:16:56 +02:00
parent 2f771f6c99
commit f0b5d6af74
4 changed files with 102 additions and 4 deletions

View File

@ -2,6 +2,7 @@
from .common import FileDownloader from .common import FileDownloader
from .hls import HlsFD from .hls import HlsFD
from .hls import NativeHlsFD
from .http import HttpFD from .http import HttpFD
from .mplayer import MplayerFD from .mplayer import MplayerFD
from .rtmp import RtmpFD from .rtmp import RtmpFD
@ -19,6 +20,8 @@ def get_suitable_downloader(info_dict):
if url.startswith('rtmp'): if url.startswith('rtmp'):
return RtmpFD return RtmpFD
if protocol == 'm3u8_native':
return NativeHlsFD
if (protocol == 'm3u8') or (protocol is None and determine_ext(url) == 'm3u8'): if (protocol == 'm3u8') or (protocol is None and determine_ext(url) == 'm3u8'):
return HlsFD return HlsFD
if url.startswith('mms') or url.startswith('rtsp'): if url.startswith('mms') or url.startswith('rtsp'):

View File

@ -1,8 +1,12 @@
from __future__ import unicode_literals
import os import os
import re
import subprocess import subprocess
from .common import FileDownloader from .common import FileDownloader
from ..utils import ( from ..utils import (
compat_urlparse,
check_executable, check_executable,
encodeFilename, encodeFilename,
) )
@ -43,3 +47,46 @@ def real_download(self, filename, info_dict):
self.to_stderr(u"\n") self.to_stderr(u"\n")
self.report_error(u'%s exited with code %d' % (program, retval)) self.report_error(u'%s exited with code %d' % (program, retval))
return False return False
class NativeHlsFD(FileDownloader):
""" A more limited implementation that does not require ffmpeg """
def real_download(self, filename, info_dict):
url = info_dict['url']
self.report_destination(filename)
tmpfilename = self.temp_name(filename)
self.to_screen(
'[hlsnative] %s: Downloading m3u8 manifest' % info_dict['id'])
data = self.ydl.urlopen(url).read()
s = data.decode('utf-8', 'ignore')
segment_urls = []
for line in s.splitlines():
line = line.strip()
if line and not line.startswith('#'):
segment_url = (
line
if re.match(r'^https?://', line)
else compat_urlparse.urljoin(url, line))
segment_urls.append(segment_url)
byte_counter = 0
with open(tmpfilename, 'wb') as outf:
for i, segurl in enumerate(segment_urls):
segment = self.ydl.urlopen(segurl).read()
outf.write(segment)
byte_counter += len(segment)
self.to_screen(
'[hlsnative] %s: Downloading segment %d / %d' %
(info_dict['id'], i + 1, len(segment_urls)))
self._hook_progress({
'downloaded_bytes': byte_counter,
'total_bytes': byte_counter,
'filename': filename,
'status': 'finished',
})
self.try_rename(tmpfilename, filename)
return True

View File

@ -15,6 +15,7 @@
compat_http_client, compat_http_client,
compat_urllib_error, compat_urllib_error,
compat_urllib_parse_urlparse, compat_urllib_parse_urlparse,
compat_urlparse,
compat_str, compat_str,
clean_html, clean_html,
@ -640,7 +641,9 @@ def _extract_f4m_formats(self, manifest_url, video_id):
return formats return formats
def _extract_m3u8_formats(self, m3u8_url, video_id, ext=None): def _extract_m3u8_formats(self, m3u8_url, video_id, ext=None,
entry_protocol='m3u8', preference=None):
formats = [{ formats = [{
'format_id': 'm3u8-meta', 'format_id': 'm3u8-meta',
'url': m3u8_url, 'url': m3u8_url,
@ -651,6 +654,11 @@ def _extract_m3u8_formats(self, m3u8_url, video_id, ext=None):
'format_note': 'Quality selection URL', 'format_note': 'Quality selection URL',
}] }]
format_url = lambda u: (
u
if re.match(r'^https?://', u)
else compat_urlparse.urljoin(m3u8_url, u))
m3u8_doc = self._download_webpage(m3u8_url, video_id) m3u8_doc = self._download_webpage(m3u8_url, video_id)
last_info = None last_info = None
kv_rex = re.compile( kv_rex = re.compile(
@ -667,15 +675,17 @@ def _extract_m3u8_formats(self, m3u8_url, video_id, ext=None):
continue continue
else: else:
if last_info is None: if last_info is None:
formats.append({'url': line}) formats.append({'url': format_url(line)})
continue continue
tbr = int_or_none(last_info.get('BANDWIDTH'), scale=1000) tbr = int_or_none(last_info.get('BANDWIDTH'), scale=1000)
f = { f = {
'format_id': 'm3u8-%d' % (tbr if tbr else len(formats)), 'format_id': 'm3u8-%d' % (tbr if tbr else len(formats)),
'url': line.strip(), 'url': format_url(line.strip()),
'tbr': tbr, 'tbr': tbr,
'ext': ext, 'ext': ext,
'protocol': entry_protocol,
'preference': preference,
} }
codecs = last_info.get('CODECS') codecs = last_info.get('CODECS')
if codecs: if codecs:

View File

@ -6,6 +6,7 @@
from .common import InfoExtractor from .common import InfoExtractor
from ..utils import ( from ..utils import (
compat_HTTPError, compat_HTTPError,
compat_urllib_request,
ExtractorError, ExtractorError,
) )
@ -69,6 +70,21 @@ class VevoIE(InfoExtractor):
}] }]
_SMIL_BASE_URL = 'http://smil.lvl3.vevo.com/' _SMIL_BASE_URL = 'http://smil.lvl3.vevo.com/'
def _real_initialize(self):
req = compat_urllib_request.Request(
'http://www.vevo.com/auth', data=b'')
webpage = self._download_webpage(
req, None,
note='Retrieving oauth token',
errnote='Unable to retrieve oauth token',
fatal=False)
if webpage is False:
self._oauth_token = None
else:
self._oauth_token = self._search_regex(
r'access_token":\s*"([^"]+)"',
webpage, 'access token', fatal=False)
def _formats_from_json(self, video_info): def _formats_from_json(self, video_info):
last_version = {'version': -1} last_version = {'version': -1}
for version in video_info['videoVersions']: for version in video_info['videoVersions']:
@ -129,6 +145,26 @@ def _formats_from_smil(self, smil_xml):
}) })
return formats return formats
def _download_api_formats(self, video_id):
if not self._oauth_token:
self._downloader.report_warning(
'No oauth token available, skipping API HLS download')
return []
api_url = 'https://apiv2.vevo.com/video/%s/streams/hls?token=%s' % (
video_id, self._oauth_token)
api_data = self._download_json(
api_url, video_id,
note='Downloading HLS formats',
errnote='Failed to download HLS format list', fatal=False)
if api_data is None:
return []
m3u8_url = api_data[0]['url']
return self._extract_m3u8_formats(
m3u8_url, video_id, entry_protocol='m3u8_native', ext='mp4',
preference=0)
def _real_extract(self, url): def _real_extract(self, url):
mobj = re.match(self._VALID_URL, url) mobj = re.match(self._VALID_URL, url)
video_id = mobj.group('id') video_id = mobj.group('id')
@ -152,6 +188,9 @@ def _real_extract(self, url):
else: else:
age_limit = None age_limit = None
# Download via HLS API
formats.extend(self._download_api_formats(video_id))
# Download SMIL # Download SMIL
smil_blocks = sorted(( smil_blocks = sorted((
f for f in video_info['videoVersions'] f for f in video_info['videoVersions']
@ -166,7 +205,6 @@ def _real_extract(self, url):
fatal=False) fatal=False)
if smil_url_m is not None: if smil_url_m is not None:
smil_url = smil_url_m smil_url = smil_url_m
try: try:
smil_xml = self._download_webpage(smil_url, video_id, smil_xml = self._download_webpage(smil_url, video_id,
'Downloading SMIL info') 'Downloading SMIL info')