3 from __future__ import unicode_literals
5 # Allow direct execution
9 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
13 from test.helper import FakeYDL, assertRegexpMatches
14 from youtube_dl import YoutubeDL
15 from youtube_dl.extractor import YoutubeIE
16 from youtube_dl.postprocessor.common import PostProcessor
20 def __init__(self, *args, **kwargs):
21 super(YDL, self).__init__(*args, **kwargs)
22 self.downloaded_info_dicts = []
25 def process_info(self, info_dict):
26 self.downloaded_info_dicts.append(info_dict)
28 def to_screen(self, msg):
32 def _make_result(formats, **kwargs):
36 'title': 'testttitle',
37 'extractor': 'testex',
43 class TestFormatSelection(unittest.TestCase):
44 def test_prefer_free_formats(self):
45 # Same resolution => download webm
47 ydl.params['prefer_free_formats'] = True
49 {'ext': 'webm', 'height': 460, 'url': 'x'},
50 {'ext': 'mp4', 'height': 460, 'url': 'y'},
52 info_dict = _make_result(formats)
54 yie._sort_formats(info_dict['formats'])
55 ydl.process_ie_result(info_dict)
56 downloaded = ydl.downloaded_info_dicts[0]
57 self.assertEqual(downloaded['ext'], 'webm')
59 # Different resolution => download best quality (mp4)
61 ydl.params['prefer_free_formats'] = True
63 {'ext': 'webm', 'height': 720, 'url': 'a'},
64 {'ext': 'mp4', 'height': 1080, 'url': 'b'},
66 info_dict['formats'] = formats
68 yie._sort_formats(info_dict['formats'])
69 ydl.process_ie_result(info_dict)
70 downloaded = ydl.downloaded_info_dicts[0]
71 self.assertEqual(downloaded['ext'], 'mp4')
73 # No prefer_free_formats => prefer mp4 and flv for greater compatibility
75 ydl.params['prefer_free_formats'] = False
77 {'ext': 'webm', 'height': 720, 'url': '_'},
78 {'ext': 'mp4', 'height': 720, 'url': '_'},
79 {'ext': 'flv', 'height': 720, 'url': '_'},
81 info_dict['formats'] = formats
83 yie._sort_formats(info_dict['formats'])
84 ydl.process_ie_result(info_dict)
85 downloaded = ydl.downloaded_info_dicts[0]
86 self.assertEqual(downloaded['ext'], 'mp4')
89 ydl.params['prefer_free_formats'] = False
91 {'ext': 'flv', 'height': 720, 'url': '_'},
92 {'ext': 'webm', 'height': 720, 'url': '_'},
94 info_dict['formats'] = formats
96 yie._sort_formats(info_dict['formats'])
97 ydl.process_ie_result(info_dict)
98 downloaded = ydl.downloaded_info_dicts[0]
99 self.assertEqual(downloaded['ext'], 'flv')
101 def test_format_limit(self):
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},
108 info_dict = _make_result(formats)
111 ydl.process_ie_result(info_dict)
112 downloaded = ydl.downloaded_info_dicts[0]
113 self.assertEqual(downloaded['format_id'], 'excellent')
115 ydl = YDL({'format_limit': 'good'})
116 assert ydl.params['format_limit'] == 'good'
117 ydl.process_ie_result(info_dict.copy())
118 downloaded = ydl.downloaded_info_dicts[0]
119 self.assertEqual(downloaded['format_id'], 'good')
121 ydl = YDL({'format_limit': 'great', 'format': 'all'})
122 ydl.process_ie_result(info_dict.copy())
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')
126 self.assertTrue('3' in ydl.msgs[0])
129 ydl.params['format_limit'] = 'excellent'
130 ydl.process_ie_result(info_dict.copy())
131 downloaded = ydl.downloaded_info_dicts[0]
132 self.assertEqual(downloaded['format_id'], 'excellent')
134 def test_format_selection(self):
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': '_'},
141 info_dict = _make_result(formats)
143 ydl = YDL({'format': '20/47'})
144 ydl.process_ie_result(info_dict.copy())
145 downloaded = ydl.downloaded_info_dicts[0]
146 self.assertEqual(downloaded['format_id'], '47')
148 ydl = YDL({'format': '20/71/worst'})
149 ydl.process_ie_result(info_dict.copy())
150 downloaded = ydl.downloaded_info_dicts[0]
151 self.assertEqual(downloaded['format_id'], '35')
154 ydl.process_ie_result(info_dict.copy())
155 downloaded = ydl.downloaded_info_dicts[0]
156 self.assertEqual(downloaded['format_id'], '2')
158 ydl = YDL({'format': 'webm/mp4'})
159 ydl.process_ie_result(info_dict.copy())
160 downloaded = ydl.downloaded_info_dicts[0]
161 self.assertEqual(downloaded['format_id'], '47')
163 ydl = YDL({'format': '3gp/40/mp4'})
164 ydl.process_ie_result(info_dict.copy())
165 downloaded = ydl.downloaded_info_dicts[0]
166 self.assertEqual(downloaded['format_id'], '35')
168 def test_format_selection_audio(self):
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': '_'},
175 info_dict = _make_result(formats)
177 ydl = YDL({'format': 'bestaudio'})
178 ydl.process_ie_result(info_dict.copy())
179 downloaded = ydl.downloaded_info_dicts[0]
180 self.assertEqual(downloaded['format_id'], 'audio-high')
182 ydl = YDL({'format': 'worstaudio'})
183 ydl.process_ie_result(info_dict.copy())
184 downloaded = ydl.downloaded_info_dicts[0]
185 self.assertEqual(downloaded['format_id'], 'audio-low')
188 {'format_id': 'vid-low', 'ext': 'mp4', 'preference': 1, 'url': '_'},
189 {'format_id': 'vid-high', 'ext': 'mp4', 'preference': 2, 'url': '_'},
191 info_dict = _make_result(formats)
193 ydl = YDL({'format': 'bestaudio/worstaudio/best'})
194 ydl.process_ie_result(info_dict.copy())
195 downloaded = ydl.downloaded_info_dicts[0]
196 self.assertEqual(downloaded['format_id'], 'vid-high')
198 def test_format_selection_audio_exts(self):
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'},
207 info_dict = _make_result(formats)
208 ydl = YDL({'format': 'best'})
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')
215 ydl = YDL({'format': 'mp3'})
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')
222 ydl = YDL({'prefer_free_formats': True})
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')
229 def test_format_selection_video(self):
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': '_'},
235 info_dict = _make_result(formats)
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')
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')
247 def test_youtube_format_selection(self):
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',
253 '85', '84', '102', '83', '101', '82', '100',
255 '137', '248', '136', '247', '135', '246',
256 '245', '244', '134', '243', '133', '242', '160',
258 '141', '172', '140', '171', '139',
261 for f1id, f2id in zip(order, order[1:]):
262 f1 = YoutubeIE._formats[f1id].copy()
263 f1['format_id'] = f1id
264 f1['url'] = 'url:' + f1id
265 f2 = YoutubeIE._formats[f2id].copy()
266 f2['format_id'] = f2id
267 f2['url'] = 'url:' + f2id
269 info_dict = _make_result([f1, f2], extractor='youtube')
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)
277 info_dict = _make_result([f2, f1], extractor='youtube')
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)
285 def test_format_filtering(self):
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},
293 {'format_id': 'G', 'filesize': 1000000},
296 f['url'] = 'http://_/'
298 info_dict = _make_result(formats)
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')
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')
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')
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')
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')
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')
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')
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')
340 def test_add_extra_info(self):
346 'playlist': 'funny videos',
348 YDL.add_extra_info(test_dict, extra_info)
349 self.assertEqual(test_dict['extractor'], 'Foo')
350 self.assertEqual(test_dict['playlist'], 'funny videos')
352 def test_prepare_filename(self):
360 ydl = YoutubeDL({'outtmpl': templ})
361 return ydl.prepare_filename(info)
362 self.assertEqual(fname('%(id)s.%(ext)s'), '1234.mp4')
363 self.assertEqual(fname('%(id)s-%(width)s.%(ext)s'), '1234-NA.mp4')
364 # Replace missing fields with 'NA'
365 self.assertEqual(fname('%(uploader_date)s-%(id)s.%(ext)s'), 'NA-1234.mp4')
367 def test_format_note(self):
369 self.assertEqual(ydl._format_note({}), '')
370 assertRegexpMatches(self, ydl._format_note({
374 def test_postprocessors(self):
375 filename = 'post-processor-testfile.mp4'
376 audiofile = filename + '.mp3'
378 class SimplePP(PostProcessor):
380 with open(audiofile, 'wt') as f:
386 with open(filename, 'wt') as f:
388 ydl = YoutubeDL(params)
389 ydl.add_post_processor(SimplePP())
390 ydl.post_process(filename, {'filepath': filename})
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)
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)
404 if __name__ == '__main__':