]> jfr.im git - yt-dlp.git/blame - youtube_dl/extractor/generic.py
[extractor/common] Extract format id from label attribute of source tag for HTML5...
[yt-dlp.git] / youtube_dl / extractor / generic.py
CommitLineData
dcdb292f 1# coding: utf-8
cfe50f04 2
79649588
PH
3from __future__ import unicode_literals
4
9b122384
PH
5import os
6import re
6c91a5a7 7import sys
9b122384
PH
8
9from .common import InfoExtractor
fc9713a1 10from .youtube import YoutubeIE
8c25f81b 11from ..compat import (
f7854627 12 compat_etree_fromstring,
4e363703 13 compat_str,
1ddb9456 14 compat_urllib_parse_unquote,
a5caba1e 15 compat_urlparse,
f7300c5c 16 compat_xml_parse_error,
8c25f81b
PH
17)
18from ..utils import (
b759a0d4 19 determine_ext,
9b122384 20 ExtractorError,
c8e9a235 21 float_or_none,
aa94a6d3 22 HEADRequest,
61ca9a80 23 is_html,
a4a554a7 24 js_to_json,
ed2d6a19 25 orderedSet,
5c2266df 26 sanitized_Request,
9d4660ca
PH
27 smuggle_url,
28 unescapeHTML,
42393ce2 29 unified_strdate,
4d54ef20 30 unsmuggle_url,
416c7fcb 31 UnsupportedError,
76c73715 32 xpath_text,
9b122384 33)
b7a8c1bc 34from .commonprotocols import RtmpIE
ed126900 35from .brightcove import (
4fcaa4f4 36 BrightcoveLegacyIE,
5c17f0a6 37 BrightcoveNewIE,
ed126900 38)
3f59b015
S
39from .nexx import (
40 NexxIE,
41 NexxEmbedIE,
42)
a2edf2e7 43from .nbc import NBCSportsVPlayerIE
c0d0b01f 44from .ooyala import OoyalaIE
93d020dd 45from .rutv import RUTVIE
954c1d05 46from .tvc import TVCIE
d40a3b5b 47from .sportbox import SportBoxEmbedIE
cb3ac1c6 48from .smotri import SmotriIE
6dd94d3a 49from .myvi import MyviIE
1419fafd 50from .condenast import CondeNastIE
418c5cc3 51from .udn import UDNEmbedIE
2fe1b5bd 52from .senateisvp import SenateISVPIE
bab19a8e 53from .svt import SVTIE
65d161c4 54from .pornhub import PornHubIE
2bb5b6d0 55from .xhamster import XHamsterEmbedIE
2c9ca782 56from .tnaflix import TNAFlixNetworkEmbedIE
37e7a71c 57from .drtuber import DrTuberIE
e28ed498 58from .redtube import RedTubeIE
b407e173 59from .vimeo import VimeoIE
ad213a1d
YCH
60from .dailymotion import (
61 DailymotionIE,
62 DailymotionCloudIE,
63)
71a1db89 64from .dailymail import DailyMailIE
1ac1c4c2 65from .onionstudios import OnionStudiosIE
67167920 66from .viewlift import ViewLiftEmbedIE
46fde8a1 67from .mtv import MTVServicesEmbeddedIE
45dad7ba 68from .pladform import PladformIE
ff18735c 69from .videomore import VideomoreIE
83f1481b 70from .webcaster import WebcasterFeedIE
5b251628 71from .googledrive import GoogleDriveIE
7cb09524 72from .jwplatform import JWPlatformIE
aecfcd4e 73from .digiteka import DigitekaIE
1979969f 74from .arkena import ArkenaIE
5a51775a 75from .instagram import InstagramIE
b8f67449 76from .liveleak import LiveLeakIE
5d39176f 77from .threeqsdn import ThreeQSDNIE
4d8819d2 78from .theplatform import ThePlatformIE
48a5eabc 79from .vessel import VesselIE
c287f2bc 80from .kaltura import KalturaIE
06a96da1 81from .eagleplatform import EaglePlatformIE
fd6ca382 82from .facebook import FacebookIE
94aae015 83from .soundcloud import SoundcloudIE
027e2312 84from .tunein import TuneInBaseIE
2a1321a2 85from .vbox7 import Vbox7IE
b0c8f2e9 86from .dbtv import DBTVIE
b1c35797 87from .piksel import PikselIE
e186a9ec 88from .videa import VideaIE
b687c85e 89from .twentymin import TwentyMinutenIE
d77ac737 90from .ustream import UstreamIE
17f8deeb 91from .openload import OpenloadIE
6ef3e65a 92from .videopress import VideoPressIE
eb3079b6 93from .rutube import RutubeIE
e5d39886 94from .limelight import LimelightBaseIE
7986c3ab 95from .anvato import AnvatoIE
55719459 96from .washingtonpost import WashingtonPostIE
58bb4402 97from .wistia import WistiaIE
5d29af3d 98from .mediaset import MediasetIE
73cf76a9 99from .joj import JojIE
24e966e8 100from .megaphone import MegaphoneIE
41918eaa 101from .vzaar import VzaarIE
9b122384 102
0838239e 103
9b122384 104class GenericIE(InfoExtractor):
79649588 105 IE_DESC = 'Generic downloader that works on some sites'
9b122384 106 _VALID_URL = r'.*'
79649588 107 IE_NAME = 'generic'
cfe50f04 108 _TESTS = [
c5fa81fe
S
109 # Direct link to a video
110 {
111 'url': 'http://media.w3.org/2010/05/sintel/trailer.mp4',
112 'md5': '67d406c2bcb6af27fa886f31aa934bbe',
113 'info_dict': {
114 'id': 'trailer',
115 'ext': 'mp4',
116 'title': 'trailer',
117 'upload_date': '20100513',
118 }
119 },
c5138a7c 120 # Direct link to media delivered compressed (until Accept-Encoding is *)
c5fa81fe
S
121 {
122 'url': 'http://calimero.tk/muzik/FictionJunction-Parallel_Hearts.flac',
123 'md5': '128c42e68b13950268b648275386fc74',
124 'info_dict': {
125 'id': 'FictionJunction-Parallel_Hearts',
126 'ext': 'flac',
127 'title': 'FictionJunction-Parallel_Hearts',
128 'upload_date': '20140522',
129 },
130 'expected_warnings': [
131 'URL could be a direct video link, returning it as such.'
39efc6e3
YCH
132 ],
133 'skip': 'URL invalid',
c5fa81fe
S
134 },
135 # Direct download with broken HEAD
136 {
137 'url': 'http://ai-radio.org:8000/radio.opus',
138 'info_dict': {
139 'id': 'radio',
140 'ext': 'opus',
141 'title': 'radio',
142 },
143 'params': {
144 'skip_download': True, # infinite live stream
145 },
146 'expected_warnings': [
ef0e4e7b
YCH
147 r'501.*Not Implemented',
148 r'400.*Bad Request',
c5fa81fe
S
149 ],
150 },
151 # Direct link with incorrect MIME type
152 {
153 'url': 'http://ftp.nluug.nl/video/nluug/2014-11-20_nj14/zaal-2/5_Lennart_Poettering_-_Systemd.webm',
154 'md5': '4ccbebe5f36706d85221f204d7eb5913',
155 'info_dict': {
156 'url': 'http://ftp.nluug.nl/video/nluug/2014-11-20_nj14/zaal-2/5_Lennart_Poettering_-_Systemd.webm',
157 'id': '5_Lennart_Poettering_-_Systemd',
158 'ext': 'webm',
159 'title': '5_Lennart_Poettering_-_Systemd',
160 'upload_date': '20141120',
161 },
162 'expected_warnings': [
163 'URL could be a direct video link, returning it as such.'
164 ]
165 },
166 # RSS feed
167 {
168 'url': 'http://phihag.de/2014/youtube-dl/rss2.xml',
169 'info_dict': {
170 'id': 'http://phihag.de/2014/youtube-dl/rss2.xml',
171 'title': 'Zero Punctuation',
172 'description': 're:.*groundbreaking video review series.*'
173 },
174 'playlist_mincount': 11,
175 },
176 # RSS feed with enclosure
177 {
178 'url': 'http://podcastfeeds.nbcnews.com/audio/podcast/MSNBC-MADDOW-NETCAST-M4V.xml',
179 'info_dict': {
180 'id': 'pdv_maddow_netcast_m4v-02-27-2015-201624',
181 'ext': 'm4v',
182 'upload_date': '20150228',
183 'title': 'pdv_maddow_netcast_m4v-02-27-2015-201624',
184 }
185 },
8765222d
S
186 # SMIL from http://videolectures.net/promogram_igor_mekjavic_eng
187 {
188 'url': 'http://videolectures.net/promogram_igor_mekjavic_eng/video/1/smil.xml',
189 'info_dict': {
190 'id': 'smil',
191 'ext': 'mp4',
192 'title': 'Automatics, robotics and biocybernetics',
193 'description': 'md5:815fc1deb6b3a2bff99de2d5325be482',
e327b736 194 'upload_date': '20130627',
8765222d
S
195 'formats': 'mincount:16',
196 'subtitles': 'mincount:1',
197 },
198 'params': {
199 'force_generic_extractor': True,
200 'skip_download': True,
201 },
202 },
203 # SMIL from http://www1.wdr.de/mediathek/video/livestream/index.html
204 {
205 'url': 'http://metafilegenerator.de/WDR/WDR_FS/hds/hds.smil',
206 'info_dict': {
207 'id': 'hds',
208 'ext': 'flv',
209 'title': 'hds',
210 'formats': 'mincount:1',
211 },
212 'params': {
213 'skip_download': True,
214 },
215 },
216 # SMIL from https://www.restudy.dk/video/play/id/1637
217 {
218 'url': 'https://www.restudy.dk/awsmedia/SmilDirectory/video_1637.xml',
219 'info_dict': {
220 'id': 'video_1637',
221 'ext': 'flv',
222 'title': 'video_1637',
223 'formats': 'mincount:3',
224 },
225 'params': {
226 'skip_download': True,
227 },
228 },
229 # SMIL from http://adventure.howstuffworks.com/5266-cool-jobs-iditarod-musher-video.htm
230 {
231 'url': 'http://services.media.howstuffworks.com/videos/450221/smil-service.smil',
232 'info_dict': {
233 'id': 'smil-service',
234 'ext': 'flv',
235 'title': 'smil-service',
236 'formats': 'mincount:1',
237 },
238 'params': {
239 'skip_download': True,
240 },
241 },
242 # SMIL from http://new.livestream.com/CoheedandCambria/WebsterHall/videos/4719370
243 {
244 'url': 'http://api.new.livestream.com/accounts/1570303/events/1585861/videos/4719370.smil',
245 'info_dict': {
246 'id': '4719370',
247 'ext': 'mp4',
248 'title': '571de1fd-47bc-48db-abf9-238872a58d1f',
249 'formats': 'mincount:3',
250 },
251 'params': {
252 'skip_download': True,
253 },
254 },
1de5cd3b
S
255 # XSPF playlist from http://www.telegraaf.nl/tv/nieuws/binnenland/24353229/__Tikibad_ontruimd_wegens_brand__.html
256 {
257 'url': 'http://www.telegraaf.nl/xml/playlist/2015/8/7/mZlp2ctYIUEB.xspf',
258 'info_dict': {
259 'id': 'mZlp2ctYIUEB',
260 'ext': 'mp4',
261 'title': 'Tikibad ontruimd wegens brand',
262 'description': 'md5:05ca046ff47b931f9b04855015e163a4',
ec85ded8 263 'thumbnail': r're:^https?://.*\.jpg$',
1de5cd3b
S
264 'duration': 33,
265 },
266 'params': {
267 'skip_download': True,
268 },
269 },
9d939cec
S
270 # MPD from http://dash-mse-test.appspot.com/media.html
271 {
272 'url': 'http://yt-dash-mse-test.commondatastorage.googleapis.com/media/car-20120827-manifest.mpd',
273 'md5': '4b57baab2e30d6eb3a6a09f0ba57ef53',
274 'info_dict': {
275 'id': 'car-20120827-manifest',
276 'ext': 'mp4',
277 'title': 'car-20120827-manifest',
278 'formats': 'mincount:9',
0738187f 279 'upload_date': '20130904',
9d939cec
S
280 },
281 'params': {
282 'format': 'bestvideo',
283 },
284 },
20938f76
S
285 # m3u8 served with Content-Type: audio/x-mpegURL; charset=utf-8
286 {
287 'url': 'http://once.unicornmedia.com/now/master/playlist/bb0b18ba-64f5-4b1b-a29f-0ac252f06b68/77a785f3-5188-4806-b788-0893a61634ed/93677179-2d99-4ef4-9e17-fe70d49abfbf/content.m3u8',
288 'info_dict': {
289 'id': 'content',
290 'ext': 'mp4',
291 'title': 'content',
292 'formats': 'mincount:8',
293 },
294 'params': {
295 # m3u8 downloads
296 'skip_download': True,
39efc6e3
YCH
297 },
298 'skip': 'video gone',
20938f76 299 },
edd9b71c
S
300 # m3u8 served with Content-Type: text/plain
301 {
302 'url': 'http://www.nacentapps.com/m3u8/index.m3u8',
303 'info_dict': {
304 'id': 'index',
305 'ext': 'mp4',
306 'title': 'index',
307 'upload_date': '20140720',
308 'formats': 'mincount:11',
309 },
310 'params': {
311 # m3u8 downloads
312 'skip_download': True,
39efc6e3
YCH
313 },
314 'skip': 'video gone',
edd9b71c 315 },
c5fa81fe
S
316 # google redirect
317 {
318 'url': 'http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CCUQtwIwAA&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DcmQHVoWB5FY&ei=F-sNU-LLCaXk4QT52ICQBQ&usg=AFQjCNEw4hL29zgOohLXvpJ-Bdh2bils1Q&bvm=bv.61965928,d.bGE',
319 'info_dict': {
320 'id': 'cmQHVoWB5FY',
321 'ext': 'mp4',
322 'upload_date': '20130224',
323 'uploader_id': 'TheVerge',
ec85ded8 324 'description': r're:^Chris Ziegler takes a look at the\.*',
c5fa81fe
S
325 'uploader': 'The Verge',
326 'title': 'First Firefox OS phones side-by-side',
327 },
328 'params': {
329 'skip_download': False,
330 }
331 },
6c91a5a7
S
332 {
333 # redirect in Refresh HTTP header
334 'url': 'https://www.facebook.com/l.php?u=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DpO8h3EaFRdo&h=TAQHsoToz&enc=AZN16h-b6o4Zq9pZkCCdOLNKMN96BbGMNtcFwHSaazus4JHT_MFYkAA-WARTX2kvsCIdlAIyHZjl6d33ILIJU7Jzwk_K3mcenAXoAzBNoZDI_Q7EXGDJnIhrGkLXo_LJ_pAa2Jzbx17UHMd3jAs--6j2zaeto5w9RTn8T_1kKg3fdC5WPX9Dbb18vzH7YFX0eSJmoa6SP114rvlkw6pkS1-T&s=1',
335 'info_dict': {
336 'id': 'pO8h3EaFRdo',
337 'ext': 'mp4',
338 'title': 'Tripeo Boiler Room x Dekmantel Festival DJ Set',
339 'description': 'md5:6294cc1af09c4049e0652b51a2df10d5',
340 'upload_date': '20150917',
341 'uploader_id': 'brtvofficial',
342 'uploader': 'Boiler Room',
343 },
344 'params': {
345 'skip_download': False,
346 },
347 },
cfe50f04 348 {
79649588 349 'url': 'http://www.hodiho.fr/2013/02/regis-plante-sa-jeep.html',
d360a146 350 'md5': '85b90ccc9d73b4acd9138d3af4c27f89',
79649588 351 'info_dict': {
d360a146
S
352 'id': '13601338388002',
353 'ext': 'mp4',
79649588
PH
354 'uploader': 'www.hodiho.fr',
355 'title': 'R\u00e9gis plante sa Jeep',
cfe50f04
JMF
356 }
357 },
c19f7764
JMF
358 # bandcamp page with custom domain
359 {
79649588
PH
360 'add_ie': ['Bandcamp'],
361 'url': 'http://bronyrock.com/track/the-pony-mash',
79649588 362 'info_dict': {
fd50bf62
S
363 'id': '3235767654',
364 'ext': 'mp3',
79649588
PH
365 'title': 'The Pony Mash',
366 'uploader': 'M_Pallante',
c19f7764 367 },
79649588 368 'skip': 'There is a limit of 200 free downloads / month for the test song',
c19f7764 369 },
eeb165e6 370 {
53a664ed
S
371 # embedded brightcove video
372 # it also tests brightcove videos that need to set the 'Referer'
373 # in the http requests
3b7d9aa4 374 'add_ie': ['BrightcoveLegacy'],
79649588
PH
375 'url': 'http://www.bfmtv.com/video/bfmbusiness/cours-bourse/cours-bourse-l-analyse-technique-154522/',
376 'info_dict': {
377 'id': '2765128793001',
378 'ext': 'mp4',
379 'title': 'Le cours de bourse : l’analyse technique',
380 'description': 'md5:7e9ad046e968cb2d1114004aba466fd9',
381 'uploader': 'BFM BUSINESS',
eeb165e6 382 },
79649588
PH
383 'params': {
384 'skip_download': True,
eeb165e6
JMF
385 },
386 },
53a664ed
S
387 {
388 # embedded with itemprop embedURL and video id spelled as `idVideo`
389 'add_id': ['BrightcoveLegacy'],
390 'url': 'http://bfmbusiness.bfmtv.com/mediaplayer/chroniques/olivier-delamarche/',
391 'info_dict': {
392 'id': '5255628253001',
393 'ext': 'mp4',
394 'title': 'md5:37c519b1128915607601e75a87995fc0',
395 'description': 'md5:37f7f888b434bb8f8cc8dbd4f7a4cf26',
396 'uploader': 'BFM BUSINESS',
397 'uploader_id': '876450612001',
398 'timestamp': 1482255315,
399 'upload_date': '20161220',
400 },
401 'params': {
402 'skip_download': True,
403 },
404 },
17ab4d3b
PH
405 {
406 # https://github.com/rg3/youtube-dl/issues/2253
407 'url': 'http://bcove.me/i6nfkrc3',
17ab4d3b
PH
408 'md5': '0ba9446db037002366bab3b3eb30c88c',
409 'info_dict': {
fd50bf62
S
410 'id': '3101154703001',
411 'ext': 'mp4',
17ab4d3b
PH
412 'title': 'Still no power',
413 'uploader': 'thestar.com',
414 'description': 'Mississauga resident David Farmer is still out of power as a result of the ice storm a month ago. To keep the house warm, Farmer cuts wood from his property for a wood burning stove downstairs.',
415 },
3b7d9aa4 416 'add_ie': ['BrightcoveLegacy'],
39efc6e3 417 'skip': 'video gone',
17ab4d3b 418 },
0479c625
S
419 {
420 'url': 'http://www.championat.com/video/football/v/87/87499.html',
421 'md5': 'fb973ecf6e4a78a67453647444222983',
422 'info_dict': {
423 'id': '3414141473001',
424 'ext': 'mp4',
425 'title': 'Видео. Удаление Дзагоева (ЦСКА)',
426 'description': 'Онлайн-трансляция матча ЦСКА - "Волга"',
427 'uploader': 'Championat',
428 },
429 },
bdf97017 430 {
37aab278 431 # https://github.com/rg3/youtube-dl/issues/3541
3b7d9aa4 432 'add_ie': ['BrightcoveLegacy'],
bdf97017
NJ
433 'url': 'http://www.kijk.nl/sbs6/leermijvrouwenkennen/videos/jqMiXKAYan2S/aflevering-1',
434 'info_dict': {
435 'id': '3866516442001',
37aab278 436 'ext': 'mp4',
bdf97017
NJ
437 'title': 'Leer mij vrouwen kennen: Aflevering 1',
438 'description': 'Leer mij vrouwen kennen: Aflevering 1',
439 'uploader': 'SBS Broadcasting',
440 },
37aab278 441 'skip': 'Restricted to Netherlands',
bdf97017 442 'params': {
37aab278 443 'skip_download': True, # m3u8 download
bdf97017
NJ
444 },
445 },
06d0ad9a
YCH
446 {
447 # Brightcove video in <iframe>
448 'url': 'http://www.un.org/chinese/News/story.asp?NewsID=27724',
449 'md5': '36d74ef5e37c8b4a2ce92880d208b968',
450 'info_dict': {
451 'id': '5360463607001',
452 'ext': 'mp4',
453 'title': '叙利亚失明儿童在废墟上演唱《心跳》 呼吁获得正常童年生活',
454 'description': '联合国儿童基金会中东和北非区域大使、作曲家扎德·迪拉尼(Zade Dirani)在3月15日叙利亚冲突爆发7周年纪念日之际发布了为叙利亚谱写的歌曲《心跳》(HEARTBEAT),为受到六年冲突影响的叙利亚儿童发出强烈呐喊,呼吁世界做出共同努力,使叙利亚儿童重新获得享有正常童年生活的权利。',
455 'uploader': 'United Nations',
456 'uploader_id': '1362235914001',
457 'timestamp': 1489593889,
458 'upload_date': '20170315',
459 },
460 'add_ie': ['BrightcoveLegacy'],
461 },
16e2c8f7
YCH
462 {
463 # Brightcove with alternative playerID key
464 'url': 'http://www.nature.com/nmeth/journal/v9/n7/fig_tab/nmeth.2062_SV1.html',
465 'info_dict': {
466 'id': 'nmeth.2062_SV1',
467 'title': 'Simultaneous multiview imaging of the Drosophila syncytial blastoderm : Quantitative high-speed imaging of entire developing embryos with simultaneous multiview light-sheet microscopy : Nature Methods : Nature Research',
468 },
469 'playlist': [{
470 'info_dict': {
471 'id': '2228375078001',
472 'ext': 'mp4',
473 'title': 'nmeth.2062-sv1',
474 'description': 'nmeth.2062-sv1',
475 'timestamp': 1363357591,
476 'upload_date': '20130315',
477 'uploader': 'Nature Publishing Group',
478 'uploader_id': '1964492299001',
479 },
480 }],
481 },
40158f55
JH
482 {
483 # Brightcove with UUID in videoPlayer
484 'url': 'http://www8.hp.com/cn/zh/home.html',
485 'info_dict': {
486 'id': '5255815316001',
487 'ext': 'mp4',
488 'title': 'Sprocket Video - China',
489 'description': 'Sprocket Video - China',
490 'uploader': 'HP-Video Gallery',
491 'timestamp': 1482263210,
492 'upload_date': '20161220',
493 'uploader_id': '1107601872001',
494 },
495 'params': {
496 'skip_download': True, # m3u8 download
497 },
498 'skip': 'video rotates...weekly?',
499 },
500 {
501 # Brightcove:new type [2].
502 'url': 'http://www.delawaresportszone.com/video-st-thomas-more-earns-first-trip-to-basketball-semis',
503 'md5': '2b35148fcf48da41c9fb4591650784f3',
504 'info_dict': {
505 'id': '5348741021001',
506 'ext': 'mp4',
507 'upload_date': '20170306',
508 'uploader_id': '4191638492001',
509 'timestamp': 1488769918,
510 'title': 'VIDEO: St. Thomas More earns first trip to basketball semis',
511
512 },
513 },
514 {
515 # Alternative brightcove <video> attributes
516 'url': 'http://www.programme-tv.net/videos/extraits/81095-guillaume-canet-evoque-les-rumeurs-d-infidelite-de-marion-cotillard-avec-brad-pitt-dans-vivement-dimanche/',
517 'info_dict': {
518 'id': '81095-guillaume-canet-evoque-les-rumeurs-d-infidelite-de-marion-cotillard-avec-brad-pitt-dans-vivement-dimanche',
519 'title': "Guillaume Canet évoque les rumeurs d'infidélité de Marion Cotillard avec Brad Pitt dans Vivement Dimanche, Extraits : toutes les vidéos avec Télé-Loisirs",
520 },
521 'playlist': [{
522 'md5': '732d22ba3d33f2f3fc253c39f8f36523',
523 'info_dict': {
524 'id': '5311302538001',
525 'ext': 'mp4',
526 'title': "Guillaume Canet évoque les rumeurs d'infidélité de Marion Cotillard avec Brad Pitt dans Vivement Dimanche",
527 'description': "Guillaume Canet évoque les rumeurs d'infidélité de Marion Cotillard avec Brad Pitt dans Vivement Dimanche (France 2, 5 février 2017)",
528 'timestamp': 1486321708,
529 'upload_date': '20170205',
530 'uploader_id': '800000640001',
531 },
532 'only_matching': True,
533 }],
534 },
b68a812e
S
535 {
536 # Brightcove with UUID in videoPlayer
537 'url': 'http://www8.hp.com/cn/zh/home.html',
538 'info_dict': {
539 'id': '5255815316001',
540 'ext': 'mp4',
541 'title': 'Sprocket Video - China',
542 'description': 'Sprocket Video - China',
543 'uploader': 'HP-Video Gallery',
544 'timestamp': 1482263210,
545 'upload_date': '20161220',
546 'uploader_id': '1107601872001',
547 },
548 'params': {
549 'skip_download': True, # m3u8 download
550 },
551 },
c0d0b01f
JMF
552 # ooyala video
553 {
79649588 554 'url': 'http://www.rollingstone.com/music/videos/norwegian-dj-cashmere-cat-goes-spartan-on-with-me-premiere-20131219',
87830900 555 'md5': '166dd577b433b4d4ebfee10b0824d8ff',
79649588
PH
556 'info_dict': {
557 'id': 'BwY2RxaTrTkslxOfcan0UCf0YqyvWysJ',
558 'ext': 'mp4',
3486df38 559 'title': '2cc213299525360.mov', # that's what we get
53e06b25 560 'duration': 238.231,
c0d0b01f 561 },
87830900 562 'add_ie': ['Ooyala'],
c0d0b01f 563 },
bf94d763
S
564 {
565 # ooyala video embedded with http://player.ooyala.com/iframe.js
566 'url': 'http://www.macrumors.com/2015/07/24/steve-jobs-the-man-in-the-machine-first-trailer/',
567 'info_dict': {
568 'id': 'p0MGJndjoG5SOKqO_hZJuZFPB-Tr5VgB',
569 'ext': 'mp4',
570 'title': '"Steve Jobs: Man in the Machine" trailer',
571 'description': 'The first trailer for the Alex Gibney documentary "Steve Jobs: Man in the Machine."',
53e06b25 572 'duration': 135.427,
bf94d763
S
573 },
574 'params': {
575 'skip_download': True,
576 },
39efc6e3 577 'skip': 'movie expired',
bf94d763 578 },
198d4cb4
GR
579 # ooyala video embedded with http://player.ooyala.com/static/v4/production/latest/core.min.js
580 {
581 'url': 'http://wnep.com/2017/07/22/steampunk-fest-comes-to-honesdale/',
582 'info_dict': {
583 'id': 'lwYWYxYzE6V5uJMjNGyKtwwiw9ZJD7t2',
584 'ext': 'mp4',
585 'title': 'Steampunk Fest Comes to Honesdale',
586 'duration': 43.276,
587 },
588 'params': {
589 'skip_download': True,
590 }
591 },
1b86cc41 592 # embed.ly video
593 {
594 'url': 'http://www.tested.com/science/weird/460206-tested-grinding-coffee-2000-frames-second/',
595 'info_dict': {
596 'id': '9ODmcdjQcHQ',
597 'ext': 'mp4',
0a5bce56
PH
598 'title': 'Tested: Grinding Coffee at 2000 Frames Per Second',
599 'upload_date': '20140225',
600 'description': 'md5:06a40fbf30b220468f1e0957c0f558ff',
601 'uploader': 'Tested',
602 'uploader_id': 'testedcom',
1b86cc41 603 },
604 # No need to test YoutubeIE here
605 'params': {
606 'skip_download': True,
607 },
608 },
60cc4dc4
PH
609 # funnyordie embed
610 {
611 'url': 'http://www.theguardian.com/world/2014/mar/11/obama-zach-galifianakis-between-two-ferns',
60cc4dc4
PH
612 'info_dict': {
613 'id': '18e820ec3f',
614 'ext': 'mp4',
615 'title': 'Between Two Ferns with Zach Galifianakis: President Barack Obama',
616 'description': 'Episode 18: President Barack Obama sits down with Zach Galifianakis for his most memorable interview yet.',
93d020dd 617 },
39efc6e3
YCH
618 # HEAD requests lead to endless 301, while GET is OK
619 'expected_warnings': ['301'],
60cc4dc4 620 },
93d020dd
S
621 # RUTV embed
622 {
623 'url': 'http://www.rg.ru/2014/03/15/reg-dfo/anklav-anons.html',
624 'info_dict': {
625 'id': '776940',
626 'ext': 'mp4',
627 'title': 'Охотское море стало целиком российским',
628 'description': 'md5:5ed62483b14663e2a95ebbe115eb8f43',
629 },
630 'params': {
631 # m3u8 download
632 'skip_download': True,
633 },
aab74fa1 634 },
f37bdbe5
S
635 # TVC embed
636 {
637 'url': 'http://sch1298sz.mskobr.ru/dou_edu/karamel_ki/filial_galleries/video/iframe_src_http_tvc_ru_video_iframe_id_55304_isplay_false_acc_video_id_channel_brand_id_11_show_episodes_episode_id_32307_frameb/',
638 'info_dict': {
639 'id': '55304',
640 'ext': 'mp4',
641 'title': 'Дошкольное воспитание',
642 },
643 },
b827a601
S
644 # SportBox embed
645 {
646 'url': 'http://www.vestifinance.ru/articles/25753',
647 'info_dict': {
648 'id': '25753',
05d1e7aa 649 'title': 'Прямые трансляции с Форума-выставки "Госзаказ-2013"',
b827a601
S
650 },
651 'playlist': [{
652 'info_dict': {
653 'id': '370908',
654 'title': 'Госзаказ. День 3',
655 'ext': 'mp4',
656 }
657 }, {
658 'info_dict': {
659 'id': '370905',
660 'title': 'Госзаказ. День 2',
661 'ext': 'mp4',
662 }
663 }, {
664 'info_dict': {
665 'id': '370902',
666 'title': 'Госзаказ. День 1',
667 'ext': 'mp4',
668 }
669 }],
670 'params': {
671 # m3u8 download
672 'skip_download': True,
673 },
674 },
bf20b9c5
S
675 # Myvi.ru embed
676 {
677 'url': 'http://www.kinomyvi.tv/news/detail/Pervij-dublirovannij-trejler--Uzhastikov-_nOw1',
678 'info_dict': {
679 'id': 'f4dafcad-ff21-423d-89b5-146cfd89fa1e',
680 'ext': 'mp4',
681 'title': 'Ужастики, русский трейлер (2015)',
ec85ded8 682 'thumbnail': r're:^https?://.*\.jpg$',
bf20b9c5
S
683 'duration': 153,
684 }
685 },
c76799c5
S
686 # XHamster embed
687 {
688 'url': 'http://www.numisc.com/forum/showthread.php?11696-FM15-which-pumiscer-was-this-%28-vid-%29-%28-alfa-as-fuck-srx-%29&s=711f5db534502e22260dec8c5e2d66d8',
689 'info_dict': {
690 'id': 'showthread',
691 'title': '[NSFL] [FM15] which pumiscer was this ( vid ) ( alfa as fuck srx )',
692 },
693 'playlist_mincount': 7,
39efc6e3
YCH
694 # This forum does not allow <iframe> syntaxes anymore
695 # Now HTML tags are displayed as-is
696 'skip': 'No videos on this page',
c76799c5 697 },
aab74fa1
PH
698 # Embedded TED video
699 {
700 'url': 'http://en.support.wordpress.com/videos/ted-talks/',
a8eb5a8e 701 'md5': '65fdff94098e4a607385a60c5177c638',
aab74fa1 702 'info_dict': {
a8eb5a8e 703 'id': '1969',
aab74fa1 704 'ext': 'mp4',
a8eb5a8e
PH
705 'title': 'Hidden miracles of the natural world',
706 'uploader': 'Louie Schwartzberg',
707 'description': 'md5:8145d19d320ff3e52f28401f4c4283b9',
aab74fa1 708 }
60cc4dc4 709 },
d95e35d6
S
710 # nowvideo embed hidden behind percent encoding
711 {
712 'url': 'http://www.waoanime.tv/the-super-dimension-fortress-macross-episode-1/',
713 'md5': '2baf4ddd70f697d94b1c18cf796d5107',
714 'info_dict': {
715 'id': '06e53103ca9aa',
716 'ext': 'flv',
717 'title': 'Macross Episode 001 Watch Macross Episode 001 onl',
718 'description': 'No description',
719 },
0f2a2ba1 720 },
893f8832
PH
721 # arte embed
722 {
723 'url': 'http://www.tv-replay.fr/redirection/20-03-14/x-enius-arte-10753389.html',
724 'md5': '7653032cbb25bf6c80d80f217055fa43',
725 'info_dict': {
726 'id': '048195-004_PLUS7-F',
727 'ext': 'flv',
728 'title': 'X:enius',
729 'description': 'md5:d5fdf32ef6613cdbfd516ae658abf168',
730 'upload_date': '20140320',
731 },
732 'params': {
733 'skip_download': 'Requires rtmpdump'
39efc6e3
YCH
734 },
735 'skip': 'video gone',
893f8832 736 },
cbd55ade
S
737 # francetv embed
738 {
739 'url': 'http://www.tsprod.com/replay-du-concert-alcaline-de-calogero',
740 'info_dict': {
741 'id': 'EV_30231',
742 'ext': 'mp4',
743 'title': 'Alcaline, le concert avec Calogero',
744 'description': 'md5:61f08036dcc8f47e9cfc33aed08ffaff',
745 'upload_date': '20150226',
746 'timestamp': 1424989860,
747 'duration': 5400,
748 },
749 'params': {
750 # m3u8 downloads
751 'skip_download': True,
752 },
753 'expected_warnings': [
754 'Forbidden'
755 ]
756 },
fa35cdad
PH
757 # Condé Nast embed
758 {
759 'url': 'http://www.wired.com/2014/04/honda-asimo/',
760 'md5': 'ba0dfe966fa007657bd1443ee672db0f',
761 'info_dict': {
762 'id': '53501be369702d3275860000',
763 'ext': 'mp4',
764 'title': 'Honda’s New Asimo Robot Is More Human Than Ever',
765 }
ebd3c7b3
PH
766 },
767 # Dailymotion embed
768 {
769 'url': 'http://www.spi0n.com/zap-spi0n-com-n216/',
770 'md5': '441aeeb82eb72c422c7f14ec533999cd',
771 'info_dict': {
772 'id': 'k2mm4bCdJ6CQ2i7c8o2',
773 'ext': 'mp4',
774 'title': 'Le Zap de Spi0n n°216 - Zapping du Web',
0738187f 775 'description': 'md5:faf028e48a461b8b7fad38f1e104b119',
ebd3c7b3 776 'uploader': 'Spi0n',
0738187f
YCH
777 'uploader_id': 'xgditw',
778 'upload_date': '20140425',
779 'timestamp': 1398441542,
ebd3c7b3
PH
780 },
781 'add_ie': ['Dailymotion'],
2b88feed 782 },
71a1db89
S
783 # DailyMail embed
784 {
785 'url': 'http://www.bumm.sk/krimi/2017/07/05/biztonsagi-kamera-buktatta-le-az-agg-ferfit-utlegelo-apolot',
786 'info_dict': {
787 'id': '1495629',
788 'ext': 'mp4',
789 'title': 'Care worker punches elderly dementia patient in head 11 times',
790 'description': 'md5:3a743dee84e57e48ec68bf67113199a5',
791 },
792 'add_ie': ['DailyMail'],
793 'params': {
794 'skip_download': True,
795 },
796 },
2b88feed
PH
797 # YouTube embed
798 {
799 'url': 'http://www.badzine.de/ansicht/datum/2014/06/09/so-funktioniert-die-neue-englische-badminton-liga.html',
800 'info_dict': {
801 'id': 'FXRb4ykk4S0',
802 'ext': 'mp4',
803 'title': 'The NBL Auction 2014',
804 'uploader': 'BADMINTON England',
805 'uploader_id': 'BADMINTONEvents',
806 'upload_date': '20140603',
807 'description': 'md5:9ef128a69f1e262a700ed83edb163a73',
808 },
809 'add_ie': ['Youtube'],
810 'params': {
811 'skip_download': True,
812 }
813 },
c5cd249e
JMF
814 # MTVSercices embed
815 {
1fa309da
YCH
816 'url': 'http://www.vulture.com/2016/06/new-key-peele-sketches-released.html',
817 'md5': 'ca1aef97695ef2c1d6973256a57e5252',
c5cd249e 818 'info_dict': {
1fa309da 819 'id': '769f7ec0-0692-4d62-9b45-0d88074bffc1',
c5cd249e 820 'ext': 'mp4',
1fa309da
YCH
821 'title': 'Key and Peele|October 10, 2012|2|203|Liam Neesons - Uncensored',
822 'description': 'Two valets share their love for movie star Liam Neesons.',
05d1e7aa
YCH
823 'timestamp': 1349922600,
824 'upload_date': '20121011',
c5cd249e
JMF
825 },
826 },
61013473 827 # YouTube embed via <data-embed-url="">
828 {
829 'url': 'https://play.google.com/store/apps/details?id=com.gameloft.android.ANMP.GloftA8HM',
61013473 830 'info_dict': {
a8eb5a8e 831 'id': '4vAffPZIT44',
61013473 832 'ext': 'mp4',
a8eb5a8e 833 'title': 'Asphalt 8: Airborne - Update - Welcome to Dubai!',
ed2d6a19
PH
834 'uploader': 'Gameloft',
835 'uploader_id': 'gameloft',
a8eb5a8e
PH
836 'upload_date': '20140828',
837 'description': 'md5:c80da9ed3d83ae6d1876c834de03e1c4',
ed2d6a19
PH
838 },
839 'params': {
840 'skip_download': True,
61013473 841 }
c8e9a235 842 },
61568e50
JH
843 # YouTube <object> embed
844 {
845 'url': 'http://www.improbable.com/2017/04/03/untrained-modern-youths-and-ancient-masters-in-selfie-portraits/',
846 'md5': '516718101ec834f74318df76259fb3cc',
847 'info_dict': {
848 'id': 'msN87y-iEx0',
849 'ext': 'webm',
850 'title': 'Feynman: Mirrors FUN TO IMAGINE 6',
851 'upload_date': '20080526',
852 'description': 'md5:0ffc78ea3f01b2e2c247d5f8d1d3c18d',
853 'uploader': 'Christopher Sykes',
854 'uploader_id': 'ChristopherJSykes',
855 },
856 'add_ie': ['Youtube'],
857 },
c8e9a235
PH
858 # Camtasia studio
859 {
860 'url': 'http://www.ll.mit.edu/workshops/education/videocourses/antennas/lecture1/video/',
861 'playlist': [{
862 'md5': '0c5e352edabf715d762b0ad4e6d9ee67',
863 'info_dict': {
864 'id': 'Fenn-AA_PA_Radar_Course_Lecture_1c_Final',
865 'title': 'Fenn-AA_PA_Radar_Course_Lecture_1c_Final - video1',
866 'ext': 'flv',
867 'duration': 2235.90,
868 }
869 }, {
870 'md5': '10e4bb3aaca9fd630e273ff92d9f3c63',
871 'info_dict': {
872 'id': 'Fenn-AA_PA_Radar_Course_Lecture_1c_Final_PIP',
873 'title': 'Fenn-AA_PA_Radar_Course_Lecture_1c_Final - pip',
874 'ext': 'flv',
875 'duration': 2235.93,
876 }
877 }],
878 'info_dict': {
879 'title': 'Fenn-AA_PA_Radar_Course_Lecture_1c_Final',
880 }
4d805e06
PH
881 },
882 # Flowplayer
883 {
884 'url': 'http://www.handjobhub.com/video/busty-blonde-siri-tit-fuck-while-wank-6313.html',
885 'md5': '9d65602bf31c6e20014319c7d07fba27',
886 'info_dict': {
887 'id': '5123ea6d5e5a7',
888 'ext': 'mp4',
889 'age_limit': 18,
890 'uploader': 'www.handjobhub.com',
d6d9186f 891 'title': 'Busty Blonde Siri Tit Fuck While Wank at HandjobHub.com',
4d805e06 892 }
0990305d 893 },
22a6f150
PH
894 # Multiple brightcove videos
895 # https://github.com/rg3/youtube-dl/issues/2283
896 {
897 'url': 'http://www.newyorker.com/online/blogs/newsdesk/2014/01/always-never-nuclear-command-and-control.html',
898 'info_dict': {
899 'id': 'always-never',
900 'title': 'Always / Never - The New Yorker',
901 },
902 'playlist_count': 3,
903 'params': {
904 'extract_flat': False,
905 'skip_download': True,
906 }
1a94ff68
S
907 },
908 # MLB embed
909 {
910 'url': 'http://umpire-empire.com/index.php/topic/58125-laz-decides-no-thats-low/',
911 'md5': '96f09a37e44da40dd083e12d9a683327',
912 'info_dict': {
913 'id': '33322633',
914 'ext': 'mp4',
915 'title': 'Ump changes call to ball',
916 'description': 'md5:71c11215384298a172a6dcb4c2e20685',
917 'duration': 48,
918 'timestamp': 1401537900,
919 'upload_date': '20140531',
ec85ded8 920 'thumbnail': r're:^https?://.*\.jpg$',
1a94ff68
S
921 },
922 },
746c67d7
NJ
923 # Wistia embed
924 {
6c114b12
S
925 'url': 'http://study.com/academy/lesson/north-american-exploration-failed-colonies-of-spain-france-england.html#lesson',
926 'md5': '1953f3a698ab51cfc948ed3992a0b7ff',
746c67d7 927 'info_dict': {
6c114b12 928 'id': '6e2wtrbdaf',
746c67d7 929 'ext': 'mov',
6c114b12
S
930 'title': 'paywall_north-american-exploration-failed-colonies-of-spain-france-england',
931 'description': 'a Paywall Videos video from Remilon',
932 'duration': 644.072,
933 'uploader': 'study.com',
934 'timestamp': 1459678540,
935 'upload_date': '20160403',
936 'filesize': 24687186,
746c67d7
NJ
937 },
938 },
52cffcb1 939 {
940 'url': 'http://thoughtworks.wistia.com/medias/uxjb0lwrcz',
941 'md5': 'baf49c2baa8a7de5f3fc145a8506dcd4',
942 'info_dict': {
943 'id': 'uxjb0lwrcz',
944 'ext': 'mp4',
6c114b12 945 'title': 'Conversation about Hexagonal Rails Part 1',
0738187f 946 'description': 'a Martin Fowler video from ThoughtWorks',
52cffcb1 947 'duration': 1715.0,
85d7b765 948 'uploader': 'thoughtworks.wistia.com',
0738187f 949 'timestamp': 1401832161,
6c114b12 950 'upload_date': '20140603',
70b7e3fb 951 },
52cffcb1 952 },
7ded6545
S
953 # Wistia standard embed (async)
954 {
955 'url': 'https://www.getdrip.com/university/brennan-dunn-drip-workshop/',
956 'info_dict': {
957 'id': '807fafadvk',
958 'ext': 'mp4',
959 'title': 'Drip Brennan Dunn Workshop',
960 'description': 'a JV Webinars video from getdrip-1',
961 'duration': 4986.95,
7ded6545 962 'timestamp': 1463607249,
6c114b12 963 'upload_date': '20160518',
7ded6545
S
964 },
965 'params': {
966 'skip_download': True,
967 }
968 },
ac645ac7
PH
969 # Soundcloud embed
970 {
971 'url': 'http://nakedsecurity.sophos.com/2014/10/29/sscc-171-are-you-sure-that-1234-is-a-bad-password-podcast/',
972 'info_dict': {
973 'id': '174391317',
974 'ext': 'mp3',
975 'description': 'md5:ff867d6b555488ad3c52572bb33d432c',
976 'uploader': 'Sophos Security',
977 'title': 'Chet Chat 171 - Oct 29, 2014',
978 'upload_date': '20141029',
979 }
af63fed7 980 },
db19df6c
S
981 # Soundcloud multiple embeds
982 {
983 'url': 'http://www.guitarplayer.com/lessons/1014/legato-workout-one-hour-to-more-fluid-performance---tab/52809',
984 'info_dict': {
985 'id': '52809',
986 'title': 'Guitar Essentials: Legato Workout—One-Hour to Fluid Performance | TAB + AUDIO',
987 },
988 'playlist_mincount': 7,
989 },
027e2312
S
990 # TuneIn station embed
991 {
992 'url': 'http://radiocnrv.com/promouvoir-radio-cnrv/',
993 'info_dict': {
994 'id': '204146',
995 'ext': 'mp3',
996 'title': 'CNRV',
997 'location': 'Paris, France',
998 'is_live': True,
999 },
1000 'params': {
1001 # Live stream
1002 'skip_download': True,
1003 },
1004 },
af63fed7
PH
1005 # Livestream embed
1006 {
1007 'url': 'http://www.esa.int/Our_Activities/Space_Science/Rosetta/Philae_comet_touch-down_webcast',
1008 'info_dict': {
1009 'id': '67864563',
1010 'ext': 'flv',
1011 'upload_date': '20141112',
1012 'title': 'Rosetta #CometLanding webcast HL 10',
1013 }
1014 },
78d3b3e2
YCH
1015 # Another Livestream embed, without 'new.' in URL
1016 {
1017 'url': 'https://www.freespeech.org/',
1018 'info_dict': {
1019 'id': '123537347',
1020 'ext': 'mp4',
1021 'title': 're:^FSTV [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$',
1022 },
1023 'params': {
1024 # Live stream
1025 'skip_download': True,
1026 },
1027 },
65f3a228
PH
1028 # LazyYT
1029 {
e8e4cc5a 1030 'url': 'https://skiplagged.com/',
65f3a228 1031 'info_dict': {
e8e4cc5a
JH
1032 'id': 'skiplagged',
1033 'title': 'Skiplagged: The smart way to find cheap flights',
65f3a228 1034 },
e8e4cc5a
JH
1035 'playlist_mincount': 1,
1036 'add_ie': ['Youtube'],
4e262a88 1037 },
42bdd9d0
PH
1038 # Cinchcast embed
1039 {
1040 'url': 'http://undergroundwellness.com/podcasts/306-5-steps-to-permanent-gut-healing/',
1041 'info_dict': {
1042 'id': '7141703',
1043 'ext': 'mp3',
1044 'upload_date': '20141126',
1045 'title': 'Jack Tips: 5 Steps to Permanent Gut Healing',
1046 }
1047 },
501f13fb
PH
1048 # Cinerama player
1049 {
1050 'url': 'http://www.abc.net.au/7.30/content/2015/s4164797.htm',
1051 'info_dict': {
1052 'id': '730m_DandD_1901_512k',
1053 'ext': 'mp4',
1054 'uploader': 'www.abc.net.au',
1055 'title': 'Game of Thrones with dice - Dungeons and Dragons fantasy role-playing game gets new life - 19/01/2015',
1056 }
796df3c6
S
1057 },
1058 # embedded viddler video
1059 {
1060 'url': 'http://deadspin.com/i-cant-stop-watching-john-wall-chop-the-nuggets-with-th-1681801597',
1061 'info_dict': {
1062 'id': '4d03aad9',
1063 'ext': 'mp4',
1064 'uploader': 'deadspin',
1065 'title': 'WALL-TO-GORTAT',
1066 'timestamp': 1422285291,
1067 'upload_date': '20150126',
1068 },
1069 'add_ie': ['Viddler'],
a0f71985 1070 },
2051acde
S
1071 # Libsyn embed
1072 {
1073 'url': 'http://thedailyshow.cc.com/podcast/episodetwelve',
1074 'info_dict': {
1075 'id': '3377616',
1076 'ext': 'mp3',
1077 'title': "The Daily Show Podcast without Jon Stewart - Episode 12: Bassem Youssef: Egypt's Jon Stewart",
1078 'description': 'md5:601cb790edd05908957dae8aaa866465',
1079 'upload_date': '20150220',
1080 },
326fa4e6 1081 'skip': 'All The Daily Show URLs now redirect to http://www.cc.com/shows/',
2051acde 1082 },
a0f71985
PH
1083 # jwplayer YouTube
1084 {
1085 'url': 'http://media.nationalarchives.gov.uk/index.php/webinar-using-discovery-national-archives-online-catalogue/',
1086 'info_dict': {
1087 'id': 'Mrj4DVp2zeA',
1088 'ext': 'mp4',
f37e3f99 1089 'upload_date': '20150212',
a0f71985
PH
1090 'uploader': 'The National Archives UK',
1091 'description': 'md5:a236581cd2449dd2df4f93412f3f01c6',
1092 'uploader_id': 'NationalArchives08',
1093 'title': 'Webinar: Using Discovery, The National Archives’ online catalogue',
1094 },
59b8ab58 1095 },
5620f840
S
1096 # jwplayer rtmp
1097 {
1098 'url': 'http://www.suffolk.edu/sjc/',
1099 'info_dict': {
1100 'id': 'sjclive',
1101 'ext': 'flv',
1102 'title': 'Massachusetts Supreme Judicial Court Oral Arguments',
1103 'uploader': 'www.suffolk.edu',
1104 },
1105 'params': {
1106 'skip_download': True,
1107 }
1108 },
a4a554a7
YCH
1109 # Complex jwplayer
1110 {
1111 'url': 'http://www.indiedb.com/games/king-machine/videos',
1112 'info_dict': {
1113 'id': 'videos',
1114 'ext': 'mp4',
1115 'title': 'king machine trailer 1',
1116 'thumbnail': r're:^https?://.*\.jpg$',
1117 },
1118 },
03486dbb
RU
1119 {
1120 # JWPlayer config passed as variable
1121 'url': 'http://www.txxx.com/videos/3326530/ariele/',
1122 'info_dict': {
1123 'id': '3326530_hq',
1124 'ext': 'mp4',
1125 'title': 'ARIELE | Tube Cup',
1126 'uploader': 'www.txxx.com',
1127 'age_limit': 18,
1128 },
1129 'params': {
1130 'skip_download': True,
1131 }
1132 },
59b8ab58
PH
1133 # rtl.nl embed
1134 {
1135 'url': 'http://www.rtlnieuws.nl/nieuws/buitenland/aanslagen-kopenhagen',
1136 'playlist_mincount': 5,
1137 'info_dict': {
1138 'id': 'aanslagen-kopenhagen',
1139 'title': 'Aanslagen Kopenhagen | RTL Nieuws',
1140 }
255fca5e
S
1141 },
1142 # Zapiks embed
1143 {
1144 'url': 'http://www.skipass.com/news/116090-bon-appetit-s5ep3-baqueira-mi-cor.html',
1145 'info_dict': {
1146 'id': '118046',
1147 'ext': 'mp4',
1148 'title': 'EP3S5 - Bon Appétit - Baqueira Mi Corazon !',
1149 }
1150 },
66e568de
S
1151 # Kaltura embed (different embed code)
1152 {
1153 'url': 'http://www.premierchristianradio.com/Shows/Saturday/Unbelievable/Conference-Videos/Os-Guinness-Is-It-Fools-Talk-Unbelievable-Conference-2014',
1154 'info_dict': {
1155 'id': '1_a52wc67y',
1156 'ext': 'flv',
1157 'upload_date': '20150127',
1158 'uploader_id': 'PremierMedia',
1159 'timestamp': int,
1160 'title': 'Os Guinness // Is It Fools Talk? // Unbelievable? Conference 2014',
1161 },
1162 },
87703231
YCH
1163 # Kaltura embed with single quotes
1164 {
1165 'url': 'http://fod.infobase.com/p_ViewPlaylist.aspx?AssignmentID=NUN8ZY',
1166 'info_dict': {
1167 'id': '0_izeg5utt',
1168 'ext': 'mp4',
1169 'title': '35871',
1170 'timestamp': 1355743100,
1171 'upload_date': '20121217',
1172 'uploader_id': 'batchUser',
1173 },
1174 'add_ie': ['Kaltura'],
1175 },
427cd050
S
1176 {
1177 # Kaltura embedded via quoted entry_id
1178 'url': 'https://www.oreilly.com/ideas/my-cloud-makes-pretty-pictures',
1179 'info_dict': {
1180 'id': '0_utuok90b',
1181 'ext': 'mp4',
1182 'title': '06_matthew_brender_raj_dutt',
1183 'timestamp': 1466638791,
1184 'upload_date': '20160622',
1185 },
1186 'add_ie': ['Kaltura'],
1187 'expected_warnings': [
1188 'Could not send HEAD request'
1189 ],
1190 'params': {
1191 'skip_download': True,
1192 }
1193 },
8ab7e6c4
YCH
1194 {
1195 # Kaltura embedded, some fileExt broken (#11480)
1196 'url': 'http://www.cornell.edu/video/nima-arkani-hamed-standard-models-of-particle-physics',
1197 'info_dict': {
1198 'id': '1_sgtvehim',
1199 'ext': 'mp4',
1200 'title': 'Our "Standard Models" of particle physics and cosmology',
1201 'description': 'md5:67ea74807b8c4fea92a6f38d6d323861',
1202 'timestamp': 1321158993,
1203 'upload_date': '20111113',
1204 'uploader_id': 'kps1',
1205 },
1206 'add_ie': ['Kaltura'],
1207 },
a01825a5
JH
1208 {
1209 # Kaltura iframe embed
1210 'url': 'http://www.gsd.harvard.edu/event/i-m-pei-a-centennial-celebration/',
1211 'md5': 'ae5ace8eb09dc1a35d03b579a9c2cc44',
1212 'info_dict': {
1213 'id': '0_f2cfbpwy',
1214 'ext': 'mp4',
1215 'title': 'I. M. Pei: A Centennial Celebration',
1216 'description': 'md5:1db8f40c69edc46ca180ba30c567f37c',
1217 'upload_date': '20170403',
1218 'uploader_id': 'batchUser',
1219 'timestamp': 1491232186,
1220 },
1221 'add_ie': ['Kaltura'],
1222 },
665e9452 1223 # EaglePlatform embed (generic URL)
135c9c42
S
1224 {
1225 'url': 'http://lenta.ru/news/2015/03/06/navalny/',
4645432d 1226 # Not checking MD5 as sometimes the direct HTTP link results in 404 and HLS is used
135c9c42
S
1227 'info_dict': {
1228 'id': '227304',
1229 'ext': 'mp4',
1230 'title': 'Навальный вышел на свободу',
1231 'description': 'md5:d97861ac9ae77377f3f20eaf9d04b4f5',
ec85ded8 1232 'thumbnail': r're:^https?://.*\.jpg$',
135c9c42
S
1233 'duration': 87,
1234 'view_count': int,
1235 'age_limit': 0,
1236 },
250b042c
S
1237 'params': {
1238 'skip_download': True,
1239 },
1240 },
1241 # referrer protected EaglePlatform embed
1242 {
1243 'url': 'https://tvrain.ru/lite/teleshow/kak_vse_nachinalos/namin-418921/',
1244 'info_dict': {
1245 'id': '582306',
1246 'ext': 'mp4',
1247 'title': 'Стас Намин: «Мы нарушили девственность Кремля»',
1248 'thumbnail': r're:^https?://.*\.jpg$',
1249 'duration': 3382,
1250 'view_count': int,
1251 },
1252 'params': {
1253 'skip_download': True,
1254 },
135c9c42 1255 },
665e9452 1256 # ClipYou (EaglePlatform) embed (custom URL)
d47ae7f6
S
1257 {
1258 'url': 'http://muz-tv.ru/play/7129/',
4645432d 1259 # Not checking MD5 as sometimes the direct HTTP link results in 404 and HLS is used
d47ae7f6
S
1260 'info_dict': {
1261 'id': '12820',
1262 'ext': 'mp4',
1263 'title': "'O Sole Mio",
ec85ded8 1264 'thumbnail': r're:^https?://.*\.jpg$',
d47ae7f6
S
1265 'duration': 216,
1266 'view_count': int,
1267 },
250b042c
S
1268 'params': {
1269 'skip_download': True,
1270 },
d47ae7f6 1271 },
f8388757
S
1272 # Pladform embed
1273 {
1274 'url': 'http://muz-tv.ru/kinozal/view/7400/',
1275 'info_dict': {
1276 'id': '100183293',
1277 'ext': 'mp4',
62259846 1278 'title': 'Тайны перевала Дятлова • 1 серия 2 часть',
f8388757 1279 'description': 'Документальный сериал-расследование одной из самых жутких тайн ХХ века',
ec85ded8 1280 'thumbnail': r're:^https?://.*\.jpg$',
f8388757
S
1281 'duration': 694,
1282 'age_limit': 0,
1283 },
1284 },
c798f15b
S
1285 # Playwire embed
1286 {
1287 'url': 'http://www.cinemablend.com/new/First-Joe-Dirt-2-Trailer-Teaser-Stupid-Greatness-70874.html',
1288 'info_dict': {
1289 'id': '3519514',
1290 'ext': 'mp4',
1291 'title': 'Joe Dirt 2 Beautiful Loser Teaser Trailer',
ec85ded8 1292 'thumbnail': r're:^https?://.*\.png$',
c798f15b
S
1293 'duration': 45.115,
1294 },
1295 },
ad320e9b
NJ
1296 # 5min embed
1297 {
1298 'url': 'http://techcrunch.com/video/facebook-creates-on-this-day-crunch-report/518726732/',
1299 'md5': '4c6f127a30736b59b3e2c19234ee2bf7',
1300 'info_dict': {
1301 'id': '518726732',
1302 'ext': 'mp4',
1303 'title': 'Facebook Creates "On This Day" | Crunch Report',
1304 },
1305 },
dc455a5f
S
1306 # SVT embed
1307 {
1308 'url': 'http://www.svt.se/sport/ishockey/jagr-tacklar-giroux-under-intervjun',
1309 'info_dict': {
1310 'id': '2900353',
1311 'ext': 'flv',
1312 'title': 'Här trycker Jagr till Giroux (under SVT-intervjun)',
1313 'duration': 27,
1314 'age_limit': 0,
1315 },
1316 },
a4257017
S
1317 # Crooks and Liars embed
1318 {
1319 'url': 'http://crooksandliars.com/2015/04/fox-friends-says-protecting-atheists',
1320 'info_dict': {
1321 'id': '8RUoRhRi',
1322 'ext': 'mp4',
1323 'title': "Fox & Friends Says Protecting Atheists From Discrimination Is Anti-Christian!",
1324 'description': 'md5:e1a46ad1650e3a5ec7196d432799127f',
1325 'timestamp': 1428207000,
1326 'upload_date': '20150405',
1327 'uploader': 'Heather',
1328 },
1329 },
1330 # Crooks and Liars external embed
1331 {
1332 'url': 'http://theothermccain.com/2010/02/02/video-proves-that-bill-kristol-has-been-watching-glenn-beck/comment-page-1/',
1333 'info_dict': {
1334 'id': 'MTE3MjUtMzQ2MzA',
1335 'ext': 'mp4',
1336 'title': 'md5:5e3662a81a4014d24c250d76d41a08d5',
1337 'description': 'md5:9b8e9542d6c3c5de42d6451b7d780cec',
1338 'timestamp': 1265032391,
1339 'upload_date': '20100201',
1340 'uploader': 'Heather',
1341 },
1342 },
facecb84 1343 # NBC Sports vplayer embed
a2edf2e7 1344 {
facecb84 1345 'url': 'http://www.riderfans.com/forum/showthread.php?121827-Freeman&s=e98fa1ea6dc08e886b1678d35212494a',
a2edf2e7 1346 'info_dict': {
facecb84
S
1347 'id': 'ln7x1qSThw4k',
1348 'ext': 'flv',
1349 'title': "PFT Live: New leader in the 'new-look' defense",
1350 'description': 'md5:65a19b4bbfb3b0c0c5768bed1dfad74e',
0738187f
YCH
1351 'uploader': 'NBCU-SPORTS',
1352 'upload_date': '20140107',
1353 'timestamp': 1389118457,
a2edf2e7 1354 },
418c5cc3 1355 },
de3eb07e
YCH
1356 # NBC News embed
1357 {
1358 'url': 'http://www.vulture.com/2016/06/letterman-couldnt-care-less-about-late-night.html',
1359 'md5': '1aa589c675898ae6d37a17913cf68d66',
1360 'info_dict': {
1361 'id': '701714499682',
1362 'ext': 'mp4',
1363 'title': 'PREVIEW: On Assignment: David Letterman',
1364 'description': 'A preview of Tom Brokaw\'s interview with David Letterman as part of the On Assignment series powered by Dateline. Airs Sunday June 12 at 7/6c.',
1365 },
1366 },
418c5cc3
YCH
1367 # UDN embed
1368 {
811586eb 1369 'url': 'https://video.udn.com/news/300346',
01c58f84 1370 'md5': 'fd2060e988c326991037b9aff9df21a6',
418c5cc3 1371 'info_dict': {
01c58f84 1372 'id': '300346',
418c5cc3 1373 'ext': 'mp4',
01c58f84 1374 'title': '中一中男師變性 全校師生力挺',
ec85ded8 1375 'thumbnail': r're:^https?://.*\.jpg$',
811586eb
YCH
1376 },
1377 'params': {
1378 # m3u8 download
1379 'skip_download': True,
1380 },
edfcf7ab
YCH
1381 },
1382 # Ooyala embed
1383 {
1384 'url': 'http://www.businessinsider.com/excel-index-match-vlookup-video-how-to-2015-2?IR=T',
1385 'info_dict': {
1386 'id': '50YnY4czr4ms1vJ7yz3xzq0excz_pUMs',
1387 'ext': 'mp4',
cce9d15d 1388 'description': 'VIDEO: INDEX/MATCH versus VLOOKUP.',
edfcf7ab 1389 'title': 'This is what separates the Excel masters from the wannabes',
53e06b25 1390 'duration': 191.933,
edfcf7ab
YCH
1391 },
1392 'params': {
1393 # m3u8 downloads
1394 'skip_download': True,
1395 }
d6fd958c 1396 },
b26733ba
YCH
1397 # Brightcove URL in single quotes
1398 {
1399 'url': 'http://www.sportsnet.ca/baseball/mlb/sn-presents-russell-martin-world-citizen/',
1400 'md5': '4ae374f1f8b91c889c4b9203c8c752af',
1401 'info_dict': {
1402 'id': '4255764656001',
1403 'ext': 'mp4',
1404 'title': 'SN Presents: Russell Martin, World Citizen',
1405 'description': 'To understand why he was the Toronto Blue Jays’ top off-season priority is to appreciate his background and upbringing in Montreal, where he first developed his baseball skills. Written and narrated by Stephen Brunt.',
1406 'uploader': 'Rogers Sportsnet',
0738187f
YCH
1407 'uploader_id': '1704050871',
1408 'upload_date': '20150525',
1409 'timestamp': 1432570283,
b26733ba 1410 },
756f574e
YCH
1411 },
1412 # Dailymotion Cloud video
1413 {
1414 'url': 'http://replay.publicsenat.fr/vod/le-debat/florent-kolandjian,dominique-cena,axel-decourtye,laurence-abeille,bruno-parmentier/175910',
7d52c052 1415 'md5': 'dcaf23ad0c67a256f4278bce6e0bae38',
756f574e 1416 'info_dict': {
7d52c052 1417 'id': 'x2uy8t3',
756f574e 1418 'ext': 'mp4',
7d52c052
YCH
1419 'title': 'Sauvons les abeilles ! - Le débat',
1420 'description': 'md5:d9082128b1c5277987825d684939ca26',
ec85ded8 1421 'thumbnail': r're:^https?://.*\.jpe?g$',
7d52c052
YCH
1422 'timestamp': 1434970506,
1423 'upload_date': '20150622',
1424 'uploader': 'Public Sénat',
1425 'uploader_id': 'xa9gza',
756f574e 1426 }
a5158f38 1427 },
8084be78
S
1428 # OnionStudios embed
1429 {
1430 'url': 'http://www.clickhole.com/video/dont-understand-bitcoin-man-will-mumble-explanatio-2537',
1431 'info_dict': {
1432 'id': '2855',
1433 'ext': 'mp4',
1434 'title': 'Don’t Understand Bitcoin? This Man Will Mumble An Explanation At You',
ec85ded8 1435 'thumbnail': r're:^https?://.*\.jpe?g$',
8084be78
S
1436 'uploader': 'ClickHole',
1437 'uploader_id': 'clickhole',
1438 }
1439 },
b8c1cc1a
S
1440 # SnagFilms embed
1441 {
1442 'url': 'http://whilewewatch.blogspot.ru/2012/06/whilewewatch-whilewewatch-gripping.html',
1443 'info_dict': {
1444 'id': '74849a00-85a9-11e1-9660-123139220831',
1445 'ext': 'mp4',
1446 'title': '#whilewewatch',
1447 }
1448 },
a5158f38
YCH
1449 # AdobeTVVideo embed
1450 {
1451 'url': 'https://helpx.adobe.com/acrobat/how-to/new-experience-acrobat-dc.html?set=acrobat--get-started--essential-beginners',
1452 'md5': '43662b577c018ad707a63766462b1e87',
1453 'info_dict': {
1454 'id': '2456',
1455 'ext': 'mp4',
1456 'title': 'New experience with Acrobat DC',
1457 'description': 'New experience with Acrobat DC',
1458 'duration': 248.667,
1459 },
1f812580 1460 },
ed126900 1461 # BrightcoveInPageEmbed embed
1462 {
1463 'url': 'http://www.geekandsundry.com/tabletop-bonus-wils-final-thoughts-on-dread/',
1464 'info_dict': {
1465 'id': '4238694884001',
1466 'ext': 'flv',
1467 'title': 'Tabletop: Dread, Last Thoughts',
1468 'description': 'Tabletop: Dread, Last Thoughts',
1469 'duration': 51690,
1470 },
750b9ff0 1471 },
d10fe835
YCH
1472 # Brightcove embed, with no valid 'renditions' but valid 'IOSRenditions'
1473 # This video can't be played in browsers if Flash disabled and UA set to iPhone, which is actually a false alarm
1474 {
1475 'url': 'https://dl.dropboxusercontent.com/u/29092637/interview.html',
1476 'info_dict': {
1477 'id': '4785848093001',
1478 'ext': 'mp4',
1479 'title': 'The Cardinal Pell Interview',
1480 'description': 'Sky News Contributor Andrew Bolt interviews George Pell in Rome, following the Cardinal\'s evidence before the Royal Commission into Child Abuse. ',
1481 'uploader': 'GlobeCast Australia - GlobeStream',
0738187f
YCH
1482 'uploader_id': '2733773828001',
1483 'upload_date': '20160304',
1484 'timestamp': 1457083087,
d10fe835
YCH
1485 },
1486 'params': {
1487 # m3u8 downloads
1488 'skip_download': True,
1489 },
1490 },
9edf47df
S
1491 {
1492 # Brightcove embed with whitespace around attribute names
1493 'url': 'http://www.stack.com/video/3167554373001/learn-to-hit-open-three-pointers-with-damian-lillard-s-baseline-drift-drill',
1494 'info_dict': {
1495 'id': '3167554373001',
1496 'ext': 'mp4',
1497 'title': "Learn to Hit Open Three-Pointers With Damian Lillard's Baseline Drift Drill",
1498 'description': 'md5:57bacb0e0f29349de4972bfda3191713',
1499 'uploader_id': '1079349493',
1500 'upload_date': '20140207',
1501 'timestamp': 1391810548,
1502 },
1503 'params': {
1504 'skip_download': True,
1505 },
1506 },
134c207e
YCH
1507 # Another form of arte.tv embed
1508 {
1509 'url': 'http://www.tv-replay.fr/redirection/09-04-16/arte-reportage-arte-11508975.html',
1510 'md5': '850bfe45417ddf221288c88a0cffe2e2',
1511 'info_dict': {
1512 'id': '030273-562_PLUS7-F',
1513 'ext': 'mp4',
1514 'title': 'ARTE Reportage - Nulle part, en France',
1515 'description': 'md5:e3a0e8868ed7303ed509b9e3af2b870d',
1516 'upload_date': '20160409',
1517 },
1518 },
b8f67449
KM
1519 # LiveLeak embed
1520 {
1521 'url': 'http://www.wykop.pl/link/3088787/',
09747ba7 1522 'md5': '7619da8c820e835bef21a1efa2a0fc71',
b8f67449
KM
1523 'info_dict': {
1524 'id': '874_1459135191',
1525 'ext': 'mp4',
1526 'title': 'Man shows poor quality of new apartment building',
1527 'description': 'The wall is like a sand pile.',
1528 'uploader': 'Lake8737',
09747ba7
YCH
1529 },
1530 'add_ie': [LiveLeakIE.ie_key()],
1531 },
1532 # Another LiveLeak embed pattern (#13336)
1533 {
1534 'url': 'https://milo.yiannopoulos.net/2017/06/concealed-carry-robbery/',
1535 'info_dict': {
1536 'id': '2eb_1496309988',
1537 'ext': 'mp4',
1538 'title': 'Thief robs place where everyone was armed',
1539 'description': 'md5:694d73ee79e535953cf2488562288eee',
1540 'uploader': 'brazilwtf',
1541 },
1542 'add_ie': [LiveLeakIE.ie_key()],
b8f67449 1543 },
4a120778
YCH
1544 # Duplicated embedded video URLs
1545 {
1546 'url': 'http://www.hudl.com/athlete/2538180/highlights/149298443',
1547 'info_dict': {
1548 'id': '149298443_480_16c25b74_2',
1549 'ext': 'mp4',
1550 'title': 'vs. Blue Orange Spring Game',
1551 'uploader': 'www.hudl.com',
1552 },
1553 },
371ddb14
S
1554 # twitter:player:stream embed
1555 {
1556 'url': 'http://www.rtl.be/info/video/589263.aspx?CategoryID=288',
1557 'info_dict': {
1558 'id': 'master',
1559 'ext': 'mp4',
1560 'title': 'Une nouvelle espèce de dinosaure découverte en Argentine',
1561 'uploader': 'www.rtl.be',
1562 },
1563 'params': {
1564 # m3u8 downloads
1565 'skip_download': True,
1566 },
1567 },
32917907
RA
1568 # twitter:player embed
1569 {
1570 'url': 'http://www.theatlantic.com/video/index/484130/what-do-black-holes-sound-like/',
1571 'md5': 'a3e0df96369831de324f0778e126653c',
1572 'info_dict': {
1573 'id': '4909620399001',
1574 'ext': 'mp4',
1575 'title': 'What Do Black Holes Sound Like?',
1576 'description': 'what do black holes sound like',
1577 'upload_date': '20160524',
1578 'uploader_id': '29913724001',
1579 'timestamp': 1464107587,
1580 'uploader': 'TheAtlantic',
1581 },
1582 'add_ie': ['BrightcoveLegacy'],
fd6ca382 1583 },
4e826cd9
S
1584 # Nexx embed
1585 {
1586 'url': 'https://www.funk.net/serien/5940e15073f6120001657956/items/593efbb173f6120001657503',
1587 'info_dict': {
1588 'id': '247746',
1589 'ext': 'mp4',
1590 'title': "Yesterday's Jam (OV)",
1591 'description': 'md5:09bc0984723fed34e2581624a84e05f0',
1592 'timestamp': 1492594816,
1593 'upload_date': '20170419',
1594 },
1595 'params': {
1596 'format': 'bestvideo',
1597 'skip_download': True,
1598 },
1599 },
fd6ca382
YCH
1600 # Facebook <iframe> embed
1601 {
1602 'url': 'https://www.hostblogger.de/blog/archives/6181-Auto-jagt-Betonmischer.html',
dbf0157a 1603 'md5': 'fbcde74f534176ecb015849146dd3aee',
fd6ca382
YCH
1604 'info_dict': {
1605 'id': '599637780109885',
1606 'ext': 'mp4',
1607 'title': 'Facebook video #599637780109885',
1608 },
1609 },
fd1c5fba
S
1610 # Facebook <iframe> embed, plugin video
1611 {
1612 'url': 'http://5pillarsuk.com/2017/06/07/tariq-ramadan-disagrees-with-pr-exercise-by-imams-refusing-funeral-prayers-for-london-attackers/',
1613 'info_dict': {
1614 'id': '1754168231264132',
1615 'ext': 'mp4',
1616 'title': 'About the Imams and Religious leaders refusing to perform funeral prayers for...',
1617 'uploader': 'Tariq Ramadan (official)',
1618 'timestamp': 1496758379,
1619 'upload_date': '20170606',
1620 },
1621 'params': {
1622 'skip_download': True,
1623 },
1624 },
fd6ca382
YCH
1625 # Facebook API embed
1626 {
1627 'url': 'http://www.lothype.com/blue-stars-2016-preview-standstill-full-show/',
dbf0157a 1628 'md5': 'a47372ee61b39a7b90287094d447d94e',
fd6ca382
YCH
1629 'info_dict': {
1630 'id': '10153467542406923',
1631 'ext': 'mp4',
1632 'title': 'Facebook video #10153467542406923',
1633 },
7deef1ba
YCH
1634 },
1635 # Wordpress "YouTube Video Importer" plugin
1636 {
1637 'url': 'http://www.lothype.com/blue-devils-drumline-stanford-lot-2016/',
dbf0157a 1638 'md5': 'd16797741b560b485194eddda8121b48',
7deef1ba
YCH
1639 'info_dict': {
1640 'id': 'HNTXWDXV9Is',
1641 'ext': 'mp4',
1642 'title': 'Blue Devils Drumline Stanford lot 2016',
1643 'upload_date': '20160627',
1644 'uploader_id': 'GENOCIDE8GENERAL10',
1645 'uploader': 'cylus cyrus',
1646 },
1647 },
81953d1a
RA
1648 {
1649 # video stored on custom kaltura server
1650 'url': 'http://www.expansion.com/multimedia/videos.html?media=EQcM30NHIPv',
1651 'md5': '537617d06e64dfed891fa1593c4b30cc',
1652 'info_dict': {
1653 'id': '0_1iotm5bh',
1654 'ext': 'mp4',
1655 'title': 'Elecciones británicas: 5 lecciones para Rajoy',
1656 'description': 'md5:435a89d68b9760b92ce67ed227055f16',
1657 'uploader_id': 'videos.expansion@el-mundo.net',
1658 'upload_date': '20150429',
1659 'timestamp': 1430303472,
1660 },
1661 'add_ie': ['Kaltura'],
1662 },
c03adf90
YCH
1663 {
1664 # Non-standard Vimeo embed
1665 'url': 'https://openclassrooms.com/courses/understanding-the-web',
1666 'md5': '64d86f1c7d369afd9a78b38cbb88d80a',
1667 'info_dict': {
1668 'id': '148867247',
1669 'ext': 'mp4',
1670 'title': 'Understanding the web - Teaser',
1671 'description': 'This is "Understanding the web - Teaser" by openclassrooms on Vimeo, the home for high quality videos and the people who love them.',
1672 'upload_date': '20151214',
1673 'uploader': 'OpenClassrooms',
1674 'uploader_id': 'openclassrooms',
1675 },
1676 'add_ie': ['Vimeo'],
1677 },
a5ff05df
S
1678 {
1679 # generic vimeo embed that requires original URL passed as Referer
1680 'url': 'http://racing4everyone.eu/2016/07/30/formula-1-2016-round12-germany/',
1681 'only_matching': True,
1682 },
1979969f
S
1683 {
1684 'url': 'https://support.arkena.com/display/PLAY/Ways+to+embed+your+video',
1685 'md5': 'b96f2f71b359a8ecd05ce4e1daa72365',
1686 'info_dict': {
1687 'id': 'b41dda37-d8e7-4d3f-b1b5-9a9db578bdfe',
1688 'ext': 'mp4',
1689 'title': 'Big Buck Bunny',
1690 'description': 'Royalty free test video',
1691 'timestamp': 1432816365,
1692 'upload_date': '20150528',
1693 'is_live': False,
1694 },
1695 'params': {
1696 'skip_download': True,
1697 },
1698 'add_ie': [ArkenaIE.ie_key()],
1699 },
2a1321a2
S
1700 {
1701 'url': 'http://nova.bg/news/view/2016/08/16/156543/%D0%BD%D0%B0-%D0%BA%D0%BE%D1%81%D1%8A%D0%BC-%D0%BE%D1%82-%D0%B2%D0%B7%D1%80%D0%B8%D0%B2-%D0%BE%D1%82%D1%86%D0%B5%D0%BF%D0%B8%D1%85%D0%B0-%D1%86%D1%8F%D0%BB-%D0%BA%D0%B2%D0%B0%D1%80%D1%82%D0%B0%D0%BB-%D0%B7%D0%B0%D1%80%D0%B0%D0%B4%D0%B8-%D0%B8%D0%B7%D1%82%D0%B8%D1%87%D0%B0%D0%BD%D0%B5-%D0%BD%D0%B0-%D0%B3%D0%B0%D0%B7-%D0%B2-%D0%BF%D0%BB%D0%BE%D0%B2%D0%B4%D0%B8%D0%B2/',
1702 'info_dict': {
1703 'id': '1c7141f46c',
1704 'ext': 'mp4',
1705 'title': 'НА КОСЪМ ОТ ВЗРИВ: Изтичане на газ на бензиностанция в Пловдив',
1706 },
1707 'params': {
1708 'skip_download': True,
1709 },
1710 'add_ie': [Vbox7IE.ie_key()],
1711 },
b0c8f2e9
DR
1712 {
1713 # DBTV embeds
1714 'url': 'http://www.dagbladet.no/2016/02/23/nyheter/nordlys/ski/troms/ver/43254897/',
fd3ec986
S
1715 'info_dict': {
1716 'id': '43254897',
1717 'title': 'Etter ett års planlegging, klaffet endelig alt: - Jeg måtte ta en liten dans',
1718 },
b0c8f2e9
DR
1719 'playlist_mincount': 3,
1720 },
e186a9ec
S
1721 {
1722 # Videa embeds
1723 'url': 'http://forum.dvdtalk.com/movie-talk/623756-deleted-magic-star-wars-ot-deleted-alt-scenes-docu-style.html',
1724 'info_dict': {
1725 'id': '623756-deleted-magic-star-wars-ot-deleted-alt-scenes-docu-style',
1726 'title': 'Deleted Magic - Star Wars: OT Deleted / Alt. Scenes Docu. Style - DVD Talk Forum',
1727 },
1728 'playlist_mincount': 2,
1729 },
b687c85e
S
1730 {
1731 # 20 minuten embed
1732 'url': 'http://www.20min.ch/schweiz/news/story/So-kommen-Sie-bei-Eis-und-Schnee-sicher-an-27032552',
1733 'info_dict': {
1734 'id': '523629',
1735 'ext': 'mp4',
1736 'title': 'So kommen Sie bei Eis und Schnee sicher an',
1737 'description': 'md5:117c212f64b25e3d95747e5276863f7d',
1738 },
1739 'params': {
1740 'skip_download': True,
1741 },
1742 'add_ie': [TwentyMinutenIE.ie_key()],
6ef3e65a
S
1743 },
1744 {
1745 # VideoPress embed
1746 'url': 'https://en.support.wordpress.com/videopress/',
1747 'info_dict': {
1748 'id': 'OcobLTqC',
1749 'ext': 'm4v',
1750 'title': 'IMG_5786',
1751 'timestamp': 1435711927,
1752 'upload_date': '20150701',
1753 },
1754 'params': {
1755 'skip_download': True,
1756 },
1757 'add_ie': [VideoPressIE.ie_key()],
fef51645 1758 },
eb3079b6
S
1759 {
1760 # Rutube embed
1761 'url': 'http://magazzino.friday.ru/videos/vipuski/kazan-2',
1762 'info_dict': {
1763 'id': '9b3d5bee0a8740bf70dfd29d3ea43541',
1764 'ext': 'flv',
1765 'title': 'Магаззино: Казань 2',
1766 'description': 'md5:99bccdfac2269f0e8fdbc4bbc9db184a',
1767 'uploader': 'Магаззино',
1768 'upload_date': '20170228',
1769 'uploader_id': '996642',
1770 },
1771 'params': {
1772 'skip_download': True,
1773 },
1774 'add_ie': [RutubeIE.ie_key()],
1775 },
fef51645
YCH
1776 {
1777 # ThePlatform embedded with whitespaces in URLs
1778 'url': 'http://www.golfchannel.com/topics/shows/golftalkcentral.htm',
1779 'only_matching': True,
1780 },
97952bdb
JH
1781 {
1782 # Senate ISVP iframe https
1783 'url': 'https://www.hsgac.senate.gov/hearings/canadas-fast-track-refugee-plan-unanswered-questions-and-implications-for-us-national-security',
1784 'md5': 'fb8c70b0b515e5037981a2492099aab8',
1785 'info_dict': {
1786 'id': 'govtaff020316',
1787 'ext': 'mp4',
1788 'title': 'Integrated Senate Video Player',
1789 },
1790 'add_ie': [SenateISVPIE.ie_key()],
1791 },
ab87c260
S
1792 {
1793 # Limelight embeds (1 channel embed + 4 media embeds)
1794 'url': 'http://www.sedona.com/FacilitatorTraining2017',
1795 'info_dict': {
1796 'id': 'FacilitatorTraining2017',
1797 'title': 'Facilitator Training 2017',
1798 },
1799 'playlist_mincount': 5,
1800 },
eb02940c
S
1801 {
1802 # Limelight embed (LimelightPlayerUtil.embed)
1803 'url': 'https://tv5.ca/videos?v=xuu8qowr291ri',
1804 'info_dict': {
1805 'id': '95d035dc5c8a401588e9c0e6bd1e9c92',
1806 'ext': 'mp4',
1807 'title': '07448641',
1808 'timestamp': 1499890639,
1809 'upload_date': '20170712',
1810 },
1811 'params': {
1812 'skip_download': True,
1813 },
1814 'add_ie': ['LimelightMedia'],
1815 },
7986c3ab
S
1816 {
1817 'url': 'http://kron4.com/2017/04/28/standoff-with-walnut-creek-murder-suspect-ends-with-arrest/',
1818 'info_dict': {
1819 'id': 'standoff-with-walnut-creek-murder-suspect-ends-with-arrest',
1820 'title': 'Standoff with Walnut Creek murder suspect ends',
1821 'description': 'md5:3ccc48a60fc9441eeccfc9c469ebf788',
1822 },
1823 'playlist_mincount': 4,
1824 },
55719459
JH
1825 {
1826 # WashingtonPost embed
1827 'url': 'http://www.vanityfair.com/hollywood/2017/04/donald-trump-tv-pitches',
1828 'info_dict': {
1829 'id': '8caf6e88-d0ec-11e5-90d3-34c2c42653ac',
1830 'ext': 'mp4',
1831 'title': "No one has seen the drama series based on Trump's life \u2014 until now",
1832 'description': 'Donald Trump wanted a weekly TV drama based on his life. It never aired. But The Washington Post recently obtained a scene from the pilot script — and enlisted actors.',
1833 'timestamp': 1455216756,
1834 'uploader': 'The Washington Post',
1835 'upload_date': '20160211',
1836 },
1837 'add_ie': [WashingtonPostIE.ie_key()],
1838 },
2b8e6a68
S
1839 {
1840 # Mediaset embed
1841 'url': 'http://www.tgcom24.mediaset.it/politica/serracchiani-voglio-vivere-in-una-societa-aperta-reazioni-sproporzionate-_3071354-201702a.shtml',
1842 'info_dict': {
1843 'id': '720642',
1844 'ext': 'mp4',
1845 'title': 'Serracchiani: "Voglio vivere in una società aperta, con tutela del patto di fiducia"',
1846 },
1847 'params': {
1848 'skip_download': True,
1849 },
1850 'add_ie': [MediasetIE.ie_key()],
1851 },
73cf76a9
S
1852 {
1853 # JOJ.sk embeds
1854 'url': 'https://www.noviny.sk/slovensko/238543-slovenskom-sa-prehnala-vlna-silnych-burok',
1855 'info_dict': {
1856 'id': '238543-slovenskom-sa-prehnala-vlna-silnych-burok',
1857 'title': 'Slovenskom sa prehnala vlna silných búrok',
1858 },
1859 'playlist_mincount': 5,
1860 'add_ie': [JojIE.ie_key()],
1861 },
4328ddf8
S
1862 {
1863 # AMP embed (see https://www.ampproject.org/docs/reference/components/amp-video)
1864 'url': 'https://tvrain.ru/amp/418921/',
1865 'md5': 'cc00413936695987e8de148b67d14f1d',
1866 'info_dict': {
1867 'id': '418921',
1868 'ext': 'mp4',
1869 'title': 'Стас Намин: «Мы нарушили девственность Кремля»',
1870 },
1871 },
41918eaa 1872 {
1873 # vzaar embed
1663bd6e
S
1874 'url': 'http://help.vzaar.com/article/165-embedding-video',
1875 'md5': '7e3919d9d2620b89e3e00bec7fe8c9d4',
41918eaa 1876 'info_dict': {
1663bd6e 1877 'id': '8707641',
41918eaa 1878 'ext': 'mp4',
1663bd6e 1879 'title': 'Building A Business Online: Principal Chairs Q & A',
41918eaa 1880 },
1881 },
6e6b70d6
S
1882 # {
1883 # # TODO: find another test
1884 # # http://schema.org/VideoObject
1885 # 'url': 'https://flipagram.com/f/nyvTSJMKId',
1886 # 'md5': '888dcf08b7ea671381f00fab74692755',
1887 # 'info_dict': {
1888 # 'id': 'nyvTSJMKId',
1889 # 'ext': 'mp4',
1890 # 'title': 'Flipagram by sjuria101 featuring Midnight Memories by One Direction',
1891 # 'description': '#love for cats.',
1892 # 'timestamp': 1461244995,
1893 # 'upload_date': '20160421',
1894 # },
1895 # 'params': {
1896 # 'force_generic_extractor': True,
1897 # },
1898 # }
cfe50f04 1899 ]
9b122384 1900
9b122384
PH
1901 def report_following_redirect(self, new_url):
1902 """Report information extraction."""
79649588 1903 self._downloader.to_screen('[redirect] Following redirect to %s' % new_url)
9b122384 1904
4fc946b5
PH
1905 def _extract_rss(self, url, video_id, doc):
1906 playlist_title = doc.find('./channel/title').text
1907 playlist_desc_el = doc.find('./channel/description')
1908 playlist_desc = None if playlist_desc_el is None else playlist_desc_el.text
1909
76c73715
PH
1910 entries = []
1911 for it in doc.findall('./channel/item'):
1912 next_url = xpath_text(it, 'link', fatal=False)
1913 if not next_url:
1914 enclosure_nodes = it.findall('./enclosure')
1915 for e in enclosure_nodes:
1916 next_url = e.attrib.get('url')
1917 if next_url:
1918 break
1919
1920 if not next_url:
1921 continue
1922
1923 entries.append({
413c1f8e 1924 '_type': 'url_transparent',
76c73715
PH
1925 'url': next_url,
1926 'title': it.find('title').text,
1927 })
4fc946b5
PH
1928
1929 return {
1930 '_type': 'playlist',
1931 'id': url,
1932 'title': playlist_title,
1933 'description': playlist_desc,
1934 'entries': entries,
1935 }
1936
c8e9a235
PH
1937 def _extract_camtasia(self, url, video_id, webpage):
1938 """ Returns None if no camtasia video can be found. """
1939
1940 camtasia_cfg = self._search_regex(
1941 r'fo\.addVariable\(\s*"csConfigFile",\s*"([^"]+)"\s*\);',
1942 webpage, 'camtasia configuration file', default=None)
1943 if camtasia_cfg is None:
1944 return None
1945
1946 title = self._html_search_meta('DC.title', webpage, fatal=True)
1947
1948 camtasia_url = compat_urlparse.urljoin(url, camtasia_cfg)
1949 camtasia_cfg = self._download_xml(
1950 camtasia_url, video_id,
1951 note='Downloading camtasia configuration',
1952 errnote='Failed to download camtasia configuration')
1953 fileset_node = camtasia_cfg.find('./playlist/array/fileset')
1954
1955 entries = []
1956 for n in fileset_node.getchildren():
1957 url_n = n.find('./uri')
1958 if url_n is None:
1959 continue
1960
1961 entries.append({
1962 'id': os.path.splitext(url_n.text.rpartition('/')[2])[0],
1963 'title': '%s - %s' % (title, n.tag),
1964 'url': compat_urlparse.urljoin(url, url_n.text),
1965 'duration': float_or_none(n.find('./duration').text),
1966 })
1967
1968 return {
1969 '_type': 'playlist',
1970 'entries': entries,
1971 'title': title,
1972 }
1973
9b122384 1974 def _real_extract(self, url):
ebd3c7b3
PH
1975 if url.startswith('//'):
1976 return {
1977 '_type': 'url',
20991253 1978 'url': self.http_scheme() + url,
ebd3c7b3
PH
1979 }
1980
a7130543
JMF
1981 parsed_url = compat_urlparse.urlparse(url)
1982 if not parsed_url.scheme:
04b4d394
PH
1983 default_search = self._downloader.params.get('default_search')
1984 if default_search is None:
1f7ccb90 1985 default_search = 'fixup_error'
04b4d394 1986
1f7ccb90 1987 if default_search in ('auto', 'auto_warning', 'fixup_error'):
04b4d394
PH
1988 if '/' in url:
1989 self._downloader.report_warning('The url doesn\'t specify the protocol, trying with http')
1990 return self.url_result('http://' + url)
1f7ccb90 1991 elif default_search != 'fixup_error':
9c1fc022 1992 if default_search == 'auto_warning':
0e67ab0d
PH
1993 if re.match(r'^(?:url|URL)$', url):
1994 raise ExtractorError(
1995 'Invalid URL: %r . Call youtube-dl like this: youtube-dl -v "https://www.youtube.com/watch?v=BaW_jenozKc" ' % url,
1996 expected=True)
1997 else:
1998 self._downloader.report_warning(
7571c02c 1999 'Falling back to youtube search for %s . Set --default-search "auto" to suppress this warning.' % url)
04b4d394 2000 return self.url_result('ytsearch:' + url)
1f7ccb90
PH
2001
2002 if default_search in ('error', 'fixup_error'):
7571c02c 2003 raise ExtractorError(
b74e86f4
PH
2004 '%r is not a valid URL. '
2005 'Set --default-search "ytsearch" (or run youtube-dl "ytsearch:%s" ) to search YouTube'
2006 % (url, url), expected=True)
04b4d394 2007 else:
f2f2c0c2
PH
2008 if ':' not in default_search:
2009 default_search += ':'
04b4d394 2010 return self.url_result(default_search + url)
4d54ef20
PH
2011
2012 url, smuggled_data = unsmuggle_url(url)
2013 force_videoid = None
d6e6a422 2014 is_intentional = smuggled_data and smuggled_data.get('to_generic')
4d54ef20
PH
2015 if smuggled_data and 'force_videoid' in smuggled_data:
2016 force_videoid = smuggled_data['force_videoid']
2017 video_id = force_videoid
2018 else:
9dcd6fd3 2019 video_id = self._generic_id(url)
3d83a1ae 2020
79649588 2021 self.to_screen('%s: Requesting header' % video_id)
c1d1facd 2022
ebab4520 2023 head_req = HEADRequest(url)
23be51d8 2024 head_response = self._request_webpage(
ebab4520
PH
2025 head_req, video_id,
2026 note=False, errnote='Could not send HEAD request to %s' % url,
2027 fatal=False)
42393ce2 2028
23be51d8 2029 if head_response is not False:
42393ce2 2030 # Check for redirect
5551d771 2031 new_url = compat_str(head_response.geturl())
42393ce2
PH
2032 if url != new_url:
2033 self.report_following_redirect(new_url)
4d54ef20
PH
2034 if force_videoid:
2035 new_url = smuggle_url(
2036 new_url, {'force_videoid': force_videoid})
cecaaf3f 2037 return self.url_result(new_url)
42393ce2 2038
23be51d8
PH
2039 full_response = None
2040 if head_response is False:
5c2266df 2041 request = sanitized_Request(url)
58bde34a
S
2042 request.add_header('Accept-Encoding', '*')
2043 full_response = self._request_webpage(request, video_id)
23be51d8
PH
2044 head_response = full_response
2045
f930e0c7
S
2046 info_dict = {
2047 'id': video_id,
9dcd6fd3 2048 'title': self._generic_title(url),
303dcdb9 2049 'upload_date': unified_strdate(head_response.headers.get('Last-Modified'))
f930e0c7
S
2050 }
2051
23be51d8 2052 # Check for direct link to a video
955737b2 2053 content_type = head_response.headers.get('Content-Type', '').lower()
263eff95 2054 m = re.match(r'^(?P<type>audio|video|application(?=/(?:ogg$|(?:vnd\.apple\.|x-)?mpegurl)))/(?P<format_id>[^;\s]+)', content_type)
23be51d8 2055 if m:
4e363703 2056 format_id = compat_str(m.group('format_id'))
f930e0c7 2057 if format_id.endswith('mpegurl'):
eadc3ccd 2058 formats = self._extract_m3u8_formats(url, video_id, 'mp4')
f930e0c7
S
2059 elif format_id == 'f4m':
2060 formats = self._extract_f4m_formats(url, video_id)
eadc3ccd 2061 else:
2062 formats = [{
4e363703 2063 'format_id': format_id,
eadc3ccd 2064 'url': url,
2065 'vcodec': 'none' if m.group('type') == 'audio' else None
2066 }]
de6c51e8 2067 info_dict['direct'] = True
19dbaeec 2068 self._sort_formats(formats)
de6c51e8 2069 info_dict['formats'] = formats
f930e0c7 2070 return info_dict
42393ce2 2071
d6e6a422 2072 if not self._downloader.params.get('test', False) and not is_intentional:
2fece970
S
2073 force = self._downloader.params.get('force_generic_extractor', False)
2074 self._downloader.report_warning(
2075 '%s on generic information extractor.' % ('Forcing' if force else 'Falling back'))
d6e6a422 2076
4e262a88 2077 if not full_response:
5c2266df 2078 request = sanitized_Request(url)
58bde34a
S
2079 # Some webservers may serve compressed content of rather big size (e.g. gzipped flac)
2080 # making it impossible to download only chunk of the file (yet we need only 512kB to
2081 # test whether it's HTML or not). According to youtube-dl default Accept-Encoding
2082 # that will always result in downloading the whole file that is not desirable.
2083 # Therefore for extraction pass we have to override Accept-Encoding to any in order
2084 # to accept raw bytes and being able to download only a chunk.
2085 # It may probably better to solve this by checking Content-Type for application/octet-stream
2086 # after HEAD request finishes, but not sure if we can rely on this.
2087 request.add_header('Accept-Encoding', '*')
2088 full_response = self._request_webpage(request, video_id)
4e262a88 2089
5940862d
S
2090 first_bytes = full_response.read(512)
2091
2092 # Is it an M3U playlist?
0d769bcb 2093 if first_bytes.startswith(b'#EXTM3U'):
5940862d 2094 info_dict['formats'] = self._extract_m3u8_formats(url, video_id, 'mp4')
19dbaeec 2095 self._sort_formats(info_dict['formats'])
5940862d
S
2096 return info_dict
2097
4e262a88
PH
2098 # Maybe it's a direct link to a video?
2099 # Be careful not to download the whole thing!
61ca9a80 2100 if not is_html(first_bytes):
4e262a88
PH
2101 self._downloader.report_warning(
2102 'URL could be a direct video link, returning it as such.')
f930e0c7 2103 info_dict.update({
4e262a88
PH
2104 'direct': True,
2105 'url': url,
f930e0c7
S
2106 })
2107 return info_dict
4e262a88
PH
2108
2109 webpage = self._webpage_read_content(
2110 full_response, url, video_id, prefix=first_bytes)
2111
9b122384 2112 self.report_extraction(video_id)
887c6acd 2113
1b840245 2114 # Is it an RSS feed, a SMIL file, an XSPF playlist or a MPD manifest?
4fc946b5 2115 try:
f7854627 2116 doc = compat_etree_fromstring(webpage.encode('utf-8'))
4fc946b5
PH
2117 if doc.tag == 'rss':
2118 return self._extract_rss(url, video_id, doc)
cc99a77a
S
2119 elif doc.tag == 'SmoothStreamingMedia':
2120 info_dict['formats'] = self._parse_ism_formats(doc, url)
2121 self._sort_formats(info_dict['formats'])
2122 return info_dict
e5e8d20a 2123 elif re.match(r'^(?:{[^}]+})?smil$', doc.tag):
19dbaeec
S
2124 smil = self._parse_smil(doc, url, video_id)
2125 self._sort_formats(smil['formats'])
2126 return smil
729accb4
S
2127 elif doc.tag == '{http://xspf.org/ns/0/}playlist':
2128 return self.playlist_result(self._parse_xspf(doc, video_id), video_id)
1b840245 2129 elif re.match(r'(?i)^(?:{[^}]+})?MPD$', doc.tag):
f930e0c7 2130 info_dict['formats'] = self._parse_mpd_formats(
86f4d14f 2131 doc, video_id,
5551d771 2132 mpd_base_url=compat_str(full_response.geturl()).rpartition('/')[0],
86f4d14f 2133 mpd_url=url)
19dbaeec 2134 self._sort_formats(info_dict['formats'])
f930e0c7
S
2135 return info_dict
2136 elif re.match(r'^{http://ns\.adobe\.com/f4m/[12]\.0}manifest$', doc.tag):
2137 info_dict['formats'] = self._parse_f4m_formats(doc, url, video_id)
19dbaeec 2138 self._sort_formats(info_dict['formats'])
f930e0c7 2139 return info_dict
f7300c5c 2140 except compat_xml_parse_error:
4fc946b5
PH
2141 pass
2142
c8e9a235
PH
2143 # Is it a Camtasia project?
2144 camtasia_res = self._extract_camtasia(url, video_id, webpage)
2145 if camtasia_res is not None:
2146 return camtasia_res
2147
14390730
S
2148 # Sometimes embedded video player is hidden behind percent encoding
2149 # (e.g. https://github.com/rg3/youtube-dl/issues/2448)
2150 # Unescaping the whole page allows to handle those cases in a generic way
45eedbe5 2151 webpage = compat_urllib_parse_unquote(webpage)
1f7659db 2152
887c6acd
PH
2153 # it's tempting to parse this further, but you would
2154 # have to take into account all the variations like
2155 # Video Title - Site Name
2156 # Site Name | Video Title
2157 # Video Title - Tagline | Site Name
2158 # and so on and so forth; it's just not practical
6f41b2bc
S
2159 video_title = self._og_search_title(
2160 webpage, default=None) or self._html_search_regex(
79649588
PH
2161 r'(?s)<title>(.*?)</title>', webpage, 'video title',
2162 default='video')
ef4fd848 2163
4d805e06
PH
2164 # Try to detect age limit automatically
2165 age_limit = self._rta_search(webpage)
2166 # And then there are the jokers who advertise that they use RTA,
2167 # but actually don't.
2168 AGE_LIMIT_MARKERS = [
2169 r'Proudly Labeled <a href="http://www.rtalabel.org/" title="Restricted to Adults">RTA</a>',
2170 ]
2171 if any(re.search(marker, webpage) for marker in AGE_LIMIT_MARKERS):
2172 age_limit = 18
2173
ef4fd848
PH
2174 # video uploader is domain name
2175 video_uploader = self._search_regex(
79649588 2176 r'^(?:https?://)?([^/]*)/.*', url, 'video uploader')
887c6acd 2177
6f41b2bc
S
2178 video_description = self._og_search_description(webpage, default=None)
2179 video_thumbnail = self._og_search_thumbnail(webpage, default=None)
2180
b311b0ea
S
2181 info_dict.update({
2182 'title': video_title,
2183 'description': video_description,
2184 'thumbnail': video_thumbnail,
2185 'age_limit': age_limit,
2186 })
2187
1f4b722b 2188 # Look for Brightcove Legacy Studio embeds
4fcaa4f4 2189 bc_urls = BrightcoveLegacyIE._extract_brightcove_urls(webpage)
99877772 2190 if bc_urls:
99877772
PH
2191 entries = [{
2192 '_type': 'url',
2193 'url': smuggle_url(bc_url, {'Referer': url}),
3b7d9aa4 2194 'ie_key': 'BrightcoveLegacy'
99877772
PH
2195 } for bc_url in bc_urls]
2196
2197 return {
2198 '_type': 'playlist',
2199 'title': video_title,
2200 'id': video_id,
2201 'entries': entries,
2202 }
cfe50f04 2203
f6519f89 2204 # Look for Brightcove New Studio embeds
0254f93b 2205 bc_urls = BrightcoveNewIE._extract_urls(self, webpage)
f6519f89 2206 if bc_urls:
46b18f23 2207 return self.playlist_from_matches(bc_urls, video_id, video_title, ie='BrightcoveNew')
ed126900 2208
4e826cd9
S
2209 # Look for Nexx embeds
2210 nexx_urls = NexxIE._extract_urls(webpage)
2211 if nexx_urls:
2212 return self.playlist_from_matches(nexx_urls, video_id, video_title, ie=NexxIE.ie_key())
2213
3f59b015
S
2214 # Look for Nexx iFrame embeds
2215 nexx_embed_urls = NexxEmbedIE._extract_urls(webpage)
2216 if nexx_embed_urls:
2217 return self.playlist_from_matches(nexx_embed_urls, video_id, video_title, ie=NexxEmbedIE.ie_key())
2218
4d8819d2
S
2219 # Look for ThePlatform embeds
2220 tp_urls = ThePlatformIE._extract_urls(webpage)
2221 if tp_urls:
46b18f23 2222 return self.playlist_from_matches(tp_urls, video_id, video_title, ie='ThePlatform')
4d8819d2 2223
48a5eabc
S
2224 # Look for Vessel embeds
2225 vessel_urls = VesselIE._extract_urls(webpage)
2226 if vessel_urls:
46b18f23 2227 return self.playlist_from_matches(vessel_urls, video_id, video_title, ie=VesselIE.ie_key())
48a5eabc 2228
59b8ab58
PH
2229 # Look for embedded rtl.nl player
2230 matches = re.findall(
97b570a9 2231 r'<iframe[^>]+?src="((?:https?:)?//(?:www\.)?rtl\.nl/system/videoplayer/[^"]+(?:video_)?embed[^"]+)"',
59b8ab58
PH
2232 webpage)
2233 if matches:
46b18f23 2234 return self.playlist_from_matches(matches, video_id, video_title, ie='RtlNl')
59b8ab58 2235
09b9c45e
S
2236 vimeo_urls = VimeoIE._extract_urls(url, webpage)
2237 if vimeo_urls:
46b18f23 2238 return self.playlist_from_matches(vimeo_urls, video_id, video_title, ie=VimeoIE.ie_key())
7115ca84 2239
a1b85269
YCH
2240 vid_me_embed_url = self._search_regex(
2241 r'src=[\'"](https?://vid\.me/[^\'"]+)[\'"]',
2242 webpage, 'vid.me embed', default=None)
2243 if vid_me_embed_url is not None:
2244 return self.url_result(vid_me_embed_url, 'Vidme')
2245
53c1d3ef 2246 # Look for embedded YouTube player
1f9da904 2247 matches = re.findall(r'''(?x)
2b88feed
PH
2248 (?:
2249 <iframe[^>]+?src=|
c71dfccc 2250 data-video-url=|
2b88feed 2251 <embed[^>]+?src=|
a7e97f6d 2252 embedSWF\(?:\s*|
61568e50 2253 <object[^>]+data=|
a7e97f6d 2254 new\s+SWFObject\(
2b88feed
PH
2255 )
2256 (["\'])
1bf5423e 2257 (?P<url>(?:https?:)?//(?:www\.)?youtube(?:-nocookie)?\.com/
6b08cdf6 2258 (?:embed|v|p)/.+?)
1f9da904 2259 \1''', webpage)
887c6acd 2260 if matches:
46b18f23
JH
2261 return self.playlist_from_matches(
2262 matches, video_id, video_title, lambda m: unescapeHTML(m[1]))
53c1d3ef 2263
65f3a228
PH
2264 # Look for lazyYT YouTube embed
2265 matches = re.findall(
2266 r'class="lazyYT" data-youtube-id="([^"]+)"', webpage)
2267 if matches:
46b18f23 2268 return self.playlist_from_matches(matches, video_id, video_title, lambda m: unescapeHTML(m))
65f3a228 2269
7deef1ba
YCH
2270 # Look for Wordpress "YouTube Video Importer" plugin
2271 matches = re.findall(r'''(?x)<div[^>]+
2272 class=(?P<q1>[\'"])[^\'"]*\byvii_single_video_player\b[^\'"]*(?P=q1)[^>]+
2273 data-video_id=(?P<q2>[\'"])([^\'"]+)(?P=q2)''', webpage)
2274 if matches:
46b18f23 2275 return self.playlist_from_matches(matches, video_id, video_title, lambda m: m[-1])
7deef1ba 2276
ad213a1d 2277 matches = DailymotionIE._extract_urls(webpage)
355e4fd0 2278 if matches:
46b18f23 2279 return self.playlist_from_matches(matches, video_id, video_title)
355e4fd0 2280
8489578d
NJ
2281 # Look for embedded Dailymotion playlist player (#3822)
2282 m = re.search(
2283 r'<iframe[^>]+?src=(["\'])(?P<url>(?:https?:)?//(?:www\.)?dailymotion\.[a-z]{2,3}/widget/jukebox\?.+?)\1', webpage)
2284 if m:
2285 playlists = re.findall(
2286 r'list\[\]=/playlist/([^/]+)/', unescapeHTML(m.group('url')))
2287 if playlists:
46b18f23
JH
2288 return self.playlist_from_matches(
2289 playlists, video_id, video_title, lambda p: '//dailymotion.com/playlist/%s' % p)
8489578d 2290
71a1db89
S
2291 # Look for DailyMail embeds
2292 dailymail_urls = DailyMailIE._extract_urls(webpage)
2293 if dailymail_urls:
2294 return self.playlist_from_matches(
2295 dailymail_urls, video_id, video_title, ie=DailyMailIE.ie_key())
2296
ef4fd848 2297 # Look for embedded Wistia player
58bb4402
S
2298 wistia_url = WistiaIE._extract_url(webpage)
2299 if wistia_url:
ef4fd848
PH
2300 return {
2301 '_type': 'url_transparent',
58bb4402
S
2302 'url': self._proto_relative_url(wistia_url),
2303 'ie_key': WistiaIE.ie_key(),
ef4fd848 2304 'uploader': video_uploader,
ef4fd848 2305 }
5f6a1245 2306
bab19a8e
S
2307 # Look for SVT player
2308 svt_url = SVTIE._extract_url(webpage)
2309 if svt_url:
2310 return self.url_result(svt_url, 'SVT')
2311
c19f7764
JMF
2312 # Look for Bandcamp pages with custom domain
2313 mobj = re.search(r'<meta property="og:url"[^>]*?content="(.*?bandcamp\.com.*?)"', webpage)
2314 if mobj is not None:
2315 burl = unescapeHTML(mobj.group(1))
09804265
JMF
2316 # Don't set the extractor because it can be a track url or an album
2317 return self.url_result(burl)
c19f7764 2318
f25571ff
PH
2319 # Look for embedded Vevo player
2320 mobj = re.search(
2321 r'<iframe[^>]+?src=(["\'])(?P<url>(?:https?:)?//(?:cache\.)?vevo\.com/.+?)\1', webpage)
2322 if mobj is not None:
2323 return self.url_result(mobj.group('url'))
796df3c6
S
2324
2325 # Look for embedded Viddler player
cb454b33
S
2326 mobj = re.search(
2327 r'<(?:iframe[^>]+?src|param[^>]+?value)=(["\'])(?P<url>(?:https?:)?//(?:www\.)?viddler\.com/(?:embed|player)/.+?)\1',
2328 webpage)
796df3c6
S
2329 if mobj is not None:
2330 return self.url_result(mobj.group('url'))
f25571ff 2331
3378d67a
S
2332 # Look for NYTimes player
2333 mobj = re.search(
2334 r'<iframe[^>]+src=(["\'])(?P<url>(?:https?:)?//graphics8\.nytimes\.com/bcvideo/[^/]+/iframe/embed\.html.+?)\1>',
2335 webpage)
2336 if mobj is not None:
2337 return self.url_result(mobj.group('url'))
2338
cefdf970
S
2339 # Look for Libsyn player
2340 mobj = re.search(
2341 r'<iframe[^>]+src=(["\'])(?P<url>(?:https?:)?//html5-player\.libsyn\.com/embed/.+?)\1', webpage)
2342 if mobj is not None:
2343 return self.url_result(mobj.group('url'))
2344
c0d0b01f 2345 # Look for Ooyala videos
8a37aa15 2346 mobj = (re.search(r'player\.ooyala\.com/[^"?]+[?#][^"]*?(?:embedCode|ec)=(?P<ec>[^"&]+)', webpage) or
f076b638 2347 re.search(r'OO\.Player\.create\([\'"].*?[\'"],\s*[\'"](?P<ec>.{32})[\'"]', webpage) or
198d4cb4 2348 re.search(r'OO\.Player\.create\.apply\(\s*OO\.Player\s*,\s*op\(\s*\[\s*[\'"][^\'"]*[\'"]\s*,\s*[\'"](?P<ec>.{32})[\'"]', webpage) or
edfcf7ab
YCH
2349 re.search(r'SBN\.VideoLinkset\.ooyala\([\'"](?P<ec>.{32})[\'"]\)', webpage) or
2350 re.search(r'data-ooyala-video-id\s*=\s*[\'"](?P<ec>.{32})[\'"]', webpage))
c0d0b01f 2351 if mobj is not None:
9837cb75
RA
2352 embed_token = self._search_regex(
2353 r'embedToken[\'"]?\s*:\s*[\'"]([^\'"]+)',
2354 webpage, 'ooyala embed token', default=None)
2355 return OoyalaIE._build_url_result(smuggle_url(
2356 mobj.group('ec'), {
2357 'domain': url,
2358 'embed_token': embed_token,
2359 }))
c0d0b01f 2360
f076b638 2361 # Look for multiple Ooyala embeds on SBN network websites
2362 mobj = re.search(r'SBN\.VideoLinkset\.entryGroup\((\[.*?\])', webpage)
2363 if mobj is not None:
2364 embeds = self._parse_json(mobj.group(1), video_id, fatal=False)
2365 if embeds:
46b18f23
JH
2366 return self.playlist_from_matches(
2367 embeds, video_id, video_title,
2368 getter=lambda v: OoyalaIE._url_for_embed_code(smuggle_url(v['provider_video_id'], {'domain': url})), ie='Ooyala')
f076b638 2369
aa94a6d3 2370 # Look for Aparat videos
48099643 2371 mobj = re.search(r'<iframe .*?src="(http://www\.aparat\.com/video/[^"]+)"', webpage)
aa94a6d3
PH
2372 if mobj is not None:
2373 return self.url_result(mobj.group(1), 'Aparat')
2374
c93c2ab1 2375 # Look for MPORA videos
c3f51436 2376 mobj = re.search(r'<iframe .*?src="(http://mpora\.(?:com|de)/videos/[^"]+)"', webpage)
c93c2ab1
PH
2377 if mobj is not None:
2378 return self.url_result(mobj.group(1), 'Mpora')
5f59ee79 2379
15c0e8e7 2380 # Look for embedded NovaMov-based player
8f89e687 2381 mobj = re.search(
8dfa187b 2382 r'''(?x)<(?:pagespeed_)?iframe[^>]+?src=(["\'])
15c0e8e7
S
2383 (?P<url>http://(?:(?:embed|www)\.)?
2384 (?:novamov\.com|
2385 nowvideo\.(?:ch|sx|eu|at|ag|co)|
2386 videoweed\.(?:es|com)|
2387 movshare\.(?:net|sx|ag)|
2388 divxstage\.(?:eu|net|ch|co|at|ag))
2389 /embed\.php.+?)\1''', webpage)
8f89e687 2390 if mobj is not None:
15c0e8e7 2391 return self.url_result(mobj.group('url'))
50f56607 2392
9834872b 2393 # Look for embedded Facebook player
0646e34c
S
2394 facebook_urls = FacebookIE._extract_urls(webpage)
2395 if facebook_urls:
2396 return self.playlist_from_matches(facebook_urls, video_id, video_title)
9834872b 2397
ca97a56e
S
2398 # Look for embedded VK player
2399 mobj = re.search(r'<iframe[^>]+?src=(["\'])(?P<url>https?://vk\.com/video_ext\.php.+?)\1', webpage)
2400 if mobj is not None:
2401 return self.url_result(mobj.group('url'), 'VK')
2402
33d4fdab
S
2403 # Look for embedded Odnoklassniki player
2404 mobj = re.search(r'<iframe[^>]+?src=(["\'])(?P<url>https?://(?:odnoklassniki|ok)\.ru/videoembed/.+?)\1', webpage)
2405 if mobj is not None:
2406 return self.url_result(mobj.group('url'), 'Odnoklassniki')
2407
0364fa8b
S
2408 # Look for embedded ivi player
2409 mobj = re.search(r'<embed[^>]+?src=(["\'])(?P<url>https?://(?:www\.)?ivi\.ru/video/player.+?)\1', webpage)
2410 if mobj is not None:
2411 return self.url_result(mobj.group('url'), 'Ivi')
2412
db1f3888
PH
2413 # Look for embedded Huffington Post player
2414 mobj = re.search(
c3f51436 2415 r'<iframe[^>]+?src=(["\'])(?P<url>https?://embed\.live\.huffingtonpost\.com/.+?)\1', webpage)
db1f3888
PH
2416 if mobj is not None:
2417 return self.url_result(mobj.group('url'), 'HuffPost')
2418
1b86cc41 2419 # Look for embed.ly
2420 mobj = re.search(r'class=["\']embedly-card["\'][^>]href=["\'](?P<url>[^"\']+)', webpage)
2421 if mobj is not None:
2422 return self.url_result(mobj.group('url'))
2423 mobj = re.search(r'class=["\']embedly-embed["\'][^>]src=["\'][^"\']*url=(?P<url>[^&]+)', webpage)
2424 if mobj is not None:
f7e6f7fa 2425 return self.url_result(compat_urllib_parse_unquote(mobj.group('url')))
1b86cc41 2426
60cc4dc4
PH
2427 # Look for funnyordie embed
2428 matches = re.findall(r'<iframe[^>]+?src="(https?://(?:www\.)?funnyordie\.com/embed/[^"]+)"', webpage)
2429 if matches:
46b18f23
JH
2430 return self.playlist_from_matches(
2431 matches, video_id, video_title, getter=unescapeHTML, ie='FunnyOrDie')
60cc4dc4 2432
db546cf8
S
2433 # Look for BBC iPlayer embed
2434 matches = re.findall(r'setPlaylist\("(https?://www\.bbc\.co\.uk/iplayer/[^/]+/[\da-z]{8})"\)', webpage)
2435 if matches:
46b18f23 2436 return self.playlist_from_matches(matches, video_id, video_title, ie='BBCCoUk')
db546cf8 2437
93d020dd
S
2438 # Look for embedded RUTV player
2439 rutv_url = RUTVIE._extract_url(webpage)
2440 if rutv_url:
2441 return self.url_result(rutv_url, 'RUTV')
2442
494f20cb 2443 # Look for embedded TVC player
b8599718
S
2444 tvc_url = TVCIE._extract_url(webpage)
2445 if tvc_url:
2446 return self.url_result(tvc_url, 'TVC')
494f20cb 2447
d40a3b5b
S
2448 # Look for embedded SportBox player
2449 sportbox_urls = SportBoxEmbedIE._extract_urls(webpage)
2450 if sportbox_urls:
46b18f23 2451 return self.playlist_from_matches(sportbox_urls, video_id, video_title, ie='SportBoxEmbed')
d40a3b5b 2452
2bb5b6d0
S
2453 # Look for embedded XHamster player
2454 xhamster_urls = XHamsterEmbedIE._extract_urls(webpage)
2455 if xhamster_urls:
46b18f23 2456 return self.playlist_from_matches(xhamster_urls, video_id, video_title, ie='XHamsterEmbed')
2bb5b6d0 2457
2c9ca782
S
2458 # Look for embedded TNAFlixNetwork player
2459 tnaflix_urls = TNAFlixNetworkEmbedIE._extract_urls(webpage)
2460 if tnaflix_urls:
46b18f23 2461 return self.playlist_from_matches(tnaflix_urls, video_id, video_title, ie=TNAFlixNetworkEmbedIE.ie_key())
2c9ca782 2462
b52c9ef1
S
2463 # Look for embedded PornHub player
2464 pornhub_urls = PornHubIE._extract_urls(webpage)
2465 if pornhub_urls:
46b18f23 2466 return self.playlist_from_matches(pornhub_urls, video_id, video_title, ie=PornHubIE.ie_key())
b52c9ef1 2467
37e7a71c
S
2468 # Look for embedded DrTuber player
2469 drtuber_urls = DrTuberIE._extract_urls(webpage)
2470 if drtuber_urls:
46b18f23 2471 return self.playlist_from_matches(drtuber_urls, video_id, video_title, ie=DrTuberIE.ie_key())
37e7a71c 2472
e28ed498
S
2473 # Look for embedded RedTube player
2474 redtube_urls = RedTubeIE._extract_urls(webpage)
2475 if redtube_urls:
46b18f23 2476 return self.playlist_from_matches(redtube_urls, video_id, video_title, ie=RedTubeIE.ie_key())
e28ed498 2477
9872d311
S
2478 # Look for embedded Tvigle player
2479 mobj = re.search(
2480 r'<iframe[^>]+?src=(["\'])(?P<url>(?:https?:)?//cloud\.tvigle\.ru/video/.+?)\1', webpage)
2481 if mobj is not None:
2482 return self.url_result(mobj.group('url'), 'Tvigle')
2483
7e2ede98
JMF
2484 # Look for embedded TED player
2485 mobj = re.search(
d7cc31b6 2486 r'<iframe[^>]+?src=(["\'])(?P<url>https?://embed(?:-ssl)?\.ted\.com/.+?)\1', webpage)
7e2ede98
JMF
2487 if mobj is not None:
2488 return self.url_result(mobj.group('url'), 'TED')
2489
5c386252 2490 # Look for embedded Ustream videos
d77ac737
YCH
2491 ustream_url = UstreamIE._extract_url(webpage)
2492 if ustream_url:
2493 return self.url_result(ustream_url, UstreamIE.ie_key())
5c386252 2494
893f8832
PH
2495 # Look for embedded arte.tv player
2496 mobj = re.search(
134c207e 2497 r'<(?:script|iframe) [^>]*?src="(?P<url>http://www\.arte\.tv/(?:playerv2/embed|arte_vp/index)[^"]+)"',
893f8832
PH
2498 webpage)
2499 if mobj is not None:
2500 return self.url_result(mobj.group('url'), 'ArteTVEmbed')
2501
cbd55ade
S
2502 # Look for embedded francetv player
2503 mobj = re.search(
2504 r'<iframe[^>]+?src=(["\'])(?P<url>(?:https?://)?embed\.francetv\.fr/\?ue=.+?)\1',
2505 webpage)
2506 if mobj is not None:
2507 return self.url_result(mobj.group('url'))
2508
cb3ac1c6
S
2509 # Look for embedded smotri.com player
2510 smotri_url = SmotriIE._extract_url(webpage)
2511 if smotri_url:
2512 return self.url_result(smotri_url, 'Smotri')
2513
e6c2d9ad 2514 # Look for embedded Myvi.ru player
6dd94d3a 2515 myvi_url = MyviIE._extract_url(webpage)
e6c2d9ad
S
2516 if myvi_url:
2517 return self.url_result(myvi_url)
2518
dfb1b146 2519 # Look for embedded soundcloud player
94aae015
S
2520 soundcloud_urls = SoundcloudIE._extract_urls(webpage)
2521 if soundcloud_urls:
46b18f23 2522 return self.playlist_from_matches(soundcloud_urls, video_id, video_title, getter=unescapeHTML, ie=SoundcloudIE.ie_key())
20991253 2523
027e2312
S
2524 # Look for tunein player
2525 tunein_urls = TuneInBaseIE._extract_urls(webpage)
2526 if tunein_urls:
46b18f23 2527 return self.playlist_from_matches(tunein_urls, video_id, video_title)
027e2312 2528
c5cd249e 2529 # Look for embedded mtvservices player
46fde8a1
S
2530 mtvservices_url = MTVServicesEmbeddedIE._extract_url(webpage)
2531 if mtvservices_url:
2532 return self.url_result(mtvservices_url, ie='MTVServicesEmbedded')
c5cd249e 2533
49807b4a
S
2534 # Look for embedded yahoo player
2535 mobj = re.search(
2536 r'<iframe[^>]+?src=(["\'])(?P<url>https?://(?:screen|movies)\.yahoo\.com/.+?\.html\?format=embed)\1',
2537 webpage)
2538 if mobj is not None:
2539 return self.url_result(mobj.group('url'), 'Yahoo')
2540
2ef6fcb5
PH
2541 # Look for embedded sbs.com.au player
2542 mobj = re.search(
e98b8e79
PH
2543 r'''(?x)
2544 (?:
2545 <meta\s+property="og:video"\s+content=|
2546 <iframe[^>]+?src=
2547 )
2548 (["\'])(?P<url>https?://(?:www\.)?sbs\.com\.au/ondemand/video/.+?)\1''',
2ef6fcb5
PH
2549 webpage)
2550 if mobj is not None:
2551 return self.url_result(mobj.group('url'), 'SBS')
2552
42bdd9d0
PH
2553 # Look for embedded Cinchcast player
2554 mobj = re.search(
2555 r'<iframe[^>]+?src=(["\'])(?P<url>https?://player\.cinchcast\.com/.+?)\1',
2556 webpage)
2557 if mobj is not None:
2558 return self.url_result(mobj.group('url'), 'Cinchcast')
2559
1a94ff68 2560 mobj = re.search(
5263cdfc 2561 r'<iframe[^>]+?src=(["\'])(?P<url>https?://m(?:lb)?\.mlb\.com/shared/video/embed/embed\.html\?.+?)\1',
1a94ff68 2562 webpage)
8001607e
YCH
2563 if not mobj:
2564 mobj = re.search(
2565 r'data-video-link=["\'](?P<url>http://m.mlb.com/video/[^"\']+)',
2566 webpage)
1a94ff68
S
2567 if mobj is not None:
2568 return self.url_result(mobj.group('url'), 'MLB')
2569
1419fafd 2570 mobj = re.search(
dd467d33 2571 r'<(?:iframe|script)[^>]+?src=(["\'])(?P<url>%s)\1' % CondeNastIE.EMBED_URL,
1419fafd
S
2572 webpage)
2573 if mobj is not None:
2574 return self.url_result(self._proto_relative_url(mobj.group('url'), scheme='http:'), 'CondeNast')
2575
af63fed7 2576 mobj = re.search(
78d3b3e2 2577 r'<iframe[^>]+src="(?P<url>https?://(?:new\.)?livestream\.com/[^"]+/player[^"]+)"',
af63fed7
PH
2578 webpage)
2579 if mobj is not None:
2580 return self.url_result(mobj.group('url'), 'Livestream')
2581
255fca5e
S
2582 # Look for Zapiks embed
2583 mobj = re.search(
2584 r'<iframe[^>]+src="(?P<url>https?://(?:www\.)?zapiks\.fr/index\.php\?.+?)"', webpage)
2585 if mobj is not None:
2586 return self.url_result(mobj.group('url'), 'Zapiks')
2587
e3216b82 2588 # Look for Kaltura embeds
c287f2bc
S
2589 kaltura_url = KalturaIE._extract_url(webpage)
2590 if kaltura_url:
2591 return self.url_result(smuggle_url(kaltura_url, {'source_url': url}), KalturaIE.ie_key())
e3216b82 2592
665e9452 2593 # Look for EaglePlatform embeds
06a96da1
S
2594 eagleplatform_url = EaglePlatformIE._extract_url(webpage)
2595 if eagleplatform_url:
665e9452 2596 return self.url_result(smuggle_url(eagleplatform_url, {'referrer': url}), EaglePlatformIE.ie_key())
135c9c42 2597
665e9452 2598 # Look for ClipYou (uses EaglePlatform) embeds
d47ae7f6
S
2599 mobj = re.search(
2600 r'<iframe[^>]+src="https?://(?P<host>media\.clipyou\.ru)/index/player\?.*\brecord_id=(?P<id>\d+).*"', webpage)
2601 if mobj is not None:
2602 return self.url_result('eagleplatform:%(host)s:%(id)s' % mobj.groupdict(), 'EaglePlatform')
2603
f8388757 2604 # Look for Pladform embeds
45dad7ba
S
2605 pladform_url = PladformIE._extract_url(webpage)
2606 if pladform_url:
2607 return self.url_result(pladform_url)
f8388757 2608
ff18735c
S
2609 # Look for Videomore embeds
2610 videomore_url = VideomoreIE._extract_url(webpage)
2611 if videomore_url:
2612 return self.url_result(videomore_url)
2613
83f1481b
S
2614 # Look for Webcaster embeds
2615 webcaster_url = WebcasterFeedIE._extract_url(self, webpage)
2616 if webcaster_url:
2617 return self.url_result(webcaster_url, ie=WebcasterFeedIE.ie_key())
2618
2dcc114f
S
2619 # Look for Playwire embeds
2620 mobj = re.search(
2621 r'<script[^>]+data-config=(["\'])(?P<url>(?:https?:)?//config\.playwire\.com/.+?)\1', webpage)
2622 if mobj is not None:
2623 return self.url_result(mobj.group('url'))
2624
ad320e9b
NJ
2625 # Look for 5min embeds
2626 mobj = re.search(
2627 r'<meta[^>]+property="og:video"[^>]+content="https?://embed\.5min\.com/(?P<id>[0-9]+)/?', webpage)
2628 if mobj is not None:
2629 return self.url_result('5min:%s' % mobj.group('id'), 'FiveMin')
2630
18153f1b
S
2631 # Look for Crooks and Liars embeds
2632 mobj = re.search(
2633 r'<(?:iframe[^>]+src|param[^>]+value)=(["\'])(?P<url>(?:https?:)?//embed\.crooksandliars\.com/(?:embed|v)/.+?)\1', webpage)
2634 if mobj is not None:
2635 return self.url_result(mobj.group('url'))
2636
a2edf2e7
YCH
2637 # Look for NBC Sports VPlayer embeds
2638 nbc_sports_url = NBCSportsVPlayerIE._extract_url(webpage)
2639 if nbc_sports_url:
2640 return self.url_result(nbc_sports_url, 'NBCSportsVPlayer')
2641
de3eb07e
YCH
2642 # Look for NBC News embeds
2643 nbc_news_embed_url = re.search(
2644 r'<iframe[^>]+src=(["\'])(?P<url>(?:https?:)?//www\.nbcnews\.com/widget/video-embed/[^"\']+)\1', webpage)
2645 if nbc_news_embed_url:
2646 return self.url_result(nbc_news_embed_url.group('url'), 'NBCNews')
2647
653789af 2648 # Look for Google Drive embeds
5b251628 2649 google_drive_url = GoogleDriveIE._extract_url(webpage)
653789af 2650 if google_drive_url:
2651 return self.url_result(google_drive_url, 'GoogleDrive')
2652
418c5cc3
YCH
2653 # Look for UDN embeds
2654 mobj = re.search(
c39fd7b1 2655 r'<iframe[^>]+src="(?P<url>%s)"' % UDNEmbedIE._PROTOCOL_RELATIVE_VALID_URL, webpage)
418c5cc3
YCH
2656 if mobj is not None:
2657 return self.url_result(
0a160363 2658 compat_urlparse.urljoin(url, mobj.group('url')), 'UDNEmbed')
418c5cc3 2659
2fe1b5bd
YCH
2660 # Look for Senate ISVP iframe
2661 senate_isvp_url = SenateISVPIE._search_iframe_url(webpage)
2662 if senate_isvp_url:
25c3a734 2663 return self.url_result(senate_isvp_url, 'SenateISVP')
2fe1b5bd 2664
756f574e
YCH
2665 # Look for Dailymotion Cloud videos
2666 dmcloud_url = DailymotionCloudIE._extract_dmcloud_url(webpage)
2667 if dmcloud_url:
2668 return self.url_result(dmcloud_url, 'DailymotionCloud')
2669
1ac1c4c2
S
2670 # Look for OnionStudios embeds
2671 onionstudios_url = OnionStudiosIE._extract_url(webpage)
2672 if onionstudios_url:
2673 return self.url_result(onionstudios_url)
2674
67167920 2675 # Look for ViewLift embeds
2676 viewlift_url = ViewLiftEmbedIE._extract_url(webpage)
2677 if viewlift_url:
2678 return self.url_result(viewlift_url)
eedd20ef 2679
7cb09524 2680 # Look for JWPlatform embeds
2681 jwplatform_url = JWPlatformIE._extract_url(webpage)
2682 if jwplatform_url:
2683 return self.url_result(jwplatform_url, 'JWPlatform')
2684
aecfcd4e
S
2685 # Look for Digiteka embeds
2686 digiteka_url = DigitekaIE._extract_url(webpage)
2687 if digiteka_url:
2688 return self.url_result(self._proto_relative_url(digiteka_url), DigitekaIE.ie_key())
6aeba407 2689
1979969f
S
2690 # Look for Arkena embeds
2691 arkena_url = ArkenaIE._extract_url(webpage)
2692 if arkena_url:
2693 return self.url_result(arkena_url, ArkenaIE.ie_key())
2694
b1c35797
RA
2695 # Look for Piksel embeds
2696 piksel_url = PikselIE._extract_url(webpage)
2697 if piksel_url:
2698 return self.url_result(piksel_url, PikselIE.ie_key())
2699
1bf996fa 2700 # Look for Limelight embeds
e5d39886
S
2701 limelight_urls = LimelightBaseIE._extract_urls(webpage, url)
2702 if limelight_urls:
2703 return self.playlist_result(
2704 limelight_urls, video_id, video_title, video_description)
2705
7986c3ab
S
2706 # Look for Anvato embeds
2707 anvato_urls = AnvatoIE._extract_urls(self, webpage, video_id)
2708 if anvato_urls:
2709 return self.playlist_result(
2710 anvato_urls, video_id, video_title, video_description)
2711
a5158f38
YCH
2712 # Look for AdobeTVVideo embeds
2713 mobj = re.search(
2714 r'<iframe[^>]+src=[\'"]((?:https?:)?//video\.tv\.adobe\.com/v/\d+[^"]+)[\'"]',
2715 webpage)
2716 if mobj is not None:
2717 return self.url_result(
2718 self._proto_relative_url(unescapeHTML(mobj.group(1))),
2719 'AdobeTVVideo')
2720
088e1aac
YCH
2721 # Look for Vine embeds
2722 mobj = re.search(
2723 r'<iframe[^>]+src=[\'"]((?:https?:)?//(?:www\.)?vine\.co/v/[^/]+/embed/(?:simple|postcard))',
2724 webpage)
2725 if mobj is not None:
2726 return self.url_result(
2727 self._proto_relative_url(unescapeHTML(mobj.group(1))), 'Vine')
2728
217d5ae0
RA
2729 # Look for VODPlatform embeds
2730 mobj = re.search(
93b84045 2731 r'<iframe[^>]+src=(["\'])(?P<url>(?:https?:)?//(?:www\.)?vod-platform\.net/[eE]mbed/.+?)\1',
217d5ae0
RA
2732 webpage)
2733 if mobj is not None:
2734 return self.url_result(
93b84045 2735 self._proto_relative_url(unescapeHTML(mobj.group('url'))), 'VODPlatform')
217d5ae0 2736
7d273a38
RA
2737 # Look for Mangomolo embeds
2738 mobj = re.search(
d05ef09d 2739 r'''(?x)<iframe[^>]+src=(["\'])(?P<url>(?:https?:)?//(?:www\.)?admin\.mangomolo\.com/analytics/index\.php/customers/embed/
7d273a38
RA
2740 (?:
2741 video\?.*?\bid=(?P<video_id>\d+)|
2742 index\?.*?\bchannelid=(?P<channel_id>(?:[A-Za-z0-9+/=]|%2B|%2F|%3D)+)
2743 ).+?)\1''', webpage)
2744 if mobj is not None:
2745 info = {
2746 '_type': 'url_transparent',
2747 'url': self._proto_relative_url(unescapeHTML(mobj.group('url'))),
2748 'title': video_title,
2749 'description': video_description,
2750 'thumbnail': video_thumbnail,
2751 'uploader': video_uploader,
2752 }
2753 video_id = mobj.group('video_id')
2754 if video_id:
2755 info.update({
2756 'ie_key': 'MangomoloVideo',
2757 'id': video_id,
2758 })
2759 else:
2760 info.update({
2761 'ie_key': 'MangomoloLive',
2762 'id': mobj.group('channel_id'),
2763 })
2764 return info
2765
5a51775a
YCH
2766 # Look for Instagram embeds
2767 instagram_embed_url = InstagramIE._extract_embed_url(webpage)
2768 if instagram_embed_url is not None:
11e60fca
S
2769 return self.url_result(
2770 self._proto_relative_url(instagram_embed_url), InstagramIE.ie_key())
5a51775a 2771
b8f67449 2772 # Look for LiveLeak embeds
09747ba7
YCH
2773 liveleak_urls = LiveLeakIE._extract_urls(webpage)
2774 if liveleak_urls:
2775 return self.playlist_from_matches(liveleak_urls, video_id, video_title)
b8f67449 2776
5d39176f
S
2777 # Look for 3Q SDN embeds
2778 threeqsdn_url = ThreeQSDNIE._extract_url(webpage)
2779 if threeqsdn_url:
6f41b2bc
S
2780 return {
2781 '_type': 'url_transparent',
2782 'ie_key': ThreeQSDNIE.ie_key(),
2783 'url': self._proto_relative_url(threeqsdn_url),
2784 'title': video_title,
2785 'description': video_description,
2786 'thumbnail': video_thumbnail,
2787 'uploader': video_uploader,
2788 }
5d39176f 2789
2a1321a2
S
2790 # Look for VBOX7 embeds
2791 vbox7_url = Vbox7IE._extract_url(webpage)
2792 if vbox7_url:
2793 return self.url_result(vbox7_url, Vbox7IE.ie_key())
2794
b0c8f2e9
DR
2795 # Look for DBTV embeds
2796 dbtv_urls = DBTVIE._extract_urls(webpage)
2797 if dbtv_urls:
46b18f23 2798 return self.playlist_from_matches(dbtv_urls, video_id, video_title, ie=DBTVIE.ie_key())
b0c8f2e9 2799
e186a9ec
S
2800 # Look for Videa embeds
2801 videa_urls = VideaIE._extract_urls(webpage)
2802 if videa_urls:
46b18f23 2803 return self.playlist_from_matches(videa_urls, video_id, video_title, ie=VideaIE.ie_key())
e186a9ec 2804
b687c85e
S
2805 # Look for 20 minuten embeds
2806 twentymin_urls = TwentyMinutenIE._extract_urls(webpage)
2807 if twentymin_urls:
46b18f23
JH
2808 return self.playlist_from_matches(
2809 twentymin_urls, video_id, video_title, ie=TwentyMinutenIE.ie_key())
b687c85e 2810
17f8deeb
S
2811 # Look for Openload embeds
2812 openload_urls = OpenloadIE._extract_urls(webpage)
2813 if openload_urls:
46b18f23
JH
2814 return self.playlist_from_matches(
2815 openload_urls, video_id, video_title, ie=OpenloadIE.ie_key())
17f8deeb 2816
6ef3e65a
S
2817 # Look for VideoPress embeds
2818 videopress_urls = VideoPressIE._extract_urls(webpage)
2819 if videopress_urls:
46b18f23
JH
2820 return self.playlist_from_matches(
2821 videopress_urls, video_id, video_title, ie=VideoPressIE.ie_key())
6ef3e65a 2822
eb3079b6
S
2823 # Look for Rutube embeds
2824 rutube_urls = RutubeIE._extract_urls(webpage)
2825 if rutube_urls:
46b18f23 2826 return self.playlist_from_matches(
2583c0b5 2827 rutube_urls, video_id, video_title, ie=RutubeIE.ie_key())
6ef3e65a 2828
55719459
JH
2829 # Look for WashingtonPost embeds
2830 wapo_urls = WashingtonPostIE._extract_urls(webpage)
2831 if wapo_urls:
2832 return self.playlist_from_matches(
2833 wapo_urls, video_id, video_title, ie=WashingtonPostIE.ie_key())
2834
5d29af3d
S
2835 # Look for Mediaset embeds
2836 mediaset_urls = MediasetIE._extract_urls(webpage)
2837 if mediaset_urls:
2838 return self.playlist_from_matches(
2839 mediaset_urls, video_id, video_title, ie=MediasetIE.ie_key())
2840
73cf76a9
S
2841 # Look for JOJ.sk embeds
2842 joj_urls = JojIE._extract_urls(webpage)
2843 if joj_urls:
2844 return self.playlist_from_matches(
2845 joj_urls, video_id, video_title, ie=JojIE.ie_key())
2846
24e966e8
PH
2847 # Look for megaphone.fm embeds
2848 mpfn_urls = MegaphoneIE._extract_urls(webpage)
2849 if mpfn_urls:
2850 return self.playlist_from_matches(
2851 mpfn_urls, video_id, video_title, ie=MegaphoneIE.ie_key())
2852
1663bd6e
S
2853 # Look for vzaar embeds
2854 vzaar_urls = VzaarIE._extract_urls(webpage)
2855 if vzaar_urls:
2856 return self.playlist_from_matches(
2857 vzaar_urls, video_id, video_title, ie=VzaarIE.ie_key())
2858
b311b0ea
S
2859 def merge_dicts(dict1, dict2):
2860 merged = {}
2861 for k, v in dict1.items():
2862 if v is not None:
2863 merged[k] = v
2864 for k, v in dict2.items():
2865 if v is None:
2866 continue
2867 if (k not in merged or
2868 (isinstance(v, compat_str) and v and
2869 isinstance(merged[k], compat_str) and
2870 not merged[k])):
2871 merged[k] = v
2872 return merged
2873
0de168f7
S
2874 # Looking for http://schema.org/VideoObject
2875 json_ld = self._search_json_ld(
082395d0
S
2876 webpage, video_id, default={}, expected_type='VideoObject')
2877 if json_ld.get('url'):
b311b0ea 2878 return merge_dicts(json_ld, info_dict)
0de168f7 2879
bd264412
YCH
2880 # Look for HTML5 media
2881 entries = self._parse_html5_media_entries(url, webpage, video_id, m3u8_id='hls')
2882 if entries:
2883 for entry in entries:
2884 entry.update({
2885 'id': video_id,
2886 'title': video_title,
2887 })
2888 self._sort_formats(entry['formats'])
2889 return self.playlist_result(entries)
2890
c73e330e
RU
2891 jwplayer_data = self._find_jwplayer_data(
2892 webpage, video_id, transform_source=js_to_json)
2893 if jwplayer_data:
4f06c1c9 2894 info = self._parse_jwplayer_data(
3e943cfe 2895 jwplayer_data, video_id, require_title=False, base_url=url)
b311b0ea 2896 return merge_dicts(info, info_dict)
a4a554a7 2897
ced659bb 2898 def check_video(vurl):
a0f71985
PH
2899 if YoutubeIE.suitable(vurl):
2900 return True
b7a8c1bc
S
2901 if RtmpIE.suitable(vurl):
2902 return True
ced659bb
S
2903 vpath = compat_urlparse.urlparse(vurl).path
2904 vext = determine_ext(vpath)
0ee79a37 2905 return '.' in vpath and vext not in ('swf', 'png', 'jpg', 'srt', 'sbv', 'sub', 'vtt', 'ttml', 'js', 'xml')
ced659bb
S
2906
2907 def filter_video(urls):
2908 return list(filter(check_video, urls))
2909
9b122384 2910 # Start with something easy: JW Player in SWFObject
ced659bb 2911 found = filter_video(re.findall(r'flashvars: [\'"](?:.*&)?file=(http[^\'"&]*)', webpage))
b30b8698 2912 if not found:
d981cef6 2913 # Look for gorilla-vid style embedding
ced659bb 2914 found = filter_video(re.findall(r'''(?sx)
c0292e8a
PH
2915 (?:
2916 jw_plugins|
2917 JWPlayerOptions|
2918 jwplayer\s*\(\s*["'][^'"]+["']\s*\)\s*\.setup
2919 )
a0f71985
PH
2920 .*?
2921 ['"]?file['"]?\s*:\s*["\'](.*?)["\']''', webpage))
b30b8698 2922 if not found:
9b122384 2923 # Broaden the search a little bit
ced659bb 2924 found = filter_video(re.findall(r'[^A-Za-z0-9]?(?:file|source)=(http[^\'"&]*)', webpage))
b30b8698
PH
2925 if not found:
2926 # Broaden the findall a little bit: JWPlayer JS loader
ced659bb 2927 found = filter_video(re.findall(
54a9328b 2928 r'[^A-Za-z0-9]?(?:file|video_url)["\']?:\s*["\'](http(?![^\'"]+\.[0-9]+[\'"])[^\'"]+)["\']', webpage))
4d805e06
PH
2929 if not found:
2930 # Flow player
ced659bb 2931 found = filter_video(re.findall(r'''(?xs)
4d805e06
PH
2932 flowplayer\("[^"]+",\s*
2933 \{[^}]+?\}\s*,
52585fd6 2934 \s*\{[^}]+? ["']?clip["']?\s*:\s*\{\s*
4d805e06 2935 ["']?url["']?\s*:\s*["']([^"']+)["']
ced659bb 2936 ''', webpage))
501f13fb
PH
2937 if not found:
2938 # Cinerama player
2939 found = re.findall(
2940 r"cinerama\.embedPlayer\(\s*\'[^']+\',\s*'([^']+)'", webpage)
b30b8698 2941 if not found:
9b122384 2942 # Try to find twitter cards info
371ddb14
S
2943 # twitter:player:stream should be checked before twitter:player since
2944 # it is expected to contain a raw stream (see
2945 # https://dev.twitter.com/cards/types/player#On_twitter.com_via_desktop_browser)
ced659bb
S
2946 found = filter_video(re.findall(
2947 r'<meta (?:property|name)="twitter:player:stream" (?:content|value)="(.+?)"', webpage))
b30b8698 2948 if not found:
9b122384
PH
2949 # We look for Open Graph info:
2950 # We have to match any number spaces between elements, some sites try to align them (eg.: statigr.am)
b30b8698 2951 m_video_type = re.findall(r'<meta.*?property="og:video:type".*?content="video/(.*?)"', webpage)
9b122384
PH
2952 # We only look in og:video if the MIME type is a video, don't try if it's a Flash player:
2953 if m_video_type is not None:
ced659bb 2954 found = filter_video(re.findall(r'<meta.*?property="og:video".*?content="(.*?)"', webpage))
b30b8698 2955 if not found:
ed9a25dd 2956 REDIRECT_REGEX = r'[0-9]{,2};\s*(?:URL|url)=\'?([^\'"]+)'
a5a45015 2957 found = re.search(
89ef304b 2958 r'(?i)<meta\s+(?=(?:[a-z-]+="[^"]+"\s+)*http-equiv="refresh")'
ed9a25dd 2959 r'(?:[a-z-]+="[^"]+"\s+)*?content="%s' % REDIRECT_REGEX,
89ef304b 2960 webpage)
84f81016
S
2961 if not found:
2962 # Look also in Refresh HTTP header
2963 refresh_header = head_response.headers.get('Refresh')
2964 if refresh_header:
6c91a5a7
S
2965 # In python 2 response HTTP headers are bytestrings
2966 if sys.version_info < (3, 0) and isinstance(refresh_header, str):
2967 refresh_header = refresh_header.decode('iso-8859-1')
ed9a25dd 2968 found = re.search(REDIRECT_REGEX, refresh_header)
b30b8698 2969 if found:
b37317d8 2970 new_url = compat_urlparse.urljoin(url, unescapeHTML(found.group(1)))
54b960f3
S
2971 if new_url != url:
2972 self.report_following_redirect(new_url)
2973 return {
2974 '_type': 'url',
2975 'url': new_url,
2976 }
2977 else:
2978 found = None
371ddb14
S
2979
2980 if not found:
2981 # twitter:player is a https URL to iframe player that may or may not
2982 # be supported by youtube-dl thus this is checked the very last (see
2983 # https://dev.twitter.com/cards/types/player#On_twitter.com_via_desktop_browser)
2984 embed_url = self._html_search_meta('twitter:player', webpage, default=None)
2985 if embed_url:
2986 return self.url_result(embed_url)
2987
b30b8698 2988 if not found:
416c7fcb 2989 raise UnsupportedError(url)
9b122384 2990
b30b8698 2991 entries = []
4a120778 2992 for video_url in orderedSet(found):
949b6497 2993 video_url = unescapeHTML(video_url)
6cc37c69 2994 video_url = video_url.replace('\\/', '/')
b30b8698 2995 video_url = compat_urlparse.urljoin(url, video_url)
f7e6f7fa 2996 video_id = compat_urllib_parse_unquote(os.path.basename(video_url))
9b122384 2997
b30b8698
PH
2998 # Sometimes, jwplayer extraction will result in a YouTube URL
2999 if YoutubeIE.suitable(video_url):
3000 entries.append(self.url_result(video_url, 'Youtube'))
3001 continue
9b122384 3002
b30b8698
PH
3003 # here's a fun little line of code for you:
3004 video_id = os.path.splitext(video_id)[0]
fc9713a1 3005
28602e74
YCH
3006 entry_info_dict = {
3007 'id': video_id,
3008 'uploader': video_uploader,
3009 'title': video_title,
3010 'age_limit': age_limit,
3011 }
3012
5620f840
S
3013 if RtmpIE.suitable(video_url):
3014 entry_info_dict.update({
3015 '_type': 'url_transparent',
3016 'ie_key': RtmpIE.ie_key(),
3017 'url': video_url,
3018 })
3019 entries.append(entry_info_dict)
3020 continue
3021
729accb4
S
3022 ext = determine_ext(video_url)
3023 if ext == 'smil':
28602e74 3024 entry_info_dict['formats'] = self._extract_smil_formats(video_url, video_id)
729accb4
S
3025 elif ext == 'xspf':
3026 return self.playlist_result(self._extract_xspf_playlist(video_url, video_id), video_id)
750b9ff0
YCH
3027 elif ext == 'm3u8':
3028 entry_info_dict['formats'] = self._extract_m3u8_formats(video_url, video_id, ext='mp4')
79a35085
S
3029 elif ext == 'mpd':
3030 entry_info_dict['formats'] = self._extract_mpd_formats(video_url, video_id)
3f2f4a94
S
3031 elif ext == 'f4m':
3032 entry_info_dict['formats'] = self._extract_f4m_formats(video_url, video_id)
4119a96c 3033 elif re.search(r'(?i)\.(?:ism|smil)/manifest', video_url) and video_url != url:
26aae566
S
3034 # Just matching .ism/manifest is not enough to be reliably sure
3035 # whether it's actually an ISM manifest or some other streaming
3036 # manifest since there are various streaming URL formats
3037 # possible (see [1]) as well as some other shenanigans like
3038 # .smil/manifest URLs that actually serve an ISM (see [2]) and
3039 # so on.
3040 # Thus the most reasonable way to solve this is to delegate
3041 # to generic extractor in order to look into the contents of
3042 # the manifest itself.
3043 # 1. https://azure.microsoft.com/en-us/documentation/articles/media-services-deliver-content-overview/#streaming-url-formats
3044 # 2. https://svs.itworkscdn.net/lbcivod/smil:itwfcdn/lbci/170976.smil/Manifest
3045 entry_info_dict = self.url_result(
3046 smuggle_url(video_url, {'to_generic': True}),
3047 GenericIE.ie_key())
d6fd958c 3048 else:
28602e74
YCH
3049 entry_info_dict['url'] = video_url
3050
19dbaeec
S
3051 if entry_info_dict.get('formats'):
3052 self._sort_formats(entry_info_dict['formats'])
3053
28602e74 3054 entries.append(entry_info_dict)
b30b8698
PH
3055
3056 if len(entries) == 1:
669f0e7c 3057 return entries[0]
b30b8698
PH
3058 else:
3059 for num, e in enumerate(entries, start=1):
13d8fbef
JMF
3060 # 'url' results don't have a title
3061 if e.get('title') is not None:
3062 e['title'] = '%s (%d)' % (e['title'], num)
b30b8698
PH
3063 return {
3064 '_type': 'playlist',
3065 'entries': entries,
3066 }