]> jfr.im git - yt-dlp.git/blame - test/test_YoutubeDL.py
[ted] Always extract the subtitles
[yt-dlp.git] / test / test_YoutubeDL.py
CommitLineData
e028d0d1
JMF
1#!/usr/bin/env python
2
89087418
PH
3from __future__ import unicode_literals
4
5d254f77
PH
5# Allow direct execution
6import os
e028d0d1
JMF
7import sys
8import unittest
5d254f77 9sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
e028d0d1 10
0217c783
PH
11import copy
12
c57f7757 13from test.helper import FakeYDL, assertRegexpMatches
26e63931 14from youtube_dl import YoutubeDL
3d4a70b8 15from youtube_dl.extractor import YoutubeIE
2b4ecde2 16from youtube_dl.postprocessor.common import PostProcessor
e028d0d1 17
e028d0d1
JMF
18
19class YDL(FakeYDL):
f4d96df0
PH
20 def __init__(self, *args, **kwargs):
21 super(YDL, self).__init__(*args, **kwargs)
e028d0d1 22 self.downloaded_info_dicts = []
f4d96df0 23 self.msgs = []
5d254f77 24
e028d0d1
JMF
25 def process_info(self, info_dict):
26 self.downloaded_info_dicts.append(info_dict)
27
f4d96df0
PH
28 def to_screen(self, msg):
29 self.msgs.append(msg)
30
5d254f77 31
3537b93d
PH
32def _make_result(formats, **kwargs):
33 res = {
34 'formats': formats,
35 'id': 'testid',
36 'title': 'testttitle',
37 'extractor': 'testex',
38 }
39 res.update(**kwargs)
40 return res
41
42
e028d0d1
JMF
43class TestFormatSelection(unittest.TestCase):
44 def test_prefer_free_formats(self):
45 # Same resolution => download webm
46 ydl = YDL()
47 ydl.params['prefer_free_formats'] = True
5d254f77 48 formats = [
3537b93d
PH
49 {'ext': 'webm', 'height': 460, 'url': 'x'},
50 {'ext': 'mp4', 'height': 460, 'url': 'y'},
5d254f77 51 ]
3537b93d 52 info_dict = _make_result(formats)
3d4a70b8
PH
53 yie = YoutubeIE(ydl)
54 yie._sort_formats(info_dict['formats'])
e028d0d1
JMF
55 ydl.process_ie_result(info_dict)
56 downloaded = ydl.downloaded_info_dicts[0]
89087418 57 self.assertEqual(downloaded['ext'], 'webm')
e028d0d1
JMF
58
59 # Different resolution => download best quality (mp4)
60 ydl = YDL()
61 ydl.params['prefer_free_formats'] = True
5d254f77 62 formats = [
3537b93d
PH
63 {'ext': 'webm', 'height': 720, 'url': 'a'},
64 {'ext': 'mp4', 'height': 1080, 'url': 'b'},
5d254f77 65 ]
89087418 66 info_dict['formats'] = formats
3d4a70b8
PH
67 yie = YoutubeIE(ydl)
68 yie._sort_formats(info_dict['formats'])
e028d0d1
JMF
69 ydl.process_ie_result(info_dict)
70 downloaded = ydl.downloaded_info_dicts[0]
89087418 71 self.assertEqual(downloaded['ext'], 'mp4')
e028d0d1 72
1c783bca 73 # No prefer_free_formats => prefer mp4 and flv for greater compatibility
e028d0d1
JMF
74 ydl = YDL()
75 ydl.params['prefer_free_formats'] = False
5d254f77 76 formats = [
3537b93d
PH
77 {'ext': 'webm', 'height': 720, 'url': '_'},
78 {'ext': 'mp4', 'height': 720, 'url': '_'},
79 {'ext': 'flv', 'height': 720, 'url': '_'},
5d254f77 80 ]
89087418 81 info_dict['formats'] = formats
3d4a70b8
PH
82 yie = YoutubeIE(ydl)
83 yie._sort_formats(info_dict['formats'])
84 ydl.process_ie_result(info_dict)
85 downloaded = ydl.downloaded_info_dicts[0]
89087418 86 self.assertEqual(downloaded['ext'], 'mp4')
3d4a70b8
PH
87
88 ydl = YDL()
89 ydl.params['prefer_free_formats'] = False
90 formats = [
3537b93d
PH
91 {'ext': 'flv', 'height': 720, 'url': '_'},
92 {'ext': 'webm', 'height': 720, 'url': '_'},
3d4a70b8 93 ]
89087418 94 info_dict['formats'] = formats
3d4a70b8
PH
95 yie = YoutubeIE(ydl)
96 yie._sort_formats(info_dict['formats'])
e028d0d1
JMF
97 ydl.process_ie_result(info_dict)
98 downloaded = ydl.downloaded_info_dicts[0]
89087418 99 self.assertEqual(downloaded['ext'], 'flv')
e028d0d1 100
f4d96df0
PH
101 def test_format_limit(self):
102 formats = [
89087418
PH
103 {'format_id': 'meh', 'url': 'http://example.com/meh', 'preference': 1},
104 {'format_id': 'good', 'url': 'http://example.com/good', 'preference': 2},
105 {'format_id': 'great', 'url': 'http://example.com/great', 'preference': 3},
106 {'format_id': 'excellent', 'url': 'http://example.com/exc', 'preference': 4},
f4d96df0 107 ]
3537b93d 108 info_dict = _make_result(formats)
f4d96df0
PH
109
110 ydl = YDL()
111 ydl.process_ie_result(info_dict)
112 downloaded = ydl.downloaded_info_dicts[0]
89087418 113 self.assertEqual(downloaded['format_id'], 'excellent')
f4d96df0
PH
114
115 ydl = YDL({'format_limit': 'good'})
116 assert ydl.params['format_limit'] == 'good'
8e3e0322 117 ydl.process_ie_result(info_dict.copy())
f4d96df0 118 downloaded = ydl.downloaded_info_dicts[0]
89087418 119 self.assertEqual(downloaded['format_id'], 'good')
f4d96df0
PH
120
121 ydl = YDL({'format_limit': 'great', 'format': 'all'})
8e3e0322 122 ydl.process_ie_result(info_dict.copy())
89087418
PH
123 self.assertEqual(ydl.downloaded_info_dicts[0]['format_id'], 'meh')
124 self.assertEqual(ydl.downloaded_info_dicts[1]['format_id'], 'good')
125 self.assertEqual(ydl.downloaded_info_dicts[2]['format_id'], 'great')
f4d96df0
PH
126 self.assertTrue('3' in ydl.msgs[0])
127
128 ydl = YDL()
129 ydl.params['format_limit'] = 'excellent'
8e3e0322 130 ydl.process_ie_result(info_dict.copy())
f4d96df0 131 downloaded = ydl.downloaded_info_dicts[0]
89087418 132 self.assertEqual(downloaded['format_id'], 'excellent')
f4d96df0 133
a9c58ad9
JMF
134 def test_format_selection(self):
135 formats = [
3537b93d
PH
136 {'format_id': '35', 'ext': 'mp4', 'preference': 1, 'url': '_'},
137 {'format_id': '45', 'ext': 'webm', 'preference': 2, 'url': '_'},
138 {'format_id': '47', 'ext': 'webm', 'preference': 3, 'url': '_'},
139 {'format_id': '2', 'ext': 'flv', 'preference': 4, 'url': '_'},
a9c58ad9 140 ]
3537b93d 141 info_dict = _make_result(formats)
a9c58ad9 142
89087418 143 ydl = YDL({'format': '20/47'})
8e3e0322 144 ydl.process_ie_result(info_dict.copy())
a9c58ad9 145 downloaded = ydl.downloaded_info_dicts[0]
89087418 146 self.assertEqual(downloaded['format_id'], '47')
a9c58ad9 147
89087418 148 ydl = YDL({'format': '20/71/worst'})
8e3e0322 149 ydl.process_ie_result(info_dict.copy())
a9c58ad9 150 downloaded = ydl.downloaded_info_dicts[0]
89087418 151 self.assertEqual(downloaded['format_id'], '35')
a9c58ad9
JMF
152
153 ydl = YDL()
8e3e0322 154 ydl.process_ie_result(info_dict.copy())
a9c58ad9 155 downloaded = ydl.downloaded_info_dicts[0]
89087418 156 self.assertEqual(downloaded['format_id'], '2')
a9c58ad9 157
89087418 158 ydl = YDL({'format': 'webm/mp4'})
8e3e0322 159 ydl.process_ie_result(info_dict.copy())
49e86983 160 downloaded = ydl.downloaded_info_dicts[0]
89087418 161 self.assertEqual(downloaded['format_id'], '47')
49e86983 162
89087418 163 ydl = YDL({'format': '3gp/40/mp4'})
8e3e0322 164 ydl.process_ie_result(info_dict.copy())
49e86983 165 downloaded = ydl.downloaded_info_dicts[0]
89087418 166 self.assertEqual(downloaded['format_id'], '35')
49e86983 167
ba7678f9
PH
168 def test_format_selection_audio(self):
169 formats = [
3537b93d
PH
170 {'format_id': 'audio-low', 'ext': 'webm', 'preference': 1, 'vcodec': 'none', 'url': '_'},
171 {'format_id': 'audio-mid', 'ext': 'webm', 'preference': 2, 'vcodec': 'none', 'url': '_'},
172 {'format_id': 'audio-high', 'ext': 'flv', 'preference': 3, 'vcodec': 'none', 'url': '_'},
173 {'format_id': 'vid', 'ext': 'mp4', 'preference': 4, 'url': '_'},
ba7678f9 174 ]
3537b93d 175 info_dict = _make_result(formats)
ba7678f9 176
89087418 177 ydl = YDL({'format': 'bestaudio'})
ba7678f9
PH
178 ydl.process_ie_result(info_dict.copy())
179 downloaded = ydl.downloaded_info_dicts[0]
89087418 180 self.assertEqual(downloaded['format_id'], 'audio-high')
ba7678f9 181
89087418 182 ydl = YDL({'format': 'worstaudio'})
ba7678f9
PH
183 ydl.process_ie_result(info_dict.copy())
184 downloaded = ydl.downloaded_info_dicts[0]
89087418 185 self.assertEqual(downloaded['format_id'], 'audio-low')
ba7678f9
PH
186
187 formats = [
3537b93d
PH
188 {'format_id': 'vid-low', 'ext': 'mp4', 'preference': 1, 'url': '_'},
189 {'format_id': 'vid-high', 'ext': 'mp4', 'preference': 2, 'url': '_'},
ba7678f9 190 ]
3537b93d 191 info_dict = _make_result(formats)
ba7678f9 192
89087418 193 ydl = YDL({'format': 'bestaudio/worstaudio/best'})
ba7678f9
PH
194 ydl.process_ie_result(info_dict.copy())
195 downloaded = ydl.downloaded_info_dicts[0]
89087418 196 self.assertEqual(downloaded['format_id'], 'vid-high')
ba7678f9 197
0217c783
PH
198 def test_format_selection_audio_exts(self):
199 formats = [
200 {'format_id': 'mp3-64', 'ext': 'mp3', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'},
201 {'format_id': 'ogg-64', 'ext': 'ogg', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'},
202 {'format_id': 'aac-64', 'ext': 'aac', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'},
203 {'format_id': 'mp3-32', 'ext': 'mp3', 'abr': 32, 'url': 'http://_', 'vcodec': 'none'},
204 {'format_id': 'aac-32', 'ext': 'aac', 'abr': 32, 'url': 'http://_', 'vcodec': 'none'},
205 ]
206
207 info_dict = _make_result(formats)
208 ydl = YDL({'format': 'best'})
209 ie = YoutubeIE(ydl)
210 ie._sort_formats(info_dict['formats'])
211 ydl.process_ie_result(copy.deepcopy(info_dict))
212 downloaded = ydl.downloaded_info_dicts[0]
213 self.assertEqual(downloaded['format_id'], 'aac-64')
214
215 ydl = YDL({'format': 'mp3'})
216 ie = YoutubeIE(ydl)
217 ie._sort_formats(info_dict['formats'])
218 ydl.process_ie_result(copy.deepcopy(info_dict))
219 downloaded = ydl.downloaded_info_dicts[0]
220 self.assertEqual(downloaded['format_id'], 'mp3-64')
221
222 ydl = YDL({'prefer_free_formats': True})
223 ie = YoutubeIE(ydl)
224 ie._sort_formats(info_dict['formats'])
225 ydl.process_ie_result(copy.deepcopy(info_dict))
226 downloaded = ydl.downloaded_info_dicts[0]
227 self.assertEqual(downloaded['format_id'], 'ogg-64')
228
bc6d5978
JMF
229 def test_format_selection_video(self):
230 formats = [
3537b93d
PH
231 {'format_id': 'dash-video-low', 'ext': 'mp4', 'preference': 1, 'acodec': 'none', 'url': '_'},
232 {'format_id': 'dash-video-high', 'ext': 'mp4', 'preference': 2, 'acodec': 'none', 'url': '_'},
233 {'format_id': 'vid', 'ext': 'mp4', 'preference': 3, 'url': '_'},
bc6d5978 234 ]
3537b93d 235 info_dict = _make_result(formats)
bc6d5978
JMF
236
237 ydl = YDL({'format': 'bestvideo'})
238 ydl.process_ie_result(info_dict.copy())
239 downloaded = ydl.downloaded_info_dicts[0]
240 self.assertEqual(downloaded['format_id'], 'dash-video-high')
241
242 ydl = YDL({'format': 'worstvideo'})
243 ydl.process_ie_result(info_dict.copy())
244 downloaded = ydl.downloaded_info_dicts[0]
245 self.assertEqual(downloaded['format_id'], 'dash-video-low')
246
3d4a70b8
PH
247 def test_youtube_format_selection(self):
248 order = [
249 '38', '37', '46', '22', '45', '35', '44', '18', '34', '43', '6', '5', '36', '17', '13',
250 # Apple HTTP Live Streaming
251 '96', '95', '94', '93', '92', '132', '151',
252 # 3D
253 '85', '84', '102', '83', '101', '82', '100',
254 # Dash video
c11125f9 255 '137', '248', '136', '247', '135', '246',
3d4a70b8
PH
256 '245', '244', '134', '243', '133', '242', '160',
257 # Dash audio
a053c349 258 '141', '172', '140', '171', '139',
3d4a70b8
PH
259 ]
260
261 for f1id, f2id in zip(order, order[1:]):
262 f1 = YoutubeIE._formats[f1id].copy()
263 f1['format_id'] = f1id
3537b93d 264 f1['url'] = 'url:' + f1id
3d4a70b8
PH
265 f2 = YoutubeIE._formats[f2id].copy()
266 f2['format_id'] = f2id
3537b93d 267 f2['url'] = 'url:' + f2id
3d4a70b8 268
3537b93d 269 info_dict = _make_result([f1, f2], extractor='youtube')
3d4a70b8
PH
270 ydl = YDL()
271 yie = YoutubeIE(ydl)
272 yie._sort_formats(info_dict['formats'])
273 ydl.process_ie_result(info_dict)
274 downloaded = ydl.downloaded_info_dicts[0]
275 self.assertEqual(downloaded['format_id'], f1id)
276
3537b93d 277 info_dict = _make_result([f2, f1], extractor='youtube')
3d4a70b8
PH
278 ydl = YDL()
279 yie = YoutubeIE(ydl)
280 yie._sort_formats(info_dict['formats'])
281 ydl.process_ie_result(info_dict)
282 downloaded = ydl.downloaded_info_dicts[0]
283 self.assertEqual(downloaded['format_id'], f1id)
284
083c9df9
PH
285 def test_format_filtering(self):
286 formats = [
287 {'format_id': 'A', 'filesize': 500, 'width': 1000},
288 {'format_id': 'B', 'filesize': 1000, 'width': 500},
289 {'format_id': 'C', 'filesize': 1000, 'width': 400},
290 {'format_id': 'D', 'filesize': 2000, 'width': 600},
291 {'format_id': 'E', 'filesize': 3000},
292 {'format_id': 'F'},
293 {'format_id': 'G', 'filesize': 1000000},
294 ]
295 for f in formats:
296 f['url'] = 'http://_/'
297 f['ext'] = 'unknown'
298 info_dict = _make_result(formats)
299
300 ydl = YDL({'format': 'best[filesize<3000]'})
301 ydl.process_ie_result(info_dict)
302 downloaded = ydl.downloaded_info_dicts[0]
303 self.assertEqual(downloaded['format_id'], 'D')
304
305 ydl = YDL({'format': 'best[filesize<=3000]'})
306 ydl.process_ie_result(info_dict)
307 downloaded = ydl.downloaded_info_dicts[0]
308 self.assertEqual(downloaded['format_id'], 'E')
309
310 ydl = YDL({'format': 'best[filesize <= ? 3000]'})
311 ydl.process_ie_result(info_dict)
312 downloaded = ydl.downloaded_info_dicts[0]
313 self.assertEqual(downloaded['format_id'], 'F')
314
315 ydl = YDL({'format': 'best [filesize = 1000] [width>450]'})
316 ydl.process_ie_result(info_dict)
317 downloaded = ydl.downloaded_info_dicts[0]
318 self.assertEqual(downloaded['format_id'], 'B')
319
320 ydl = YDL({'format': 'best [filesize = 1000] [width!=450]'})
321 ydl.process_ie_result(info_dict)
322 downloaded = ydl.downloaded_info_dicts[0]
323 self.assertEqual(downloaded['format_id'], 'C')
324
325 ydl = YDL({'format': '[filesize>?1]'})
326 ydl.process_ie_result(info_dict)
327 downloaded = ydl.downloaded_info_dicts[0]
328 self.assertEqual(downloaded['format_id'], 'G')
329
330 ydl = YDL({'format': '[filesize<1M]'})
331 ydl.process_ie_result(info_dict)
332 downloaded = ydl.downloaded_info_dicts[0]
333 self.assertEqual(downloaded['format_id'], 'E')
334
335 ydl = YDL({'format': '[filesize<1MiB]'})
336 ydl.process_ie_result(info_dict)
337 downloaded = ydl.downloaded_info_dicts[0]
338 self.assertEqual(downloaded['format_id'], 'G')
339
b6c45014
JMF
340 def test_add_extra_info(self):
341 test_dict = {
342 'extractor': 'Foo',
343 }
344 extra_info = {
345 'extractor': 'Bar',
346 'playlist': 'funny videos',
347 }
348 YDL.add_extra_info(test_dict, extra_info)
349 self.assertEqual(test_dict['extractor'], 'Foo')
350 self.assertEqual(test_dict['playlist'], 'funny videos')
351
26e63931
JMF
352 def test_prepare_filename(self):
353 info = {
89087418
PH
354 'id': '1234',
355 'ext': 'mp4',
356 'width': None,
26e63931 357 }
5f6a1245 358
26e63931
JMF
359 def fname(templ):
360 ydl = YoutubeDL({'outtmpl': templ})
361 return ydl.prepare_filename(info)
89087418
PH
362 self.assertEqual(fname('%(id)s.%(ext)s'), '1234.mp4')
363 self.assertEqual(fname('%(id)s-%(width)s.%(ext)s'), '1234-NA.mp4')
26e63931 364 # Replace missing fields with 'NA'
89087418 365 self.assertEqual(fname('%(uploader_date)s-%(id)s.%(ext)s'), 'NA-1234.mp4')
26e63931 366
c57f7757
PH
367 def test_format_note(self):
368 ydl = YoutubeDL()
369 self.assertEqual(ydl._format_note({}), '')
370 assertRegexpMatches(self, ydl._format_note({
371 'vbr': 10,
1c783bca 372 }), '^\s*10k$')
f4d96df0 373
2b4ecde2
JMF
374 def test_postprocessors(self):
375 filename = 'post-processor-testfile.mp4'
376 audiofile = filename + '.mp3'
377
378 class SimplePP(PostProcessor):
379 def run(self, info):
2b4ecde2
JMF
380 with open(audiofile, 'wt') as f:
381 f.write('EXAMPLE')
382 info['filepath']
383 return False, info
384
385 def run_pp(params):
386 with open(filename, 'wt') as f:
387 f.write('EXAMPLE')
388 ydl = YoutubeDL(params)
389 ydl.add_post_processor(SimplePP())
390 ydl.post_process(filename, {'filepath': filename})
391
392 run_pp({'keepvideo': True})
393 self.assertTrue(os.path.exists(filename), '%s doesn\'t exist' % filename)
394 self.assertTrue(os.path.exists(audiofile), '%s doesn\'t exist' % audiofile)
395 os.unlink(filename)
396 os.unlink(audiofile)
397
398 run_pp({'keepvideo': False})
399 self.assertFalse(os.path.exists(filename), '%s exists' % filename)
400 self.assertTrue(os.path.exists(audiofile), '%s doesn\'t exist' % audiofile)
401 os.unlink(audiofile)
402
403
e028d0d1
JMF
404if __name__ == '__main__':
405 unittest.main()