]>
Raphaël G. Git Repositories - youtubedl/blob - test/test_YoutubeDL.py
8491a88bd2f4730cd1af4e39d936966d6e1d3bb1
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',
49 class TestFormatSelection(unittest
.TestCase
):
50 def test_prefer_free_formats(self
):
51 # Same resolution => download webm
53 ydl
.params
['prefer_free_formats'] = True
55 {'ext': 'webm', 'height': 460, 'url': TEST_URL
},
56 {'ext': 'mp4', 'height': 460, 'url': TEST_URL
},
58 info_dict
= _make_result(formats
)
60 yie
._sort
_formats
(info_dict
['formats'])
61 ydl
.process_ie_result(info_dict
)
62 downloaded
= ydl
.downloaded_info_dicts
[0]
63 self
.assertEqual(downloaded
['ext'], 'webm')
65 # Different resolution => download best quality (mp4)
67 ydl
.params
['prefer_free_formats'] = True
69 {'ext': 'webm', 'height': 720, 'url': TEST_URL
},
70 {'ext': 'mp4', 'height': 1080, 'url': TEST_URL
},
72 info_dict
['formats'] = formats
74 yie
._sort
_formats
(info_dict
['formats'])
75 ydl
.process_ie_result(info_dict
)
76 downloaded
= ydl
.downloaded_info_dicts
[0]
77 self
.assertEqual(downloaded
['ext'], 'mp4')
79 # No prefer_free_formats => prefer mp4 and flv for greater compatibility
81 ydl
.params
['prefer_free_formats'] = False
83 {'ext': 'webm', 'height': 720, 'url': TEST_URL
},
84 {'ext': 'mp4', 'height': 720, 'url': TEST_URL
},
85 {'ext': 'flv', 'height': 720, 'url': TEST_URL
},
87 info_dict
['formats'] = formats
89 yie
._sort
_formats
(info_dict
['formats'])
90 ydl
.process_ie_result(info_dict
)
91 downloaded
= ydl
.downloaded_info_dicts
[0]
92 self
.assertEqual(downloaded
['ext'], 'mp4')
95 ydl
.params
['prefer_free_formats'] = False
97 {'ext': 'flv', 'height': 720, 'url': TEST_URL
},
98 {'ext': 'webm', 'height': 720, 'url': TEST_URL
},
100 info_dict
['formats'] = formats
102 yie
._sort
_formats
(info_dict
['formats'])
103 ydl
.process_ie_result(info_dict
)
104 downloaded
= ydl
.downloaded_info_dicts
[0]
105 self
.assertEqual(downloaded
['ext'], 'flv')
107 def test_format_selection(self
):
109 {'format_id': '35', 'ext': 'mp4', 'preference': 1, 'url': TEST_URL
},
110 {'format_id': 'example-with-dashes', 'ext': 'webm', 'preference': 1, 'url': TEST_URL
},
111 {'format_id': '45', 'ext': 'webm', 'preference': 2, 'url': TEST_URL
},
112 {'format_id': '47', 'ext': 'webm', 'preference': 3, 'url': TEST_URL
},
113 {'format_id': '2', 'ext': 'flv', 'preference': 4, 'url': TEST_URL
},
115 info_dict
= _make_result(formats
)
117 ydl
= YDL({'format': '20/47'})
118 ydl
.process_ie_result(info_dict
.copy())
119 downloaded
= ydl
.downloaded_info_dicts
[0]
120 self
.assertEqual(downloaded
['format_id'], '47')
122 ydl
= YDL({'format': '20/71/worst'})
123 ydl
.process_ie_result(info_dict
.copy())
124 downloaded
= ydl
.downloaded_info_dicts
[0]
125 self
.assertEqual(downloaded
['format_id'], '35')
128 ydl
.process_ie_result(info_dict
.copy())
129 downloaded
= ydl
.downloaded_info_dicts
[0]
130 self
.assertEqual(downloaded
['format_id'], '2')
132 ydl
= YDL({'format': 'webm/mp4'})
133 ydl
.process_ie_result(info_dict
.copy())
134 downloaded
= ydl
.downloaded_info_dicts
[0]
135 self
.assertEqual(downloaded
['format_id'], '47')
137 ydl
= YDL({'format': '3gp/40/mp4'})
138 ydl
.process_ie_result(info_dict
.copy())
139 downloaded
= ydl
.downloaded_info_dicts
[0]
140 self
.assertEqual(downloaded
['format_id'], '35')
142 ydl
= YDL({'format': 'example-with-dashes'})
143 ydl
.process_ie_result(info_dict
.copy())
144 downloaded
= ydl
.downloaded_info_dicts
[0]
145 self
.assertEqual(downloaded
['format_id'], 'example-with-dashes')
147 def test_format_selection_audio(self
):
149 {'format_id': 'audio-low', 'ext': 'webm', 'preference': 1, 'vcodec': 'none', 'url': TEST_URL
},
150 {'format_id': 'audio-mid', 'ext': 'webm', 'preference': 2, 'vcodec': 'none', 'url': TEST_URL
},
151 {'format_id': 'audio-high', 'ext': 'flv', 'preference': 3, 'vcodec': 'none', 'url': TEST_URL
},
152 {'format_id': 'vid', 'ext': 'mp4', 'preference': 4, 'url': TEST_URL
},
154 info_dict
= _make_result(formats
)
156 ydl
= YDL({'format': 'bestaudio'})
157 ydl
.process_ie_result(info_dict
.copy())
158 downloaded
= ydl
.downloaded_info_dicts
[0]
159 self
.assertEqual(downloaded
['format_id'], 'audio-high')
161 ydl
= YDL({'format': 'worstaudio'})
162 ydl
.process_ie_result(info_dict
.copy())
163 downloaded
= ydl
.downloaded_info_dicts
[0]
164 self
.assertEqual(downloaded
['format_id'], 'audio-low')
167 {'format_id': 'vid-low', 'ext': 'mp4', 'preference': 1, 'url': TEST_URL
},
168 {'format_id': 'vid-high', 'ext': 'mp4', 'preference': 2, 'url': TEST_URL
},
170 info_dict
= _make_result(formats
)
172 ydl
= YDL({'format': 'bestaudio/worstaudio/best'})
173 ydl
.process_ie_result(info_dict
.copy())
174 downloaded
= ydl
.downloaded_info_dicts
[0]
175 self
.assertEqual(downloaded
['format_id'], 'vid-high')
177 def test_format_selection_audio_exts(self
):
179 {'format_id': 'mp3-64', 'ext': 'mp3', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'},
180 {'format_id': 'ogg-64', 'ext': 'ogg', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'},
181 {'format_id': 'aac-64', 'ext': 'aac', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'},
182 {'format_id': 'mp3-32', 'ext': 'mp3', 'abr': 32, 'url': 'http://_', 'vcodec': 'none'},
183 {'format_id': 'aac-32', 'ext': 'aac', 'abr': 32, 'url': 'http://_', 'vcodec': 'none'},
186 info_dict
= _make_result(formats
)
187 ydl
= YDL({'format': 'best'})
189 ie
._sort
_formats
(info_dict
['formats'])
190 ydl
.process_ie_result(copy
.deepcopy(info_dict
))
191 downloaded
= ydl
.downloaded_info_dicts
[0]
192 self
.assertEqual(downloaded
['format_id'], 'aac-64')
194 ydl
= YDL({'format': 'mp3'})
196 ie
._sort
_formats
(info_dict
['formats'])
197 ydl
.process_ie_result(copy
.deepcopy(info_dict
))
198 downloaded
= ydl
.downloaded_info_dicts
[0]
199 self
.assertEqual(downloaded
['format_id'], 'mp3-64')
201 ydl
= YDL({'prefer_free_formats': True})
203 ie
._sort
_formats
(info_dict
['formats'])
204 ydl
.process_ie_result(copy
.deepcopy(info_dict
))
205 downloaded
= ydl
.downloaded_info_dicts
[0]
206 self
.assertEqual(downloaded
['format_id'], 'ogg-64')
208 def test_format_selection_video(self
):
210 {'format_id': 'dash-video-low', 'ext': 'mp4', 'preference': 1, 'acodec': 'none', 'url': TEST_URL
},
211 {'format_id': 'dash-video-high', 'ext': 'mp4', 'preference': 2, 'acodec': 'none', 'url': TEST_URL
},
212 {'format_id': 'vid', 'ext': 'mp4', 'preference': 3, 'url': TEST_URL
},
214 info_dict
= _make_result(formats
)
216 ydl
= YDL({'format': 'bestvideo'})
217 ydl
.process_ie_result(info_dict
.copy())
218 downloaded
= ydl
.downloaded_info_dicts
[0]
219 self
.assertEqual(downloaded
['format_id'], 'dash-video-high')
221 ydl
= YDL({'format': 'worstvideo'})
222 ydl
.process_ie_result(info_dict
.copy())
223 downloaded
= ydl
.downloaded_info_dicts
[0]
224 self
.assertEqual(downloaded
['format_id'], 'dash-video-low')
226 ydl
= YDL({'format': 'bestvideo[format_id^=dash][format_id$=low]'})
227 ydl
.process_ie_result(info_dict
.copy())
228 downloaded
= ydl
.downloaded_info_dicts
[0]
229 self
.assertEqual(downloaded
['format_id'], 'dash-video-low')
232 {'format_id': 'vid-vcodec-dot', 'ext': 'mp4', 'preference': 1, 'vcodec': 'avc1.123456', 'acodec': 'none', 'url': TEST_URL
},
234 info_dict
= _make_result(formats
)
236 ydl
= YDL({'format': 'bestvideo[vcodec=avc1.123456]'})
237 ydl
.process_ie_result(info_dict
.copy())
238 downloaded
= ydl
.downloaded_info_dicts
[0]
239 self
.assertEqual(downloaded
['format_id'], 'vid-vcodec-dot')
241 def test_youtube_format_selection(self
):
243 '38', '37', '46', '22', '45', '35', '44', '18', '34', '43', '6', '5', '17', '36', '13',
244 # Apple HTTP Live Streaming
245 '96', '95', '94', '93', '92', '132', '151',
247 '85', '84', '102', '83', '101', '82', '100',
249 '137', '248', '136', '247', '135', '246',
250 '245', '244', '134', '243', '133', '242', '160',
252 '141', '172', '140', '171', '139',
255 def format_info(f_id
):
256 info
= YoutubeIE
._formats
[f_id
].copy()
258 # XXX: In real cases InfoExtractor._parse_mpd_formats() fills up 'acodec'
259 # and 'vcodec', while in tests such information is incomplete since
260 # commit a6c2c24479e5f4827ceb06f64d855329c0a6f593
261 # test_YoutubeDL.test_youtube_format_selection is broken without
263 if 'acodec' in info
and 'vcodec' not in info
:
264 info
['vcodec'] = 'none'
265 elif 'vcodec' in info
and 'acodec' not in info
:
266 info
['acodec'] = 'none'
268 info
['format_id'] = f_id
269 info
['url'] = 'url:' + f_id
271 formats_order
= [format_info(f_id
) for f_id
in order
]
273 info_dict
= _make_result(list(formats_order
), extractor
='youtube')
274 ydl
= YDL({'format': 'bestvideo+bestaudio'})
276 yie
._sort
_formats
(info_dict
['formats'])
277 ydl
.process_ie_result(info_dict
)
278 downloaded
= ydl
.downloaded_info_dicts
[0]
279 self
.assertEqual(downloaded
['format_id'], '137+141')
280 self
.assertEqual(downloaded
['ext'], 'mp4')
282 info_dict
= _make_result(list(formats_order
), extractor
='youtube')
283 ydl
= YDL({'format': 'bestvideo[height>=999999]+bestaudio/best'})
285 yie
._sort
_formats
(info_dict
['formats'])
286 ydl
.process_ie_result(info_dict
)
287 downloaded
= ydl
.downloaded_info_dicts
[0]
288 self
.assertEqual(downloaded
['format_id'], '38')
290 info_dict
= _make_result(list(formats_order
), extractor
='youtube')
291 ydl
= YDL({'format': 'bestvideo/best,bestaudio'})
293 yie
._sort
_formats
(info_dict
['formats'])
294 ydl
.process_ie_result(info_dict
)
295 downloaded_ids
= [info
['format_id'] for info
in ydl
.downloaded_info_dicts
]
296 self
.assertEqual(downloaded_ids
, ['137', '141'])
298 info_dict
= _make_result(list(formats_order
), extractor
='youtube')
299 ydl
= YDL({'format': '(bestvideo[ext=mp4],bestvideo[ext=webm])+bestaudio'})
301 yie
._sort
_formats
(info_dict
['formats'])
302 ydl
.process_ie_result(info_dict
)
303 downloaded_ids
= [info
['format_id'] for info
in ydl
.downloaded_info_dicts
]
304 self
.assertEqual(downloaded_ids
, ['137+141', '248+141'])
306 info_dict
= _make_result(list(formats_order
), extractor
='youtube')
307 ydl
= YDL({'format': '(bestvideo[ext=mp4],bestvideo[ext=webm])[height<=720]+bestaudio'})
309 yie
._sort
_formats
(info_dict
['formats'])
310 ydl
.process_ie_result(info_dict
)
311 downloaded_ids
= [info
['format_id'] for info
in ydl
.downloaded_info_dicts
]
312 self
.assertEqual(downloaded_ids
, ['136+141', '247+141'])
314 info_dict
= _make_result(list(formats_order
), extractor
='youtube')
315 ydl
= YDL({'format': '(bestvideo[ext=none]/bestvideo[ext=webm])+bestaudio'})
317 yie
._sort
_formats
(info_dict
['formats'])
318 ydl
.process_ie_result(info_dict
)
319 downloaded_ids
= [info
['format_id'] for info
in ydl
.downloaded_info_dicts
]
320 self
.assertEqual(downloaded_ids
, ['248+141'])
322 for f1
, f2
in zip(formats_order
, formats_order
[1:]):
323 info_dict
= _make_result([f1
, f2
], extractor
='youtube')
324 ydl
= YDL({'format': 'best/bestvideo'})
326 yie
._sort
_formats
(info_dict
['formats'])
327 ydl
.process_ie_result(info_dict
)
328 downloaded
= ydl
.downloaded_info_dicts
[0]
329 self
.assertEqual(downloaded
['format_id'], f1
['format_id'])
331 info_dict
= _make_result([f2
, f1
], extractor
='youtube')
332 ydl
= YDL({'format': 'best/bestvideo'})
334 yie
._sort
_formats
(info_dict
['formats'])
335 ydl
.process_ie_result(info_dict
)
336 downloaded
= ydl
.downloaded_info_dicts
[0]
337 self
.assertEqual(downloaded
['format_id'], f1
['format_id'])
339 def test_audio_only_extractor_format_selection(self
):
340 # For extractors with incomplete formats (all formats are audio-only or
341 # video-only) best and worst should fallback to corresponding best/worst
342 # video-only or audio-only formats (as per
343 # https://github.com/rg3/youtube-dl/pull/5556)
345 {'format_id': 'low', 'ext': 'mp3', 'preference': 1, 'vcodec': 'none', 'url': TEST_URL
},
346 {'format_id': 'high', 'ext': 'mp3', 'preference': 2, 'vcodec': 'none', 'url': TEST_URL
},
348 info_dict
= _make_result(formats
)
350 ydl
= YDL({'format': 'best'})
351 ydl
.process_ie_result(info_dict
.copy())
352 downloaded
= ydl
.downloaded_info_dicts
[0]
353 self
.assertEqual(downloaded
['format_id'], 'high')
355 ydl
= YDL({'format': 'worst'})
356 ydl
.process_ie_result(info_dict
.copy())
357 downloaded
= ydl
.downloaded_info_dicts
[0]
358 self
.assertEqual(downloaded
['format_id'], 'low')
360 def test_format_not_available(self
):
362 {'format_id': 'regular', 'ext': 'mp4', 'height': 360, 'url': TEST_URL
},
363 {'format_id': 'video', 'ext': 'mp4', 'height': 720, 'acodec': 'none', 'url': TEST_URL
},
365 info_dict
= _make_result(formats
)
367 # This must fail since complete video-audio format does not match filter
368 # and extractor does not provide incomplete only formats (i.e. only
369 # video-only or audio-only).
370 ydl
= YDL({'format': 'best[height>360]'})
371 self
.assertRaises(ExtractorError
, ydl
.process_ie_result
, info_dict
.copy())
373 def test_invalid_format_specs(self
):
374 def assert_syntax_error(format_spec
):
375 ydl
= YDL({'format': format_spec
})
376 info_dict
= _make_result([{'format_id': 'foo', 'url': TEST_URL
}])
377 self
.assertRaises(SyntaxError, ydl
.process_ie_result
, info_dict
)
379 assert_syntax_error('bestvideo,,best')
380 assert_syntax_error('+bestaudio')
381 assert_syntax_error('bestvideo+')
382 assert_syntax_error('/')
384 def test_format_filtering(self
):
386 {'format_id': 'A', 'filesize': 500, 'width': 1000},
387 {'format_id': 'B', 'filesize': 1000, 'width': 500},
388 {'format_id': 'C', 'filesize': 1000, 'width': 400},
389 {'format_id': 'D', 'filesize': 2000, 'width': 600},
390 {'format_id': 'E', 'filesize': 3000},
392 {'format_id': 'G', 'filesize': 1000000},
395 f
['url'] = 'http://_/'
397 info_dict
= _make_result(formats
)
399 ydl
= YDL({'format': 'best[filesize<3000]'})
400 ydl
.process_ie_result(info_dict
)
401 downloaded
= ydl
.downloaded_info_dicts
[0]
402 self
.assertEqual(downloaded
['format_id'], 'D')
404 ydl
= YDL({'format': 'best[filesize<=3000]'})
405 ydl
.process_ie_result(info_dict
)
406 downloaded
= ydl
.downloaded_info_dicts
[0]
407 self
.assertEqual(downloaded
['format_id'], 'E')
409 ydl
= YDL({'format': 'best[filesize <= ? 3000]'})
410 ydl
.process_ie_result(info_dict
)
411 downloaded
= ydl
.downloaded_info_dicts
[0]
412 self
.assertEqual(downloaded
['format_id'], 'F')
414 ydl
= YDL({'format': 'best [filesize = 1000] [width>450]'})
415 ydl
.process_ie_result(info_dict
)
416 downloaded
= ydl
.downloaded_info_dicts
[0]
417 self
.assertEqual(downloaded
['format_id'], 'B')
419 ydl
= YDL({'format': 'best [filesize = 1000] [width!=450]'})
420 ydl
.process_ie_result(info_dict
)
421 downloaded
= ydl
.downloaded_info_dicts
[0]
422 self
.assertEqual(downloaded
['format_id'], 'C')
424 ydl
= YDL({'format': '[filesize>?1]'})
425 ydl
.process_ie_result(info_dict
)
426 downloaded
= ydl
.downloaded_info_dicts
[0]
427 self
.assertEqual(downloaded
['format_id'], 'G')
429 ydl
= YDL({'format': '[filesize<1M]'})
430 ydl
.process_ie_result(info_dict
)
431 downloaded
= ydl
.downloaded_info_dicts
[0]
432 self
.assertEqual(downloaded
['format_id'], 'E')
434 ydl
= YDL({'format': '[filesize<1MiB]'})
435 ydl
.process_ie_result(info_dict
)
436 downloaded
= ydl
.downloaded_info_dicts
[0]
437 self
.assertEqual(downloaded
['format_id'], 'G')
439 ydl
= YDL({'format': 'all[width>=400][width<=600]'})
440 ydl
.process_ie_result(info_dict
)
441 downloaded_ids
= [info
['format_id'] for info
in ydl
.downloaded_info_dicts
]
442 self
.assertEqual(downloaded_ids
, ['B', 'C', 'D'])
444 ydl
= YDL({'format': 'best[height<40]'})
446 ydl
.process_ie_result(info_dict
)
447 except ExtractorError
:
449 self
.assertEqual(ydl
.downloaded_info_dicts
, [])
452 class TestYoutubeDL(unittest
.TestCase
):
453 def test_subtitles(self
):
454 def s_formats(lang
, autocaption
=False):
457 'url': 'http://localhost/video.%s.%s' % (lang
, ext
),
458 '_auto': autocaption
,
459 } for ext
in ['vtt', 'srt', 'ass']]
460 subtitles
= dict((l
, s_formats(l
)) for l
in ['en', 'fr', 'es'])
461 auto_captions
= dict((l
, s_formats(l
, True)) for l
in ['it', 'pt', 'es'])
465 'url': 'http://localhost/video.mp4',
466 'subtitles': subtitles
,
467 'automatic_captions': auto_captions
,
471 def get_info(params
={}):
472 params
.setdefault('simulate', True)
474 ydl
.report_warning
= lambda *args
, **kargs
: None
475 return ydl
.process_video_result(info_dict
, download
=False)
478 self
.assertFalse(result
.get('requested_subtitles'))
479 self
.assertEqual(result
['subtitles'], subtitles
)
480 self
.assertEqual(result
['automatic_captions'], auto_captions
)
482 result
= get_info({'writesubtitles': True})
483 subs
= result
['requested_subtitles']
484 self
.assertTrue(subs
)
485 self
.assertEqual(set(subs
.keys()), set(['en']))
486 self
.assertTrue(subs
['en'].get('data') is None)
487 self
.assertEqual(subs
['en']['ext'], 'ass')
489 result
= get_info({'writesubtitles': True, 'subtitlesformat': 'foo/srt'})
490 subs
= result
['requested_subtitles']
491 self
.assertEqual(subs
['en']['ext'], 'srt')
493 result
= get_info({'writesubtitles': True, 'subtitleslangs': ['es', 'fr', 'it']})
494 subs
= result
['requested_subtitles']
495 self
.assertTrue(subs
)
496 self
.assertEqual(set(subs
.keys()), set(['es', 'fr']))
498 result
= get_info({'writesubtitles': True, 'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']})
499 subs
= result
['requested_subtitles']
500 self
.assertTrue(subs
)
501 self
.assertEqual(set(subs
.keys()), set(['es', 'pt']))
502 self
.assertFalse(subs
['es']['_auto'])
503 self
.assertTrue(subs
['pt']['_auto'])
505 result
= get_info({'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']})
506 subs
= result
['requested_subtitles']
507 self
.assertTrue(subs
)
508 self
.assertEqual(set(subs
.keys()), set(['es', 'pt']))
509 self
.assertTrue(subs
['es']['_auto'])
510 self
.assertTrue(subs
['pt']['_auto'])
512 def test_add_extra_info(self
):
518 'playlist': 'funny videos',
520 YDL
.add_extra_info(test_dict
, extra_info
)
521 self
.assertEqual(test_dict
['extractor'], 'Foo')
522 self
.assertEqual(test_dict
['playlist'], 'funny videos')
524 def test_prepare_filename(self
):
533 ydl
= YoutubeDL({'outtmpl': templ
})
534 return ydl
.prepare_filename(info
)
535 self
.assertEqual(fname('%(id)s.%(ext)s'), '1234.mp4')
536 self
.assertEqual(fname('%(id)s-%(width)s.%(ext)s'), '1234-NA.mp4')
537 # Replace missing fields with 'NA'
538 self
.assertEqual(fname('%(uploader_date)s-%(id)s.%(ext)s'), 'NA-1234.mp4')
539 self
.assertEqual(fname('%(height)d.%(ext)s'), '1080.mp4')
540 self
.assertEqual(fname('%(height)6d.%(ext)s'), ' 1080.mp4')
541 self
.assertEqual(fname('%(height)-6d.%(ext)s'), '1080 .mp4')
542 self
.assertEqual(fname('%(height)06d.%(ext)s'), '001080.mp4')
543 self
.assertEqual(fname('%(height) 06d.%(ext)s'), ' 01080.mp4')
544 self
.assertEqual(fname('%(height) 06d.%(ext)s'), ' 01080.mp4')
545 self
.assertEqual(fname('%(height)0 6d.%(ext)s'), ' 01080.mp4')
546 self
.assertEqual(fname('%(height)0 6d.%(ext)s'), ' 01080.mp4')
547 self
.assertEqual(fname('%(height) 0 6d.%(ext)s'), ' 01080.mp4')
548 self
.assertEqual(fname('%%(height)06d.%(ext)s'), '%(height)06d.mp4')
549 self
.assertEqual(fname('%(width)06d.%(ext)s'), 'NA.mp4')
550 self
.assertEqual(fname('%(width)06d.%%(ext)s'), 'NA.%(ext)s')
551 self
.assertEqual(fname('%%(width)06d.%(ext)s'), '%(width)06d.mp4')
553 def test_format_note(self
):
555 self
.assertEqual(ydl
._format
_note
({}), '')
556 assertRegexpMatches(self
, ydl
._format
_note
({
559 assertRegexpMatches(self
, ydl
._format
_note
({
563 def test_postprocessors(self
):
564 filename
= 'post-processor-testfile.mp4'
565 audiofile
= filename
+ '.mp3'
567 class SimplePP(PostProcessor
):
569 with open(audiofile
, 'wt') as f
:
571 return [info
['filepath']], info
573 def run_pp(params
, PP
):
574 with open(filename
, 'wt') as f
:
576 ydl
= YoutubeDL(params
)
577 ydl
.add_post_processor(PP())
578 ydl
.post_process(filename
, {'filepath': filename
})
580 run_pp({'keepvideo': True}, SimplePP
)
581 self
.assertTrue(os
.path
.exists(filename
), '%s doesn\'t exist' % filename
)
582 self
.assertTrue(os
.path
.exists(audiofile
), '%s doesn\'t exist' % audiofile
)
586 run_pp({'keepvideo': False}, SimplePP
)
587 self
.assertFalse(os
.path
.exists(filename
), '%s exists' % filename
)
588 self
.assertTrue(os
.path
.exists(audiofile
), '%s doesn\'t exist' % audiofile
)
591 class ModifierPP(PostProcessor
):
593 with open(info
['filepath'], 'wt') as f
:
597 run_pp({'keepvideo': False}, ModifierPP
)
598 self
.assertTrue(os
.path
.exists(filename
), '%s doesn\'t exist' % filename
)
601 def test_match_filter(self
):
602 class FilterYDL(YDL
):
603 def __init__(self
, *args
, **kwargs
):
604 super(FilterYDL
, self
).__init
__(*args
, **kwargs
)
605 self
.params
['simulate'] = True
607 def process_info(self
, info_dict
):
608 super(YDL
, self
).process_info(info_dict
)
610 def _match_entry(self
, info_dict
, incomplete
):
611 res
= super(FilterYDL
, self
)._match
_entry
(info_dict
, incomplete
)
613 self
.downloaded_info_dicts
.append(info_dict
)
622 'filesize': 10 * 1024,
624 'uploader': "變態妍字幕版 太妍 тест",
625 'creator': "тест ' 123 ' тест--",
633 'description': 'foo',
634 'filesize': 5 * 1024,
636 'uploader': "тест 123",
638 videos
= [first
, second
]
640 def get_videos(filter_
=None):
641 ydl
= FilterYDL({'match_filter': filter_
})
643 ydl
.process_ie_result(v
, download
=True)
644 return [v
['id'] for v
in ydl
.downloaded_info_dicts
]
647 self
.assertEqual(res
, ['1', '2'])
653 return 'Video id is not 1'
655 self
.assertEqual(res
, ['1'])
657 f
= match_filter_func('duration < 30')
659 self
.assertEqual(res
, ['2'])
661 f
= match_filter_func('description = foo')
663 self
.assertEqual(res
, ['2'])
665 f
= match_filter_func('description =? foo')
667 self
.assertEqual(res
, ['1', '2'])
669 f
= match_filter_func('filesize > 5KiB')
671 self
.assertEqual(res
, ['1'])
673 f
= match_filter_func('playlist_id = 42')
675 self
.assertEqual(res
, ['1'])
677 f
= match_filter_func('uploader = "變態妍字幕版 太妍 тест"')
679 self
.assertEqual(res
, ['1'])
681 f
= match_filter_func('uploader != "變態妍字幕版 太妍 тест"')
683 self
.assertEqual(res
, ['2'])
685 f
= match_filter_func('creator = "тест \' 123 \' тест--"')
687 self
.assertEqual(res
, ['1'])
689 f
= match_filter_func("creator = 'тест \\' 123 \\' тест--'")
691 self
.assertEqual(res
, ['1'])
693 f
= match_filter_func(r
"creator = 'тест \' 123 \' тест--' & duration > 30")
695 self
.assertEqual(res
, [])
697 def test_playlist_items_selection(self
):
700 'title': compat_str(i
),
702 } for i
in range(1, 5)]
707 'extractor': 'test:playlist',
708 'extractor_key': 'test:playlist',
709 'webpage_url': 'http://example.com',
714 # make a copy because the dictionary can be modified
715 ydl
.process_ie_result(playlist
.copy())
716 return [int(v
['id']) for v
in ydl
.downloaded_info_dicts
]
719 self
.assertEqual(result
, [1, 2, 3, 4])
721 result
= get_ids({'playlistend': 10})
722 self
.assertEqual(result
, [1, 2, 3, 4])
724 result
= get_ids({'playlistend': 2})
725 self
.assertEqual(result
, [1, 2])
727 result
= get_ids({'playliststart': 10})
728 self
.assertEqual(result
, [])
730 result
= get_ids({'playliststart': 2})
731 self
.assertEqual(result
, [2, 3, 4])
733 result
= get_ids({'playlist_items': '2-4'})
734 self
.assertEqual(result
, [2, 3, 4])
736 result
= get_ids({'playlist_items': '2,4'})
737 self
.assertEqual(result
, [2, 4])
739 result
= get_ids({'playlist_items': '10'})
740 self
.assertEqual(result
, [])
742 def test_urlopen_no_file_protocol(self
):
743 # see https://github.com/rg3/youtube-dl/issues/8227
745 self
.assertRaises(compat_urllib_error
.URLError
, ydl
.urlopen
, 'file:///etc/passwd')
747 def test_do_not_override_ie_key_in_url_transparent(self
):
750 class Foo1IE(InfoExtractor
):
751 _VALID_URL
= r
'foo1:'
753 def _real_extract(self
, url
):
755 '_type': 'url_transparent',
760 class Foo2IE(InfoExtractor
):
761 _VALID_URL
= r
'foo2:'
763 def _real_extract(self
, url
):
770 class Foo3IE(InfoExtractor
):
771 _VALID_URL
= r
'foo3:'
773 def _real_extract(self
, url
):
774 return _make_result([{'url': TEST_URL
}])
776 ydl
.add_info_extractor(Foo1IE(ydl
))
777 ydl
.add_info_extractor(Foo2IE(ydl
))
778 ydl
.add_info_extractor(Foo3IE(ydl
))
779 ydl
.extract_info('foo1:')
780 downloaded
= ydl
.downloaded_info_dicts
[0]
781 self
.assertEqual(downloaded
['url'], TEST_URL
)
784 if __name__
== '__main__':