4 from __future__ import unicode_literals
6 # Allow direct execution
10 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
14 from test.helper import FakeYDL, assertRegexpMatches
15 from youtube_dl import YoutubeDL
16 from youtube_dl.compat import compat_str, compat_urllib_error
17 from youtube_dl.extractor import YoutubeIE
18 from youtube_dl.extractor.common import InfoExtractor
19 from youtube_dl.postprocessor.common import PostProcessor
20 from youtube_dl.utils import ExtractorError, match_filter_func
22 TEST_URL = 'http://localhost/sample.mp4'
26 def __init__(self, *args, **kwargs):
27 super(YDL, self).__init__(*args, **kwargs)
28 self.downloaded_info_dicts = []
31 def process_info(self, info_dict):
32 self.downloaded_info_dicts.append(info_dict)
34 def to_screen(self, msg):
38 def _make_result(formats, **kwargs):
42 'title': 'testttitle',
43 'extractor': 'testex',
44 'extractor_key': 'TestEx',
50 class TestFormatSelection(unittest.TestCase):
51 def test_prefer_free_formats(self):
52 # Same resolution => download webm
54 ydl.params['prefer_free_formats'] = True
56 {'ext': 'webm', 'height': 460, 'url': TEST_URL},
57 {'ext': 'mp4', 'height': 460, 'url': TEST_URL},
59 info_dict = _make_result(formats)
61 yie._sort_formats(info_dict['formats'])
62 ydl.process_ie_result(info_dict)
63 downloaded = ydl.downloaded_info_dicts[0]
64 self.assertEqual(downloaded['ext'], 'webm')
66 # Different resolution => download best quality (mp4)
68 ydl.params['prefer_free_formats'] = True
70 {'ext': 'webm', 'height': 720, 'url': TEST_URL},
71 {'ext': 'mp4', 'height': 1080, 'url': TEST_URL},
73 info_dict['formats'] = formats
75 yie._sort_formats(info_dict['formats'])
76 ydl.process_ie_result(info_dict)
77 downloaded = ydl.downloaded_info_dicts[0]
78 self.assertEqual(downloaded['ext'], 'mp4')
80 # No prefer_free_formats => prefer mp4 and flv for greater compatibility
82 ydl.params['prefer_free_formats'] = False
84 {'ext': 'webm', 'height': 720, 'url': TEST_URL},
85 {'ext': 'mp4', 'height': 720, 'url': TEST_URL},
86 {'ext': 'flv', 'height': 720, 'url': TEST_URL},
88 info_dict['formats'] = formats
90 yie._sort_formats(info_dict['formats'])
91 ydl.process_ie_result(info_dict)
92 downloaded = ydl.downloaded_info_dicts[0]
93 self.assertEqual(downloaded['ext'], 'mp4')
96 ydl.params['prefer_free_formats'] = False
98 {'ext': 'flv', 'height': 720, 'url': TEST_URL},
99 {'ext': 'webm', 'height': 720, 'url': TEST_URL},
101 info_dict['formats'] = formats
103 yie._sort_formats(info_dict['formats'])
104 ydl.process_ie_result(info_dict)
105 downloaded = ydl.downloaded_info_dicts[0]
106 self.assertEqual(downloaded['ext'], 'flv')
108 def test_format_selection(self):
110 {'format_id': '35', 'ext': 'mp4', 'preference': 1, 'url': TEST_URL},
111 {'format_id': 'example-with-dashes', 'ext': 'webm', 'preference': 1, 'url': TEST_URL},
112 {'format_id': '45', 'ext': 'webm', 'preference': 2, 'url': TEST_URL},
113 {'format_id': '47', 'ext': 'webm', 'preference': 3, 'url': TEST_URL},
114 {'format_id': '2', 'ext': 'flv', 'preference': 4, 'url': TEST_URL},
116 info_dict = _make_result(formats)
118 ydl = YDL({'format': '20/47'})
119 ydl.process_ie_result(info_dict.copy())
120 downloaded = ydl.downloaded_info_dicts[0]
121 self.assertEqual(downloaded['format_id'], '47')
123 ydl = YDL({'format': '20/71/worst'})
124 ydl.process_ie_result(info_dict.copy())
125 downloaded = ydl.downloaded_info_dicts[0]
126 self.assertEqual(downloaded['format_id'], '35')
129 ydl.process_ie_result(info_dict.copy())
130 downloaded = ydl.downloaded_info_dicts[0]
131 self.assertEqual(downloaded['format_id'], '2')
133 ydl = YDL({'format': 'webm/mp4'})
134 ydl.process_ie_result(info_dict.copy())
135 downloaded = ydl.downloaded_info_dicts[0]
136 self.assertEqual(downloaded['format_id'], '47')
138 ydl = YDL({'format': '3gp/40/mp4'})
139 ydl.process_ie_result(info_dict.copy())
140 downloaded = ydl.downloaded_info_dicts[0]
141 self.assertEqual(downloaded['format_id'], '35')
143 ydl = YDL({'format': 'example-with-dashes'})
144 ydl.process_ie_result(info_dict.copy())
145 downloaded = ydl.downloaded_info_dicts[0]
146 self.assertEqual(downloaded['format_id'], 'example-with-dashes')
148 def test_format_selection_audio(self):
150 {'format_id': 'audio-low', 'ext': 'webm', 'preference': 1, 'vcodec': 'none', 'url': TEST_URL},
151 {'format_id': 'audio-mid', 'ext': 'webm', 'preference': 2, 'vcodec': 'none', 'url': TEST_URL},
152 {'format_id': 'audio-high', 'ext': 'flv', 'preference': 3, 'vcodec': 'none', 'url': TEST_URL},
153 {'format_id': 'vid', 'ext': 'mp4', 'preference': 4, 'url': TEST_URL},
155 info_dict = _make_result(formats)
157 ydl = YDL({'format': 'bestaudio'})
158 ydl.process_ie_result(info_dict.copy())
159 downloaded = ydl.downloaded_info_dicts[0]
160 self.assertEqual(downloaded['format_id'], 'audio-high')
162 ydl = YDL({'format': 'worstaudio'})
163 ydl.process_ie_result(info_dict.copy())
164 downloaded = ydl.downloaded_info_dicts[0]
165 self.assertEqual(downloaded['format_id'], 'audio-low')
168 {'format_id': 'vid-low', 'ext': 'mp4', 'preference': 1, 'url': TEST_URL},
169 {'format_id': 'vid-high', 'ext': 'mp4', 'preference': 2, 'url': TEST_URL},
171 info_dict = _make_result(formats)
173 ydl = YDL({'format': 'bestaudio/worstaudio/best'})
174 ydl.process_ie_result(info_dict.copy())
175 downloaded = ydl.downloaded_info_dicts[0]
176 self.assertEqual(downloaded['format_id'], 'vid-high')
178 def test_format_selection_audio_exts(self):
180 {'format_id': 'mp3-64', 'ext': 'mp3', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'},
181 {'format_id': 'ogg-64', 'ext': 'ogg', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'},
182 {'format_id': 'aac-64', 'ext': 'aac', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'},
183 {'format_id': 'mp3-32', 'ext': 'mp3', 'abr': 32, 'url': 'http://_', 'vcodec': 'none'},
184 {'format_id': 'aac-32', 'ext': 'aac', 'abr': 32, 'url': 'http://_', 'vcodec': 'none'},
187 info_dict = _make_result(formats)
188 ydl = YDL({'format': 'best'})
190 ie._sort_formats(info_dict['formats'])
191 ydl.process_ie_result(copy.deepcopy(info_dict))
192 downloaded = ydl.downloaded_info_dicts[0]
193 self.assertEqual(downloaded['format_id'], 'aac-64')
195 ydl = YDL({'format': 'mp3'})
197 ie._sort_formats(info_dict['formats'])
198 ydl.process_ie_result(copy.deepcopy(info_dict))
199 downloaded = ydl.downloaded_info_dicts[0]
200 self.assertEqual(downloaded['format_id'], 'mp3-64')
202 ydl = YDL({'prefer_free_formats': True})
204 ie._sort_formats(info_dict['formats'])
205 ydl.process_ie_result(copy.deepcopy(info_dict))
206 downloaded = ydl.downloaded_info_dicts[0]
207 self.assertEqual(downloaded['format_id'], 'ogg-64')
209 def test_format_selection_video(self):
211 {'format_id': 'dash-video-low', 'ext': 'mp4', 'preference': 1, 'acodec': 'none', 'url': TEST_URL},
212 {'format_id': 'dash-video-high', 'ext': 'mp4', 'preference': 2, 'acodec': 'none', 'url': TEST_URL},
213 {'format_id': 'vid', 'ext': 'mp4', 'preference': 3, 'url': TEST_URL},
215 info_dict = _make_result(formats)
217 ydl = YDL({'format': 'bestvideo'})
218 ydl.process_ie_result(info_dict.copy())
219 downloaded = ydl.downloaded_info_dicts[0]
220 self.assertEqual(downloaded['format_id'], 'dash-video-high')
222 ydl = YDL({'format': 'worstvideo'})
223 ydl.process_ie_result(info_dict.copy())
224 downloaded = ydl.downloaded_info_dicts[0]
225 self.assertEqual(downloaded['format_id'], 'dash-video-low')
227 ydl = YDL({'format': 'bestvideo[format_id^=dash][format_id$=low]'})
228 ydl.process_ie_result(info_dict.copy())
229 downloaded = ydl.downloaded_info_dicts[0]
230 self.assertEqual(downloaded['format_id'], 'dash-video-low')
233 {'format_id': 'vid-vcodec-dot', 'ext': 'mp4', 'preference': 1, 'vcodec': 'avc1.123456', 'acodec': 'none', 'url': TEST_URL},
235 info_dict = _make_result(formats)
237 ydl = YDL({'format': 'bestvideo[vcodec=avc1.123456]'})
238 ydl.process_ie_result(info_dict.copy())
239 downloaded = ydl.downloaded_info_dicts[0]
240 self.assertEqual(downloaded['format_id'], 'vid-vcodec-dot')
242 def test_youtube_format_selection(self):
244 '38', '37', '46', '22', '45', '35', '44', '18', '34', '43', '6', '5', '17', '36', '13',
245 # Apple HTTP Live Streaming
246 '96', '95', '94', '93', '92', '132', '151',
248 '85', '84', '102', '83', '101', '82', '100',
250 '137', '248', '136', '247', '135', '246',
251 '245', '244', '134', '243', '133', '242', '160',
253 '141', '172', '140', '171', '139',
256 def format_info(f_id):
257 info = YoutubeIE._formats[f_id].copy()
259 # XXX: In real cases InfoExtractor._parse_mpd_formats() fills up 'acodec'
260 # and 'vcodec', while in tests such information is incomplete since
261 # commit a6c2c24479e5f4827ceb06f64d855329c0a6f593
262 # test_YoutubeDL.test_youtube_format_selection is broken without
264 if 'acodec' in info and 'vcodec' not in info:
265 info['vcodec'] = 'none'
266 elif 'vcodec' in info and 'acodec' not in info:
267 info['acodec'] = 'none'
269 info['format_id'] = f_id
270 info['url'] = 'url:' + f_id
272 formats_order = [format_info(f_id) for f_id in order]
274 info_dict = _make_result(list(formats_order), extractor='youtube')
275 ydl = YDL({'format': 'bestvideo+bestaudio'})
277 yie._sort_formats(info_dict['formats'])
278 ydl.process_ie_result(info_dict)
279 downloaded = ydl.downloaded_info_dicts[0]
280 self.assertEqual(downloaded['format_id'], '137+141')
281 self.assertEqual(downloaded['ext'], 'mp4')
283 info_dict = _make_result(list(formats_order), extractor='youtube')
284 ydl = YDL({'format': 'bestvideo[height>=999999]+bestaudio/best'})
286 yie._sort_formats(info_dict['formats'])
287 ydl.process_ie_result(info_dict)
288 downloaded = ydl.downloaded_info_dicts[0]
289 self.assertEqual(downloaded['format_id'], '38')
291 info_dict = _make_result(list(formats_order), extractor='youtube')
292 ydl = YDL({'format': 'bestvideo/best,bestaudio'})
294 yie._sort_formats(info_dict['formats'])
295 ydl.process_ie_result(info_dict)
296 downloaded_ids = [info['format_id'] for info in ydl.downloaded_info_dicts]
297 self.assertEqual(downloaded_ids, ['137', '141'])
299 info_dict = _make_result(list(formats_order), extractor='youtube')
300 ydl = YDL({'format': '(bestvideo[ext=mp4],bestvideo[ext=webm])+bestaudio'})
302 yie._sort_formats(info_dict['formats'])
303 ydl.process_ie_result(info_dict)
304 downloaded_ids = [info['format_id'] for info in ydl.downloaded_info_dicts]
305 self.assertEqual(downloaded_ids, ['137+141', '248+141'])
307 info_dict = _make_result(list(formats_order), extractor='youtube')
308 ydl = YDL({'format': '(bestvideo[ext=mp4],bestvideo[ext=webm])[height<=720]+bestaudio'})
310 yie._sort_formats(info_dict['formats'])
311 ydl.process_ie_result(info_dict)
312 downloaded_ids = [info['format_id'] for info in ydl.downloaded_info_dicts]
313 self.assertEqual(downloaded_ids, ['136+141', '247+141'])
315 info_dict = _make_result(list(formats_order), extractor='youtube')
316 ydl = YDL({'format': '(bestvideo[ext=none]/bestvideo[ext=webm])+bestaudio'})
318 yie._sort_formats(info_dict['formats'])
319 ydl.process_ie_result(info_dict)
320 downloaded_ids = [info['format_id'] for info in ydl.downloaded_info_dicts]
321 self.assertEqual(downloaded_ids, ['248+141'])
323 for f1, f2 in zip(formats_order, formats_order[1:]):
324 info_dict = _make_result([f1, f2], extractor='youtube')
325 ydl = YDL({'format': 'best/bestvideo'})
327 yie._sort_formats(info_dict['formats'])
328 ydl.process_ie_result(info_dict)
329 downloaded = ydl.downloaded_info_dicts[0]
330 self.assertEqual(downloaded['format_id'], f1['format_id'])
332 info_dict = _make_result([f2, f1], extractor='youtube')
333 ydl = YDL({'format': 'best/bestvideo'})
335 yie._sort_formats(info_dict['formats'])
336 ydl.process_ie_result(info_dict)
337 downloaded = ydl.downloaded_info_dicts[0]
338 self.assertEqual(downloaded['format_id'], f1['format_id'])
340 def test_audio_only_extractor_format_selection(self):
341 # For extractors with incomplete formats (all formats are audio-only or
342 # video-only) best and worst should fallback to corresponding best/worst
343 # video-only or audio-only formats (as per
344 # https://github.com/rg3/youtube-dl/pull/5556)
346 {'format_id': 'low', 'ext': 'mp3', 'preference': 1, 'vcodec': 'none', 'url': TEST_URL},
347 {'format_id': 'high', 'ext': 'mp3', 'preference': 2, 'vcodec': 'none', 'url': TEST_URL},
349 info_dict = _make_result(formats)
351 ydl = YDL({'format': 'best'})
352 ydl.process_ie_result(info_dict.copy())
353 downloaded = ydl.downloaded_info_dicts[0]
354 self.assertEqual(downloaded['format_id'], 'high')
356 ydl = YDL({'format': 'worst'})
357 ydl.process_ie_result(info_dict.copy())
358 downloaded = ydl.downloaded_info_dicts[0]
359 self.assertEqual(downloaded['format_id'], 'low')
361 def test_format_not_available(self):
363 {'format_id': 'regular', 'ext': 'mp4', 'height': 360, 'url': TEST_URL},
364 {'format_id': 'video', 'ext': 'mp4', 'height': 720, 'acodec': 'none', 'url': TEST_URL},
366 info_dict = _make_result(formats)
368 # This must fail since complete video-audio format does not match filter
369 # and extractor does not provide incomplete only formats (i.e. only
370 # video-only or audio-only).
371 ydl = YDL({'format': 'best[height>360]'})
372 self.assertRaises(ExtractorError, ydl.process_ie_result, info_dict.copy())
374 def test_invalid_format_specs(self):
375 def assert_syntax_error(format_spec):
376 ydl = YDL({'format': format_spec})
377 info_dict = _make_result([{'format_id': 'foo', 'url': TEST_URL}])
378 self.assertRaises(SyntaxError, ydl.process_ie_result, info_dict)
380 assert_syntax_error('bestvideo,,best')
381 assert_syntax_error('+bestaudio')
382 assert_syntax_error('bestvideo+')
383 assert_syntax_error('/')
385 def test_format_filtering(self):
387 {'format_id': 'A', 'filesize': 500, 'width': 1000},
388 {'format_id': 'B', 'filesize': 1000, 'width': 500},
389 {'format_id': 'C', 'filesize': 1000, 'width': 400},
390 {'format_id': 'D', 'filesize': 2000, 'width': 600},
391 {'format_id': 'E', 'filesize': 3000},
393 {'format_id': 'G', 'filesize': 1000000},
396 f['url'] = 'http://_/'
398 info_dict = _make_result(formats)
400 ydl = YDL({'format': 'best[filesize<3000]'})
401 ydl.process_ie_result(info_dict)
402 downloaded = ydl.downloaded_info_dicts[0]
403 self.assertEqual(downloaded['format_id'], 'D')
405 ydl = YDL({'format': 'best[filesize<=3000]'})
406 ydl.process_ie_result(info_dict)
407 downloaded = ydl.downloaded_info_dicts[0]
408 self.assertEqual(downloaded['format_id'], 'E')
410 ydl = YDL({'format': 'best[filesize <= ? 3000]'})
411 ydl.process_ie_result(info_dict)
412 downloaded = ydl.downloaded_info_dicts[0]
413 self.assertEqual(downloaded['format_id'], 'F')
415 ydl = YDL({'format': 'best [filesize = 1000] [width>450]'})
416 ydl.process_ie_result(info_dict)
417 downloaded = ydl.downloaded_info_dicts[0]
418 self.assertEqual(downloaded['format_id'], 'B')
420 ydl = YDL({'format': 'best [filesize = 1000] [width!=450]'})
421 ydl.process_ie_result(info_dict)
422 downloaded = ydl.downloaded_info_dicts[0]
423 self.assertEqual(downloaded['format_id'], 'C')
425 ydl = YDL({'format': '[filesize>?1]'})
426 ydl.process_ie_result(info_dict)
427 downloaded = ydl.downloaded_info_dicts[0]
428 self.assertEqual(downloaded['format_id'], 'G')
430 ydl = YDL({'format': '[filesize<1M]'})
431 ydl.process_ie_result(info_dict)
432 downloaded = ydl.downloaded_info_dicts[0]
433 self.assertEqual(downloaded['format_id'], 'E')
435 ydl = YDL({'format': '[filesize<1MiB]'})
436 ydl.process_ie_result(info_dict)
437 downloaded = ydl.downloaded_info_dicts[0]
438 self.assertEqual(downloaded['format_id'], 'G')
440 ydl = YDL({'format': 'all[width>=400][width<=600]'})
441 ydl.process_ie_result(info_dict)
442 downloaded_ids = [info['format_id'] for info in ydl.downloaded_info_dicts]
443 self.assertEqual(downloaded_ids, ['B', 'C', 'D'])
445 ydl = YDL({'format': 'best[height<40]'})
447 ydl.process_ie_result(info_dict)
448 except ExtractorError:
450 self.assertEqual(ydl.downloaded_info_dicts, [])
453 class TestYoutubeDL(unittest.TestCase):
454 def test_subtitles(self):
455 def s_formats(lang, autocaption=False):
458 'url': 'http://localhost/video.%s.%s' % (lang, ext),
459 '_auto': autocaption,
460 } for ext in ['vtt', 'srt', 'ass']]
461 subtitles = dict((l, s_formats(l)) for l in ['en', 'fr', 'es'])
462 auto_captions = dict((l, s_formats(l, True)) for l in ['it', 'pt', 'es'])
466 'url': 'http://localhost/video.mp4',
467 'subtitles': subtitles,
468 'automatic_captions': auto_captions,
472 def get_info(params={}):
473 params.setdefault('simulate', True)
475 ydl.report_warning = lambda *args, **kargs: None
476 return ydl.process_video_result(info_dict, download=False)
479 self.assertFalse(result.get('requested_subtitles'))
480 self.assertEqual(result['subtitles'], subtitles)
481 self.assertEqual(result['automatic_captions'], auto_captions)
483 result = get_info({'writesubtitles': True})
484 subs = result['requested_subtitles']
485 self.assertTrue(subs)
486 self.assertEqual(set(subs.keys()), set(['en']))
487 self.assertTrue(subs['en'].get('data') is None)
488 self.assertEqual(subs['en']['ext'], 'ass')
490 result = get_info({'writesubtitles': True, 'subtitlesformat': 'foo/srt'})
491 subs = result['requested_subtitles']
492 self.assertEqual(subs['en']['ext'], 'srt')
494 result = get_info({'writesubtitles': True, 'subtitleslangs': ['es', 'fr', 'it']})
495 subs = result['requested_subtitles']
496 self.assertTrue(subs)
497 self.assertEqual(set(subs.keys()), set(['es', 'fr']))
499 result = get_info({'writesubtitles': True, 'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']})
500 subs = result['requested_subtitles']
501 self.assertTrue(subs)
502 self.assertEqual(set(subs.keys()), set(['es', 'pt']))
503 self.assertFalse(subs['es']['_auto'])
504 self.assertTrue(subs['pt']['_auto'])
506 result = get_info({'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']})
507 subs = result['requested_subtitles']
508 self.assertTrue(subs)
509 self.assertEqual(set(subs.keys()), set(['es', 'pt']))
510 self.assertTrue(subs['es']['_auto'])
511 self.assertTrue(subs['pt']['_auto'])
513 def test_add_extra_info(self):
519 'playlist': 'funny videos',
521 YDL.add_extra_info(test_dict, extra_info)
522 self.assertEqual(test_dict['extractor'], 'Foo')
523 self.assertEqual(test_dict['playlist'], 'funny videos')
525 def test_prepare_filename(self):
536 ydl = YoutubeDL({'outtmpl': templ})
537 return ydl.prepare_filename(info)
538 self.assertEqual(fname('%(id)s.%(ext)s'), '1234.mp4')
539 self.assertEqual(fname('%(id)s-%(width)s.%(ext)s'), '1234-NA.mp4')
540 # Replace missing fields with 'NA'
541 self.assertEqual(fname('%(uploader_date)s-%(id)s.%(ext)s'), 'NA-1234.mp4')
542 self.assertEqual(fname('%(height)d.%(ext)s'), '1080.mp4')
543 self.assertEqual(fname('%(height)6d.%(ext)s'), ' 1080.mp4')
544 self.assertEqual(fname('%(height)-6d.%(ext)s'), '1080 .mp4')
545 self.assertEqual(fname('%(height)06d.%(ext)s'), '001080.mp4')
546 self.assertEqual(fname('%(height) 06d.%(ext)s'), ' 01080.mp4')
547 self.assertEqual(fname('%(height) 06d.%(ext)s'), ' 01080.mp4')
548 self.assertEqual(fname('%(height)0 6d.%(ext)s'), ' 01080.mp4')
549 self.assertEqual(fname('%(height)0 6d.%(ext)s'), ' 01080.mp4')
550 self.assertEqual(fname('%(height) 0 6d.%(ext)s'), ' 01080.mp4')
551 self.assertEqual(fname('%%'), '%')
552 self.assertEqual(fname('%%%%'), '%%')
553 self.assertEqual(fname('%%(height)06d.%(ext)s'), '%(height)06d.mp4')
554 self.assertEqual(fname('%(width)06d.%(ext)s'), 'NA.mp4')
555 self.assertEqual(fname('%(width)06d.%%(ext)s'), 'NA.%(ext)s')
556 self.assertEqual(fname('%%(width)06d.%(ext)s'), '%(width)06d.mp4')
557 self.assertEqual(fname('Hello %(title1)s'), 'Hello $PATH')
558 self.assertEqual(fname('Hello %(title2)s'), 'Hello %PATH%')
560 def test_format_note(self):
562 self.assertEqual(ydl._format_note({}), '')
563 assertRegexpMatches(self, ydl._format_note({
566 assertRegexpMatches(self, ydl._format_note({
570 def test_postprocessors(self):
571 filename = 'post-processor-testfile.mp4'
572 audiofile = filename + '.mp3'
574 class SimplePP(PostProcessor):
576 with open(audiofile, 'wt') as f:
578 return [info['filepath']], info
580 def run_pp(params, PP):
581 with open(filename, 'wt') as f:
583 ydl = YoutubeDL(params)
584 ydl.add_post_processor(PP())
585 ydl.post_process(filename, {'filepath': filename})
587 run_pp({'keepvideo': True}, SimplePP)
588 self.assertTrue(os.path.exists(filename), '%s doesn\'t exist' % filename)
589 self.assertTrue(os.path.exists(audiofile), '%s doesn\'t exist' % audiofile)
593 run_pp({'keepvideo': False}, SimplePP)
594 self.assertFalse(os.path.exists(filename), '%s exists' % filename)
595 self.assertTrue(os.path.exists(audiofile), '%s doesn\'t exist' % audiofile)
598 class ModifierPP(PostProcessor):
600 with open(info['filepath'], 'wt') as f:
604 run_pp({'keepvideo': False}, ModifierPP)
605 self.assertTrue(os.path.exists(filename), '%s doesn\'t exist' % filename)
608 def test_match_filter(self):
609 class FilterYDL(YDL):
610 def __init__(self, *args, **kwargs):
611 super(FilterYDL, self).__init__(*args, **kwargs)
612 self.params['simulate'] = True
614 def process_info(self, info_dict):
615 super(YDL, self).process_info(info_dict)
617 def _match_entry(self, info_dict, incomplete):
618 res = super(FilterYDL, self)._match_entry(info_dict, incomplete)
620 self.downloaded_info_dicts.append(info_dict)
629 'filesize': 10 * 1024,
631 'uploader': "變態妍字幕版 太妍 тест",
632 'creator': "тест ' 123 ' тест--",
640 'description': 'foo',
641 'filesize': 5 * 1024,
643 'uploader': "тест 123",
645 videos = [first, second]
647 def get_videos(filter_=None):
648 ydl = FilterYDL({'match_filter': filter_})
650 ydl.process_ie_result(v, download=True)
651 return [v['id'] for v in ydl.downloaded_info_dicts]
654 self.assertEqual(res, ['1', '2'])
660 return 'Video id is not 1'
662 self.assertEqual(res, ['1'])
664 f = match_filter_func('duration < 30')
666 self.assertEqual(res, ['2'])
668 f = match_filter_func('description = foo')
670 self.assertEqual(res, ['2'])
672 f = match_filter_func('description =? foo')
674 self.assertEqual(res, ['1', '2'])
676 f = match_filter_func('filesize > 5KiB')
678 self.assertEqual(res, ['1'])
680 f = match_filter_func('playlist_id = 42')
682 self.assertEqual(res, ['1'])
684 f = match_filter_func('uploader = "變態妍字幕版 太妍 тест"')
686 self.assertEqual(res, ['1'])
688 f = match_filter_func('uploader != "變態妍字幕版 太妍 тест"')
690 self.assertEqual(res, ['2'])
692 f = match_filter_func('creator = "тест \' 123 \' тест--"')
694 self.assertEqual(res, ['1'])
696 f = match_filter_func("creator = 'тест \\' 123 \\' тест--'")
698 self.assertEqual(res, ['1'])
700 f = match_filter_func(r"creator = 'тест \' 123 \' тест--' & duration > 30")
702 self.assertEqual(res, [])
704 def test_playlist_items_selection(self):
707 'title': compat_str(i),
709 } for i in range(1, 5)]
714 'extractor': 'test:playlist',
715 'extractor_key': 'test:playlist',
716 'webpage_url': 'http://example.com',
721 # make a copy because the dictionary can be modified
722 ydl.process_ie_result(playlist.copy())
723 return [int(v['id']) for v in ydl.downloaded_info_dicts]
726 self.assertEqual(result, [1, 2, 3, 4])
728 result = get_ids({'playlistend': 10})
729 self.assertEqual(result, [1, 2, 3, 4])
731 result = get_ids({'playlistend': 2})
732 self.assertEqual(result, [1, 2])
734 result = get_ids({'playliststart': 10})
735 self.assertEqual(result, [])
737 result = get_ids({'playliststart': 2})
738 self.assertEqual(result, [2, 3, 4])
740 result = get_ids({'playlist_items': '2-4'})
741 self.assertEqual(result, [2, 3, 4])
743 result = get_ids({'playlist_items': '2,4'})
744 self.assertEqual(result, [2, 4])
746 result = get_ids({'playlist_items': '10'})
747 self.assertEqual(result, [])
749 def test_urlopen_no_file_protocol(self):
750 # see https://github.com/rg3/youtube-dl/issues/8227
752 self.assertRaises(compat_urllib_error.URLError, ydl.urlopen, 'file:///etc/passwd')
754 def test_do_not_override_ie_key_in_url_transparent(self):
757 class Foo1IE(InfoExtractor):
758 _VALID_URL = r'foo1:'
760 def _real_extract(self, url):
762 '_type': 'url_transparent',
765 'title': 'foo1 title',
769 class Foo2IE(InfoExtractor):
770 _VALID_URL = r'foo2:'
772 def _real_extract(self, url):
779 class Foo3IE(InfoExtractor):
780 _VALID_URL = r'foo3:'
782 def _real_extract(self, url):
783 return _make_result([{'url': TEST_URL}], title='foo3 title')
785 ydl.add_info_extractor(Foo1IE(ydl))
786 ydl.add_info_extractor(Foo2IE(ydl))
787 ydl.add_info_extractor(Foo3IE(ydl))
788 ydl.extract_info('foo1:')
789 downloaded = ydl.downloaded_info_dicts[0]
790 self.assertEqual(downloaded['url'], TEST_URL)
791 self.assertEqual(downloaded['title'], 'foo1 title')
792 self.assertEqual(downloaded['id'], 'testid')
793 self.assertEqual(downloaded['extractor'], 'testex')
794 self.assertEqual(downloaded['extractor_key'], 'TestEx')
797 if __name__ == '__main__':