Compare commits
13 Commits
2016.07.03
...
2016.07.05
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c25f1a9b63 | ||
|
|
dfaa86b75e | ||
|
|
d9163ae3b6 | ||
|
|
dafafe7cf1 | ||
|
|
81953d1ae5 | ||
|
|
3a212ed62e | ||
|
|
195f084542 | ||
|
|
aa7a455b2e | ||
|
|
6a4e659c93 | ||
|
|
40f3666f6b | ||
|
|
dd801bbe18 | ||
|
|
38cce791c7 | ||
|
|
bf3ae6a543 |
6
.github/ISSUE_TEMPLATE.md
vendored
6
.github/ISSUE_TEMPLATE.md
vendored
@@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Make sure you are using the *latest* version: run `youtube-dl --version` and ensure your version is *2016.07.03.1*. If it's not read [this FAQ entry](https://github.com/rg3/youtube-dl/blob/master/README.md#how-do-i-update-youtube-dl) and update. Issues with outdated version will be rejected.
|
### Make sure you are using the *latest* version: run `youtube-dl --version` and ensure your version is *2016.07.05*. If it's not read [this FAQ entry](https://github.com/rg3/youtube-dl/blob/master/README.md#how-do-i-update-youtube-dl) and update. Issues with outdated version will be rejected.
|
||||||
- [ ] I've **verified** and **I assure** that I'm running youtube-dl **2016.07.03.1**
|
- [ ] I've **verified** and **I assure** that I'm running youtube-dl **2016.07.05**
|
||||||
|
|
||||||
### Before submitting an *issue* make sure you have:
|
### Before submitting an *issue* make sure you have:
|
||||||
- [ ] At least skimmed through [README](https://github.com/rg3/youtube-dl/blob/master/README.md) and **most notably** [FAQ](https://github.com/rg3/youtube-dl#faq) and [BUGS](https://github.com/rg3/youtube-dl#bugs) sections
|
- [ ] At least skimmed through [README](https://github.com/rg3/youtube-dl/blob/master/README.md) and **most notably** [FAQ](https://github.com/rg3/youtube-dl#faq) and [BUGS](https://github.com/rg3/youtube-dl#bugs) sections
|
||||||
@@ -35,7 +35,7 @@ $ youtube-dl -v <your command line>
|
|||||||
[debug] User config: []
|
[debug] User config: []
|
||||||
[debug] Command-line args: [u'-v', u'http://www.youtube.com/watch?v=BaW_jenozKcj']
|
[debug] Command-line args: [u'-v', u'http://www.youtube.com/watch?v=BaW_jenozKcj']
|
||||||
[debug] Encodings: locale cp1251, fs mbcs, out cp866, pref cp1251
|
[debug] Encodings: locale cp1251, fs mbcs, out cp866, pref cp1251
|
||||||
[debug] youtube-dl version 2016.07.03.1
|
[debug] youtube-dl version 2016.07.05
|
||||||
[debug] Python version 2.7.11 - Windows-2003Server-5.2.3790-SP2
|
[debug] Python version 2.7.11 - Windows-2003Server-5.2.3790-SP2
|
||||||
[debug] exe versions: ffmpeg N-75573-g1d0487f, ffprobe N-75573-g1d0487f, rtmpdump 2.4
|
[debug] exe versions: ffmpeg N-75573-g1d0487f, ffprobe N-75573-g1d0487f, rtmpdump 2.4
|
||||||
[debug] Proxy map: {}
|
[debug] Proxy map: {}
|
||||||
|
|||||||
@@ -103,9 +103,9 @@ which means you can modify it, redistribute it or use it however you like.
|
|||||||
(experimental)
|
(experimental)
|
||||||
-6, --force-ipv6 Make all connections via IPv6
|
-6, --force-ipv6 Make all connections via IPv6
|
||||||
(experimental)
|
(experimental)
|
||||||
--cn-verification-proxy URL Use this proxy to verify the IP address for
|
--geo-verification-proxy URL Use this proxy to verify the IP address for
|
||||||
some Chinese sites. The default proxy
|
some geo-restricted sites. The default
|
||||||
specified by --proxy (or none, if the
|
proxy specified by --proxy (or none, if the
|
||||||
options is not present) is used for the
|
options is not present) is used for the
|
||||||
actual downloading. (experimental)
|
actual downloading. (experimental)
|
||||||
|
|
||||||
@@ -424,7 +424,7 @@ which means you can modify it, redistribute it or use it however you like.
|
|||||||
|
|
||||||
# CONFIGURATION
|
# CONFIGURATION
|
||||||
|
|
||||||
You can configure youtube-dl by placing any supported command line option to a configuration file. On Linux and OS X, the system wide configuration file is located at `/etc/youtube-dl.conf` and the user wide configuration file at `~/.config/youtube-dl/config`. On Windows, the user wide configuration file locations are `%APPDATA%\youtube-dl\config.txt` or `C:\Users\<user name>\youtube-dl.conf`.
|
You can configure youtube-dl by placing any supported command line option to a configuration file. On Linux and OS X, the system wide configuration file is located at `/etc/youtube-dl.conf` and the user wide configuration file at `~/.config/youtube-dl/config`. On Windows, the user wide configuration file locations are `%APPDATA%\youtube-dl\config.txt` or `C:\Users\<user name>\youtube-dl.conf`. Note that by default configuration file may not exist so you may need to create it yourself.
|
||||||
|
|
||||||
For example, with the following configuration file youtube-dl will always extract the audio, not copy the mtime, use a proxy and save all videos under `Movies` directory in your home directory:
|
For example, with the following configuration file youtube-dl will always extract the audio, not copy the mtime, use a proxy and save all videos under `Movies` directory in your home directory:
|
||||||
```
|
```
|
||||||
|
|||||||
41
devscripts/show-downloads-statistics.py
Normal file
41
devscripts/show-downloads-statistics.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
from youtube_dl.compat import (
|
||||||
|
compat_print,
|
||||||
|
compat_urllib_request,
|
||||||
|
)
|
||||||
|
from youtube_dl.utils import format_bytes
|
||||||
|
|
||||||
|
|
||||||
|
def format_size(bytes):
|
||||||
|
return '%s (%d bytes)' % (format_bytes(bytes), bytes)
|
||||||
|
|
||||||
|
|
||||||
|
total_bytes = 0
|
||||||
|
|
||||||
|
releases = json.loads(compat_urllib_request.urlopen(
|
||||||
|
'https://api.github.com/repos/rg3/youtube-dl/releases').read().decode('utf-8'))
|
||||||
|
|
||||||
|
for release in releases:
|
||||||
|
compat_print(release['name'])
|
||||||
|
for asset in release['assets']:
|
||||||
|
asset_name = asset['name']
|
||||||
|
total_bytes += asset['download_count'] * asset['size']
|
||||||
|
if all(not re.match(p, asset_name) for p in (
|
||||||
|
r'^youtube-dl$',
|
||||||
|
r'^youtube-dl-\d{4}\.\d{2}\.\d{2}(?:\.\d+)?\.tar\.gz$',
|
||||||
|
r'^youtube-dl\.exe$')):
|
||||||
|
continue
|
||||||
|
compat_print(
|
||||||
|
' %s size: %s downloads: %d'
|
||||||
|
% (asset_name, format_size(asset['size']), asset['download_count']))
|
||||||
|
|
||||||
|
compat_print('total downloads traffic: %s' % format_size(total_bytes))
|
||||||
@@ -138,27 +138,27 @@ class TestProxy(unittest.TestCase):
|
|||||||
self.proxy_thread.daemon = True
|
self.proxy_thread.daemon = True
|
||||||
self.proxy_thread.start()
|
self.proxy_thread.start()
|
||||||
|
|
||||||
self.cn_proxy = compat_http_server.HTTPServer(
|
self.geo_proxy = compat_http_server.HTTPServer(
|
||||||
('localhost', 0), _build_proxy_handler('cn'))
|
('localhost', 0), _build_proxy_handler('geo'))
|
||||||
self.cn_port = http_server_port(self.cn_proxy)
|
self.geo_port = http_server_port(self.geo_proxy)
|
||||||
self.cn_proxy_thread = threading.Thread(target=self.cn_proxy.serve_forever)
|
self.geo_proxy_thread = threading.Thread(target=self.geo_proxy.serve_forever)
|
||||||
self.cn_proxy_thread.daemon = True
|
self.geo_proxy_thread.daemon = True
|
||||||
self.cn_proxy_thread.start()
|
self.geo_proxy_thread.start()
|
||||||
|
|
||||||
def test_proxy(self):
|
def test_proxy(self):
|
||||||
cn_proxy = 'localhost:{0}'.format(self.cn_port)
|
geo_proxy = 'localhost:{0}'.format(self.geo_port)
|
||||||
ydl = YoutubeDL({
|
ydl = YoutubeDL({
|
||||||
'proxy': 'localhost:{0}'.format(self.port),
|
'proxy': 'localhost:{0}'.format(self.port),
|
||||||
'cn_verification_proxy': cn_proxy,
|
'geo_verification_proxy': geo_proxy,
|
||||||
})
|
})
|
||||||
url = 'http://foo.com/bar'
|
url = 'http://foo.com/bar'
|
||||||
response = ydl.urlopen(url).read().decode('utf-8')
|
response = ydl.urlopen(url).read().decode('utf-8')
|
||||||
self.assertEqual(response, 'normal: {0}'.format(url))
|
self.assertEqual(response, 'normal: {0}'.format(url))
|
||||||
|
|
||||||
req = compat_urllib_request.Request(url)
|
req = compat_urllib_request.Request(url)
|
||||||
req.add_header('Ytdl-request-proxy', cn_proxy)
|
req.add_header('Ytdl-request-proxy', geo_proxy)
|
||||||
response = ydl.urlopen(req).read().decode('utf-8')
|
response = ydl.urlopen(req).read().decode('utf-8')
|
||||||
self.assertEqual(response, 'cn: {0}'.format(url))
|
self.assertEqual(response, 'geo: {0}'.format(url))
|
||||||
|
|
||||||
def test_proxy_with_idn(self):
|
def test_proxy_with_idn(self):
|
||||||
ydl = YoutubeDL({
|
ydl = YoutubeDL({
|
||||||
|
|||||||
@@ -405,6 +405,12 @@ class TestUtil(unittest.TestCase):
|
|||||||
self.assertEqual(res_url, url)
|
self.assertEqual(res_url, url)
|
||||||
self.assertEqual(res_data, None)
|
self.assertEqual(res_data, None)
|
||||||
|
|
||||||
|
smug_url = smuggle_url(url, {'a': 'b'})
|
||||||
|
smug_smug_url = smuggle_url(smug_url, {'c': 'd'})
|
||||||
|
res_url, res_data = unsmuggle_url(smug_smug_url)
|
||||||
|
self.assertEqual(res_url, url)
|
||||||
|
self.assertEqual(res_data, {'a': 'b', 'c': 'd'})
|
||||||
|
|
||||||
def test_shell_quote(self):
|
def test_shell_quote(self):
|
||||||
args = ['ffmpeg', '-i', encodeFilename('ñ€ß\'.mp4')]
|
args = ['ffmpeg', '-i', encodeFilename('ñ€ß\'.mp4')]
|
||||||
self.assertEqual(shell_quote(args), """ffmpeg -i 'ñ€ß'"'"'.mp4'""")
|
self.assertEqual(shell_quote(args), """ffmpeg -i 'ñ€ß'"'"'.mp4'""")
|
||||||
|
|||||||
@@ -196,8 +196,8 @@ class YoutubeDL(object):
|
|||||||
prefer_insecure: Use HTTP instead of HTTPS to retrieve information.
|
prefer_insecure: Use HTTP instead of HTTPS to retrieve information.
|
||||||
At the moment, this is only supported by YouTube.
|
At the moment, this is only supported by YouTube.
|
||||||
proxy: URL of the proxy server to use
|
proxy: URL of the proxy server to use
|
||||||
cn_verification_proxy: URL of the proxy to use for IP address verification
|
geo_verification_proxy: URL of the proxy to use for IP address verification
|
||||||
on Chinese sites. (Experimental)
|
on geo-restricted sites. (Experimental)
|
||||||
socket_timeout: Time to wait for unresponsive hosts, in seconds
|
socket_timeout: Time to wait for unresponsive hosts, in seconds
|
||||||
bidi_workaround: Work around buggy terminals without bidirectional text
|
bidi_workaround: Work around buggy terminals without bidirectional text
|
||||||
support, using fridibi
|
support, using fridibi
|
||||||
@@ -304,6 +304,11 @@ class YoutubeDL(object):
|
|||||||
self.params.update(params)
|
self.params.update(params)
|
||||||
self.cache = Cache(self)
|
self.cache = Cache(self)
|
||||||
|
|
||||||
|
if self.params.get('cn_verification_proxy') is not None:
|
||||||
|
self.report_warning('--cn-verification-proxy is deprecated. Use --geo-verification-proxy instead.')
|
||||||
|
if self.params.get('geo_verification_proxy') is None:
|
||||||
|
self.params['geo_verification_proxy'] = self.params['cn_verification_proxy']
|
||||||
|
|
||||||
if params.get('bidi_workaround', False):
|
if params.get('bidi_workaround', False):
|
||||||
try:
|
try:
|
||||||
import pty
|
import pty
|
||||||
|
|||||||
@@ -382,6 +382,8 @@ def _real_main(argv=None):
|
|||||||
'external_downloader_args': external_downloader_args,
|
'external_downloader_args': external_downloader_args,
|
||||||
'postprocessor_args': postprocessor_args,
|
'postprocessor_args': postprocessor_args,
|
||||||
'cn_verification_proxy': opts.cn_verification_proxy,
|
'cn_verification_proxy': opts.cn_verification_proxy,
|
||||||
|
'geo_verification_proxy': opts.geo_verification_proxy,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
with YoutubeDL(ydl_opts) as ydl:
|
with YoutubeDL(ydl_opts) as ydl:
|
||||||
|
|||||||
@@ -585,6 +585,13 @@ class BrightcoveNewIE(InfoExtractor):
|
|||||||
'format_id': build_format_id('rtmp'),
|
'format_id': build_format_id('rtmp'),
|
||||||
})
|
})
|
||||||
formats.append(f)
|
formats.append(f)
|
||||||
|
|
||||||
|
errors = json_data.get('errors')
|
||||||
|
if not formats and errors:
|
||||||
|
error = errors[0]
|
||||||
|
raise ExtractorError(
|
||||||
|
error.get('message') or error.get('error_subcode') or error['error_code'], expected=True)
|
||||||
|
|
||||||
self._sort_formats(formats)
|
self._sort_formats(formats)
|
||||||
|
|
||||||
subtitles = {}
|
subtitles = {}
|
||||||
|
|||||||
@@ -1729,6 +1729,13 @@ class InfoExtractor(object):
|
|||||||
def _mark_watched(self, *args, **kwargs):
|
def _mark_watched(self, *args, **kwargs):
|
||||||
raise NotImplementedError('This method must be implemented by subclasses')
|
raise NotImplementedError('This method must be implemented by subclasses')
|
||||||
|
|
||||||
|
def geo_verification_headers(self):
|
||||||
|
headers = {}
|
||||||
|
geo_verification_proxy = self._downloader.params.get('geo_verification_proxy')
|
||||||
|
if geo_verification_proxy:
|
||||||
|
headers['Ytdl-request-proxy'] = geo_verification_proxy
|
||||||
|
return headers
|
||||||
|
|
||||||
|
|
||||||
class SearchInfoExtractor(InfoExtractor):
|
class SearchInfoExtractor(InfoExtractor):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1295,6 +1295,21 @@ class GenericIE(InfoExtractor):
|
|||||||
'uploader': 'cylus cyrus',
|
'uploader': 'cylus cyrus',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
# video stored on custom kaltura server
|
||||||
|
'url': 'http://www.expansion.com/multimedia/videos.html?media=EQcM30NHIPv',
|
||||||
|
'md5': '537617d06e64dfed891fa1593c4b30cc',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '0_1iotm5bh',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Elecciones británicas: 5 lecciones para Rajoy',
|
||||||
|
'description': 'md5:435a89d68b9760b92ce67ed227055f16',
|
||||||
|
'uploader_id': 'videos.expansion@el-mundo.net',
|
||||||
|
'upload_date': '20150429',
|
||||||
|
'timestamp': 1430303472,
|
||||||
|
},
|
||||||
|
'add_ie': ['Kaltura'],
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
def report_following_redirect(self, new_url):
|
def report_following_redirect(self, new_url):
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ class IqiyiIE(InfoExtractor):
|
|||||||
|
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
'url': 'http://www.iqiyi.com/v_19rrojlavg.html',
|
'url': 'http://www.iqiyi.com/v_19rrojlavg.html',
|
||||||
'md5': '5b0591f55961117155430b5d544fdb01',
|
# MD5 checksum differs on my machine and Travis CI
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '9c1fb1b99d192b21c559e5a1a2cb3c73',
|
'id': '9c1fb1b99d192b21c559e5a1a2cb3c73',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
@@ -293,14 +293,10 @@ class IqiyiIE(InfoExtractor):
|
|||||||
't': tm,
|
't': tm,
|
||||||
}
|
}
|
||||||
|
|
||||||
headers = {}
|
|
||||||
cn_verification_proxy = self._downloader.params.get('cn_verification_proxy')
|
|
||||||
if cn_verification_proxy:
|
|
||||||
headers['Ytdl-request-proxy'] = cn_verification_proxy
|
|
||||||
return self._download_json(
|
return self._download_json(
|
||||||
'http://cache.m.iqiyi.com/jp/tmts/%s/%s/' % (tvid, video_id),
|
'http://cache.m.iqiyi.com/jp/tmts/%s/%s/' % (tvid, video_id),
|
||||||
video_id, transform_source=lambda s: remove_start(s, 'var tvInfoJs='),
|
video_id, transform_source=lambda s: remove_start(s, 'var tvInfoJs='),
|
||||||
query=params, headers=headers)
|
query=params, headers=self.geo_verification_headers())
|
||||||
|
|
||||||
def _extract_playlist(self, webpage):
|
def _extract_playlist(self, webpage):
|
||||||
PAGE_SIZE = 50
|
PAGE_SIZE = 50
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import base64
|
|||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
from ..compat import (
|
from ..compat import (
|
||||||
compat_urllib_parse_urlencode,
|
|
||||||
compat_urlparse,
|
compat_urlparse,
|
||||||
compat_parse_qs,
|
compat_parse_qs,
|
||||||
)
|
)
|
||||||
@@ -15,6 +14,7 @@ from ..utils import (
|
|||||||
ExtractorError,
|
ExtractorError,
|
||||||
int_or_none,
|
int_or_none,
|
||||||
unsmuggle_url,
|
unsmuggle_url,
|
||||||
|
smuggle_url,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -34,7 +34,8 @@ class KalturaIE(InfoExtractor):
|
|||||||
)(?:/(?P<path>[^?]+))?(?:\?(?P<query>.*))?
|
)(?:/(?P<path>[^?]+))?(?:\?(?P<query>.*))?
|
||||||
)
|
)
|
||||||
'''
|
'''
|
||||||
_API_BASE = 'http://cdnapi.kaltura.com/api_v3/index.php?'
|
_SERVICE_URL = 'http://cdnapi.kaltura.com'
|
||||||
|
_SERVICE_BASE = '/api_v3/index.php'
|
||||||
_TESTS = [
|
_TESTS = [
|
||||||
{
|
{
|
||||||
'url': 'kaltura:269692:1_1jc2y3e4',
|
'url': 'kaltura:269692:1_1jc2y3e4',
|
||||||
@@ -88,18 +89,26 @@ class KalturaIE(InfoExtractor):
|
|||||||
(?P<q3>["\'])(?P<id>.+?)(?P=q3)
|
(?P<q3>["\'])(?P<id>.+?)(?P=q3)
|
||||||
''', webpage))
|
''', webpage))
|
||||||
if mobj:
|
if mobj:
|
||||||
return 'kaltura:%(partner_id)s:%(id)s' % mobj.groupdict()
|
embed_info = mobj.groupdict()
|
||||||
|
url = 'kaltura:%(partner_id)s:%(id)s' % embed_info
|
||||||
|
escaped_pid = re.escape(embed_info['partner_id'])
|
||||||
|
service_url = re.search(
|
||||||
|
r'<script[^>]+src=["\']((?:https?:)?//.+?)/p/%s/sp/%s00/embedIframeJs' % (escaped_pid, escaped_pid),
|
||||||
|
webpage)
|
||||||
|
if service_url:
|
||||||
|
url = smuggle_url(url, {'service_url': service_url.group(1)})
|
||||||
|
return url
|
||||||
|
|
||||||
def _kaltura_api_call(self, video_id, actions, *args, **kwargs):
|
def _kaltura_api_call(self, video_id, actions, service_url=None, *args, **kwargs):
|
||||||
params = actions[0]
|
params = actions[0]
|
||||||
if len(actions) > 1:
|
if len(actions) > 1:
|
||||||
for i, a in enumerate(actions[1:], start=1):
|
for i, a in enumerate(actions[1:], start=1):
|
||||||
for k, v in a.items():
|
for k, v in a.items():
|
||||||
params['%d:%s' % (i, k)] = v
|
params['%d:%s' % (i, k)] = v
|
||||||
|
|
||||||
query = compat_urllib_parse_urlencode(params)
|
data = self._download_json(
|
||||||
url = self._API_BASE + query
|
(service_url or self._SERVICE_URL) + self._SERVICE_BASE,
|
||||||
data = self._download_json(url, video_id, *args, **kwargs)
|
video_id, query=params, *args, **kwargs)
|
||||||
|
|
||||||
status = data if len(actions) == 1 else data[0]
|
status = data if len(actions) == 1 else data[0]
|
||||||
if status.get('objectType') == 'KalturaAPIException':
|
if status.get('objectType') == 'KalturaAPIException':
|
||||||
@@ -108,7 +117,7 @@ class KalturaIE(InfoExtractor):
|
|||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def _get_kaltura_signature(self, video_id, partner_id):
|
def _get_kaltura_signature(self, video_id, partner_id, service_url=None):
|
||||||
actions = [{
|
actions = [{
|
||||||
'apiVersion': '3.1',
|
'apiVersion': '3.1',
|
||||||
'expiry': 86400,
|
'expiry': 86400,
|
||||||
@@ -118,10 +127,10 @@ class KalturaIE(InfoExtractor):
|
|||||||
'widgetId': '_%s' % partner_id,
|
'widgetId': '_%s' % partner_id,
|
||||||
}]
|
}]
|
||||||
return self._kaltura_api_call(
|
return self._kaltura_api_call(
|
||||||
video_id, actions, note='Downloading Kaltura signature')['ks']
|
video_id, actions, service_url, note='Downloading Kaltura signature')['ks']
|
||||||
|
|
||||||
def _get_video_info(self, video_id, partner_id):
|
def _get_video_info(self, video_id, partner_id, service_url=None):
|
||||||
signature = self._get_kaltura_signature(video_id, partner_id)
|
signature = self._get_kaltura_signature(video_id, partner_id, service_url)
|
||||||
actions = [
|
actions = [
|
||||||
{
|
{
|
||||||
'action': 'null',
|
'action': 'null',
|
||||||
@@ -144,7 +153,7 @@ class KalturaIE(InfoExtractor):
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
return self._kaltura_api_call(
|
return self._kaltura_api_call(
|
||||||
video_id, actions, note='Downloading video info JSON')
|
video_id, actions, service_url, note='Downloading video info JSON')
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
url, smuggled_data = unsmuggle_url(url, {})
|
url, smuggled_data = unsmuggle_url(url, {})
|
||||||
@@ -153,7 +162,7 @@ class KalturaIE(InfoExtractor):
|
|||||||
partner_id, entry_id = mobj.group('partner_id', 'id')
|
partner_id, entry_id = mobj.group('partner_id', 'id')
|
||||||
ks = None
|
ks = None
|
||||||
if partner_id and entry_id:
|
if partner_id and entry_id:
|
||||||
info, flavor_assets = self._get_video_info(entry_id, partner_id)
|
info, flavor_assets = self._get_video_info(entry_id, partner_id, smuggled_data.get('service_url'))
|
||||||
else:
|
else:
|
||||||
path, query = mobj.group('path', 'query')
|
path, query = mobj.group('path', 'query')
|
||||||
if not path and not query:
|
if not path and not query:
|
||||||
@@ -201,12 +210,17 @@ class KalturaIE(InfoExtractor):
|
|||||||
unsigned_url += '?referrer=%s' % referrer
|
unsigned_url += '?referrer=%s' % referrer
|
||||||
return unsigned_url
|
return unsigned_url
|
||||||
|
|
||||||
|
data_url = info['dataUrl']
|
||||||
|
if '/flvclipper/' in data_url:
|
||||||
|
data_url = re.sub(r'/flvclipper/.*', '/serveFlavor', data_url)
|
||||||
|
|
||||||
formats = []
|
formats = []
|
||||||
for f in flavor_assets:
|
for f in flavor_assets:
|
||||||
# Continue if asset is not ready
|
# Continue if asset is not ready
|
||||||
if f['status'] != 2:
|
if f['status'] != 2:
|
||||||
continue
|
continue
|
||||||
video_url = sign_url('%s/flavorId/%s' % (info['dataUrl'], f['id']))
|
video_url = sign_url(
|
||||||
|
'%s/flavorId/%s' % (data_url, f['id']))
|
||||||
formats.append({
|
formats.append({
|
||||||
'format_id': '%(fileExt)s-%(bitrate)s' % f,
|
'format_id': '%(fileExt)s-%(bitrate)s' % f,
|
||||||
'ext': f.get('fileExt'),
|
'ext': f.get('fileExt'),
|
||||||
@@ -219,9 +233,12 @@ class KalturaIE(InfoExtractor):
|
|||||||
'width': int_or_none(f.get('width')),
|
'width': int_or_none(f.get('width')),
|
||||||
'url': video_url,
|
'url': video_url,
|
||||||
})
|
})
|
||||||
m3u8_url = sign_url(info['dataUrl'].replace('format/url', 'format/applehttp'))
|
if '/playManifest/' in data_url:
|
||||||
formats.extend(self._extract_m3u8_formats(
|
m3u8_url = sign_url(data_url.replace(
|
||||||
m3u8_url, entry_id, 'mp4', 'm3u8_native', m3u8_id='hls', fatal=False))
|
'format/url', 'format/applehttp'))
|
||||||
|
formats.extend(self._extract_m3u8_formats(
|
||||||
|
m3u8_url, entry_id, 'mp4', 'm3u8_native',
|
||||||
|
m3u8_id='hls', fatal=False))
|
||||||
|
|
||||||
self._check_formats(formats, entry_id)
|
self._check_formats(formats, entry_id)
|
||||||
self._sort_formats(formats)
|
self._sort_formats(formats)
|
||||||
|
|||||||
@@ -26,11 +26,6 @@ class KuwoBaseIE(InfoExtractor):
|
|||||||
def _get_formats(self, song_id, tolerate_ip_deny=False):
|
def _get_formats(self, song_id, tolerate_ip_deny=False):
|
||||||
formats = []
|
formats = []
|
||||||
for file_format in self._FORMATS:
|
for file_format in self._FORMATS:
|
||||||
headers = {}
|
|
||||||
cn_verification_proxy = self._downloader.params.get('cn_verification_proxy')
|
|
||||||
if cn_verification_proxy:
|
|
||||||
headers['Ytdl-request-proxy'] = cn_verification_proxy
|
|
||||||
|
|
||||||
query = {
|
query = {
|
||||||
'format': file_format['ext'],
|
'format': file_format['ext'],
|
||||||
'br': file_format.get('br', ''),
|
'br': file_format.get('br', ''),
|
||||||
@@ -42,7 +37,7 @@ class KuwoBaseIE(InfoExtractor):
|
|||||||
song_url = self._download_webpage(
|
song_url = self._download_webpage(
|
||||||
'http://antiserver.kuwo.cn/anti.s',
|
'http://antiserver.kuwo.cn/anti.s',
|
||||||
song_id, note='Download %s url info' % file_format['format'],
|
song_id, note='Download %s url info' % file_format['format'],
|
||||||
query=query, headers=headers,
|
query=query, headers=self.geo_verification_headers(),
|
||||||
)
|
)
|
||||||
|
|
||||||
if song_url == 'IPDeny' and not tolerate_ip_deny:
|
if song_url == 'IPDeny' and not tolerate_ip_deny:
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
determine_ext,
|
|
||||||
js_to_json,
|
js_to_json,
|
||||||
|
smuggle_url,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -18,13 +18,16 @@ class LA7IE(InfoExtractor):
|
|||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
# 'src' is a plain URL
|
# 'src' is a plain URL
|
||||||
'url': 'http://www.la7.it/crozza/video/inccool8-02-10-2015-163722',
|
'url': 'http://www.la7.it/crozza/video/inccool8-02-10-2015-163722',
|
||||||
'md5': '6054674766e7988d3e02f2148ff92180',
|
'md5': '8b613ffc0c4bf9b9e377169fc19c214c',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': 'inccool8-02-10-2015-163722',
|
'id': 'inccool8-02-10-2015-163722',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'title': 'Inc.Cool8',
|
'title': 'Inc.Cool8',
|
||||||
'description': 'Benvenuti nell\'incredibile mondo della INC. COOL. 8. dove “INC.” sta per “Incorporated” “COOL” sta per “fashion” ed Eight sta per il gesto atletico',
|
'description': 'Benvenuti nell\'incredibile mondo della INC. COOL. 8. dove “INC.” sta per “Incorporated” “COOL” sta per “fashion” ed Eight sta per il gesto atletico',
|
||||||
'thumbnail': 're:^https?://.*',
|
'thumbnail': 're:^https?://.*',
|
||||||
|
'uploader_id': 'kdla7pillole@iltrovatore.it',
|
||||||
|
'timestamp': 1443814869,
|
||||||
|
'upload_date': '20151002',
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
# 'src' is a dictionary
|
# 'src' is a dictionary
|
||||||
@@ -49,26 +52,14 @@ class LA7IE(InfoExtractor):
|
|||||||
self._search_regex(r'videoLa7\(({[^;]+})\);', webpage, 'player data'),
|
self._search_regex(r'videoLa7\(({[^;]+})\);', webpage, 'player data'),
|
||||||
video_id, transform_source=js_to_json)
|
video_id, transform_source=js_to_json)
|
||||||
|
|
||||||
source = player_data['src']
|
|
||||||
source_urls = source.values() if isinstance(source, dict) else [source]
|
|
||||||
|
|
||||||
formats = []
|
|
||||||
for source_url in source_urls:
|
|
||||||
ext = determine_ext(source_url)
|
|
||||||
if ext == 'm3u8':
|
|
||||||
formats.extend(self._extract_m3u8_formats(
|
|
||||||
source_url, video_id, ext='mp4',
|
|
||||||
entry_protocol='m3u8_native', m3u8_id='hls'))
|
|
||||||
else:
|
|
||||||
formats.append({
|
|
||||||
'url': source_url,
|
|
||||||
})
|
|
||||||
self._sort_formats(formats)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
'_type': 'url_transparent',
|
||||||
|
'url': smuggle_url('kaltura:103:%s' % player_data['vid'], {
|
||||||
|
'service_url': 'http://kdam.iltrovatore.it',
|
||||||
|
}),
|
||||||
'id': video_id,
|
'id': video_id,
|
||||||
'title': player_data['title'],
|
'title': player_data['title'],
|
||||||
'description': self._og_search_description(webpage, default=None),
|
'description': self._og_search_description(webpage, default=None),
|
||||||
'thumbnail': player_data.get('poster'),
|
'thumbnail': player_data.get('poster'),
|
||||||
'formats': formats,
|
'ie_key': 'Kaltura',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ from ..utils import (
|
|||||||
int_or_none,
|
int_or_none,
|
||||||
orderedSet,
|
orderedSet,
|
||||||
parse_iso8601,
|
parse_iso8601,
|
||||||
sanitized_Request,
|
|
||||||
str_or_none,
|
str_or_none,
|
||||||
url_basename,
|
url_basename,
|
||||||
urshift,
|
urshift,
|
||||||
@@ -121,16 +120,11 @@ class LeIE(InfoExtractor):
|
|||||||
'tkey': self.calc_time_key(int(time.time())),
|
'tkey': self.calc_time_key(int(time.time())),
|
||||||
'domain': 'www.le.com'
|
'domain': 'www.le.com'
|
||||||
}
|
}
|
||||||
play_json_req = sanitized_Request(
|
|
||||||
'http://api.le.com/mms/out/video/playJson?' + compat_urllib_parse_urlencode(params)
|
|
||||||
)
|
|
||||||
cn_verification_proxy = self._downloader.params.get('cn_verification_proxy')
|
|
||||||
if cn_verification_proxy:
|
|
||||||
play_json_req.add_header('Ytdl-request-proxy', cn_verification_proxy)
|
|
||||||
|
|
||||||
play_json = self._download_json(
|
play_json = self._download_json(
|
||||||
play_json_req,
|
'http://api.le.com/mms/out/video/playJson',
|
||||||
media_id, 'Downloading playJson data')
|
media_id, 'Downloading playJson data', query=params,
|
||||||
|
headers=self.geo_verification_headers())
|
||||||
|
|
||||||
# Check for errors
|
# Check for errors
|
||||||
playstatus = play_json['playstatus']
|
playstatus = play_json['playstatus']
|
||||||
|
|||||||
@@ -82,6 +82,10 @@ class PornHubIE(InfoExtractor):
|
|||||||
# removed by uploader
|
# removed by uploader
|
||||||
'url': 'http://www.pornhub.com/view_video.php?viewkey=ph572716d15a111',
|
'url': 'http://www.pornhub.com/view_video.php?viewkey=ph572716d15a111',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
# private video
|
||||||
|
'url': 'http://www.pornhub.com/view_video.php?viewkey=ph56fd731fce6b7',
|
||||||
|
'only_matching': True,
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://www.thumbzilla.com/video/ph56c6114abd99a/horny-girlfriend-sex',
|
'url': 'https://www.thumbzilla.com/video/ph56c6114abd99a/horny-girlfriend-sex',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
@@ -107,7 +111,7 @@ class PornHubIE(InfoExtractor):
|
|||||||
webpage = self._download_webpage(req, video_id)
|
webpage = self._download_webpage(req, video_id)
|
||||||
|
|
||||||
error_msg = self._html_search_regex(
|
error_msg = self._html_search_regex(
|
||||||
r'(?s)<div[^>]+class=(["\']).*?\bremoved\b.*?\1[^>]*>(?P<error>.+?)</div>',
|
r'(?s)<div[^>]+class=(["\']).*?\b(?:removed|userMessageSection)\b.*?\1[^>]*>(?P<error>.+?)</div>',
|
||||||
webpage, 'error message', default=None, group='error')
|
webpage, 'error message', default=None, group='error')
|
||||||
if error_msg:
|
if error_msg:
|
||||||
error_msg = re.sub(r'\s+', ' ', error_msg)
|
error_msg = re.sub(r'\s+', ' ', error_msg)
|
||||||
|
|||||||
@@ -20,17 +20,12 @@ class RaiBaseIE(InfoExtractor):
|
|||||||
formats = []
|
formats = []
|
||||||
|
|
||||||
for platform in ('mon', 'flash', 'native'):
|
for platform in ('mon', 'flash', 'native'):
|
||||||
headers = {}
|
|
||||||
# TODO: rename --cn-verification-proxy
|
|
||||||
cn_verification_proxy = self._downloader.params.get('cn_verification_proxy')
|
|
||||||
if cn_verification_proxy:
|
|
||||||
headers['Ytdl-request-proxy'] = cn_verification_proxy
|
|
||||||
|
|
||||||
relinker = self._download_xml(
|
relinker = self._download_xml(
|
||||||
relinker_url, video_id,
|
relinker_url, video_id,
|
||||||
note='Downloading XML metadata for platform %s' % platform,
|
note='Downloading XML metadata for platform %s' % platform,
|
||||||
transform_source=fix_xml_ampersands,
|
transform_source=fix_xml_ampersands,
|
||||||
query={'output': 45, 'pl': platform}, headers=headers)
|
query={'output': 45, 'pl': platform},
|
||||||
|
headers=self.geo_verification_headers())
|
||||||
|
|
||||||
media_url = find_xpath_attr(relinker, './url', 'type', 'content').text
|
media_url = find_xpath_attr(relinker, './url', 'type', 'content').text
|
||||||
if media_url == 'http://download.rai.it/video_no_available.mp4':
|
if media_url == 'http://download.rai.it/video_no_available.mp4':
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ from ..compat import (
|
|||||||
compat_str,
|
compat_str,
|
||||||
compat_urllib_parse_urlencode,
|
compat_urllib_parse_urlencode,
|
||||||
)
|
)
|
||||||
from ..utils import (
|
from ..utils import ExtractorError
|
||||||
ExtractorError,
|
|
||||||
sanitized_Request,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class SohuIE(InfoExtractor):
|
class SohuIE(InfoExtractor):
|
||||||
@@ -96,15 +93,10 @@ class SohuIE(InfoExtractor):
|
|||||||
else:
|
else:
|
||||||
base_data_url = 'http://hot.vrs.sohu.com/vrs_flash.action?vid='
|
base_data_url = 'http://hot.vrs.sohu.com/vrs_flash.action?vid='
|
||||||
|
|
||||||
req = sanitized_Request(base_data_url + vid_id)
|
|
||||||
|
|
||||||
cn_verification_proxy = self._downloader.params.get('cn_verification_proxy')
|
|
||||||
if cn_verification_proxy:
|
|
||||||
req.add_header('Ytdl-request-proxy', cn_verification_proxy)
|
|
||||||
|
|
||||||
return self._download_json(
|
return self._download_json(
|
||||||
req, video_id,
|
base_data_url + vid_id, video_id,
|
||||||
'Downloading JSON data for %s' % vid_id)
|
'Downloading JSON data for %s' % vid_id,
|
||||||
|
headers=self.geo_verification_headers())
|
||||||
|
|
||||||
mobj = re.match(self._VALID_URL, url)
|
mobj = re.match(self._VALID_URL, url)
|
||||||
video_id = mobj.group('id')
|
video_id = mobj.group('id')
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ from ..utils import (
|
|||||||
mimetype2ext,
|
mimetype2ext,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from .brightcove import BrightcoveNewIE
|
||||||
from .nbc import NBCSportsVPlayerIE
|
from .nbc import NBCSportsVPlayerIE
|
||||||
|
|
||||||
|
|
||||||
@@ -227,7 +228,12 @@ class YahooIE(InfoExtractor):
|
|||||||
# Look for NBCSports iframes
|
# Look for NBCSports iframes
|
||||||
nbc_sports_url = NBCSportsVPlayerIE._extract_url(webpage)
|
nbc_sports_url = NBCSportsVPlayerIE._extract_url(webpage)
|
||||||
if nbc_sports_url:
|
if nbc_sports_url:
|
||||||
return self.url_result(nbc_sports_url, 'NBCSportsVPlayer')
|
return self.url_result(nbc_sports_url, NBCSportsVPlayerIE.ie_key())
|
||||||
|
|
||||||
|
# Look for Brightcove New Studio embeds
|
||||||
|
bc_url = BrightcoveNewIE._extract_url(webpage)
|
||||||
|
if bc_url:
|
||||||
|
return self.url_result(bc_url, BrightcoveNewIE.ie_key())
|
||||||
|
|
||||||
# Query result is often embedded in webpage as JSON. Sometimes explicit requests
|
# Query result is often embedded in webpage as JSON. Sometimes explicit requests
|
||||||
# to video API results in a failure with geo restriction reason therefore using
|
# to video API results in a failure with geo restriction reason therefore using
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ from ..compat import (
|
|||||||
from ..utils import (
|
from ..utils import (
|
||||||
ExtractorError,
|
ExtractorError,
|
||||||
get_element_by_attribute,
|
get_element_by_attribute,
|
||||||
sanitized_Request,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -218,14 +217,10 @@ class YoukuIE(InfoExtractor):
|
|||||||
headers = {
|
headers = {
|
||||||
'Referer': req_url,
|
'Referer': req_url,
|
||||||
}
|
}
|
||||||
|
headers.update(self.geo_verification_headers())
|
||||||
self._set_cookie('youku.com', 'xreferrer', 'http://www.youku.com')
|
self._set_cookie('youku.com', 'xreferrer', 'http://www.youku.com')
|
||||||
req = sanitized_Request(req_url, headers=headers)
|
|
||||||
|
|
||||||
cn_verification_proxy = self._downloader.params.get('cn_verification_proxy')
|
raw_data = self._download_json(req_url, video_id, note=note, headers=headers)
|
||||||
if cn_verification_proxy:
|
|
||||||
req.add_header('Ytdl-request-proxy', cn_verification_proxy)
|
|
||||||
|
|
||||||
raw_data = self._download_json(req, video_id, note=note)
|
|
||||||
|
|
||||||
return raw_data['data']
|
return raw_data['data']
|
||||||
|
|
||||||
|
|||||||
@@ -209,11 +209,16 @@ def parseOpts(overrideArguments=None):
|
|||||||
action='store_const', const='::', dest='source_address',
|
action='store_const', const='::', dest='source_address',
|
||||||
help='Make all connections via IPv6 (experimental)',
|
help='Make all connections via IPv6 (experimental)',
|
||||||
)
|
)
|
||||||
|
network.add_option(
|
||||||
|
'--geo-verification-proxy',
|
||||||
|
dest='geo_verification_proxy', default=None, metavar='URL',
|
||||||
|
help='Use this proxy to verify the IP address for some geo-restricted sites. '
|
||||||
|
'The default proxy specified by --proxy (or none, if the options is not present) is used for the actual downloading. (experimental)'
|
||||||
|
)
|
||||||
network.add_option(
|
network.add_option(
|
||||||
'--cn-verification-proxy',
|
'--cn-verification-proxy',
|
||||||
dest='cn_verification_proxy', default=None, metavar='URL',
|
dest='cn_verification_proxy', default=None, metavar='URL',
|
||||||
help='Use this proxy to verify the IP address for some Chinese sites. '
|
help=optparse.SUPPRESS_HELP,
|
||||||
'The default proxy specified by --proxy (or none, if the options is not present) is used for the actual downloading. (experimental)'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
selection = optparse.OptionGroup(parser, 'Video Selection')
|
selection = optparse.OptionGroup(parser, 'Video Selection')
|
||||||
|
|||||||
@@ -1444,6 +1444,8 @@ def shell_quote(args):
|
|||||||
def smuggle_url(url, data):
|
def smuggle_url(url, data):
|
||||||
""" Pass additional data in a URL for internal use. """
|
""" Pass additional data in a URL for internal use. """
|
||||||
|
|
||||||
|
url, idata = unsmuggle_url(url, {})
|
||||||
|
data.update(idata)
|
||||||
sdata = compat_urllib_parse_urlencode(
|
sdata = compat_urllib_parse_urlencode(
|
||||||
{'__youtubedl_smuggle': json.dumps(data)})
|
{'__youtubedl_smuggle': json.dumps(data)})
|
||||||
return url + '#' + sdata
|
return url + '#' + sdata
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
__version__ = '2016.07.03.1'
|
__version__ = '2016.07.05'
|
||||||
|
|||||||
Reference in New Issue
Block a user