]>
Raphaƫl G. Git Repositories - youtubedl/blob - test/test_YoutubeDL.py
a13c09ef40c7d8c101c86b471cae142ada9ccd7c
   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
.compat 
import compat_str
 
  16 from youtube_dl
.extractor 
import YoutubeIE
 
  17 from youtube_dl
.postprocessor
.common 
import PostProcessor
 
  18 from youtube_dl
.utils 
import match_filter_func
 
  20 TEST_URL 
= 'http://localhost/sample.mp4' 
  24     def __init__(self
, *args
, **kwargs
): 
  25         super(YDL
, self
).__init
__(*args
, **kwargs
) 
  26         self
.downloaded_info_dicts 
= [] 
  29     def process_info(self
, info_dict
): 
  30         self
.downloaded_info_dicts
.append(info_dict
) 
  32     def to_screen(self
, msg
): 
  36 def _make_result(formats
, **kwargs
): 
  40         'title': 'testttitle', 
  41         'extractor': 'testex', 
  47 class TestFormatSelection(unittest
.TestCase
): 
  48     def test_prefer_free_formats(self
): 
  49         # Same resolution => download webm 
  51         ydl
.params
['prefer_free_formats'] = True 
  53             {'ext': 'webm', 'height': 460, 'url': TEST_URL
}, 
  54             {'ext': 'mp4', 'height': 460, 'url': TEST_URL
}, 
  56         info_dict 
= _make_result(formats
) 
  58         yie
._sort
_formats
(info_dict
['formats']) 
  59         ydl
.process_ie_result(info_dict
) 
  60         downloaded 
= ydl
.downloaded_info_dicts
[0] 
  61         self
.assertEqual(downloaded
['ext'], 'webm') 
  63         # Different resolution => download best quality (mp4) 
  65         ydl
.params
['prefer_free_formats'] = True 
  67             {'ext': 'webm', 'height': 720, 'url': TEST_URL
}, 
  68             {'ext': 'mp4', 'height': 1080, 'url': TEST_URL
}, 
  70         info_dict
['formats'] = formats
 
  72         yie
._sort
_formats
(info_dict
['formats']) 
  73         ydl
.process_ie_result(info_dict
) 
  74         downloaded 
= ydl
.downloaded_info_dicts
[0] 
  75         self
.assertEqual(downloaded
['ext'], 'mp4') 
  77         # No prefer_free_formats => prefer mp4 and flv for greater compatibility 
  79         ydl
.params
['prefer_free_formats'] = False 
  81             {'ext': 'webm', 'height': 720, 'url': TEST_URL
}, 
  82             {'ext': 'mp4', 'height': 720, 'url': TEST_URL
}, 
  83             {'ext': 'flv', 'height': 720, 'url': TEST_URL
}, 
  85         info_dict
['formats'] = formats
 
  87         yie
._sort
_formats
(info_dict
['formats']) 
  88         ydl
.process_ie_result(info_dict
) 
  89         downloaded 
= ydl
.downloaded_info_dicts
[0] 
  90         self
.assertEqual(downloaded
['ext'], 'mp4') 
  93         ydl
.params
['prefer_free_formats'] = False 
  95             {'ext': 'flv', 'height': 720, 'url': TEST_URL
}, 
  96             {'ext': 'webm', 'height': 720, 'url': TEST_URL
}, 
  98         info_dict
['formats'] = formats
 
 100         yie
._sort
_formats
(info_dict
['formats']) 
 101         ydl
.process_ie_result(info_dict
) 
 102         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 103         self
.assertEqual(downloaded
['ext'], 'flv') 
 105     def test_format_selection(self
): 
 107             {'format_id': '35', 'ext': 'mp4', 'preference': 1, 'url': TEST_URL
}, 
 108             {'format_id': '45', 'ext': 'webm', 'preference': 2, 'url': TEST_URL
}, 
 109             {'format_id': '47', 'ext': 'webm', 'preference': 3, 'url': TEST_URL
}, 
 110             {'format_id': '2', 'ext': 'flv', 'preference': 4, 'url': TEST_URL
}, 
 112         info_dict 
= _make_result(formats
) 
 114         ydl 
= YDL({'format': '20/47'}) 
 115         ydl
.process_ie_result(info_dict
.copy()) 
 116         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 117         self
.assertEqual(downloaded
['format_id'], '47') 
 119         ydl 
= YDL({'format': '20/71/worst'}) 
 120         ydl
.process_ie_result(info_dict
.copy()) 
 121         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 122         self
.assertEqual(downloaded
['format_id'], '35') 
 125         ydl
.process_ie_result(info_dict
.copy()) 
 126         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 127         self
.assertEqual(downloaded
['format_id'], '2') 
 129         ydl 
= YDL({'format': 'webm/mp4'}) 
 130         ydl
.process_ie_result(info_dict
.copy()) 
 131         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 132         self
.assertEqual(downloaded
['format_id'], '47') 
 134         ydl 
= YDL({'format': '3gp/40/mp4'}) 
 135         ydl
.process_ie_result(info_dict
.copy()) 
 136         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 137         self
.assertEqual(downloaded
['format_id'], '35') 
 139     def test_format_selection_audio(self
): 
 141             {'format_id': 'audio-low', 'ext': 'webm', 'preference': 1, 'vcodec': 'none', 'url': TEST_URL
}, 
 142             {'format_id': 'audio-mid', 'ext': 'webm', 'preference': 2, 'vcodec': 'none', 'url': TEST_URL
}, 
 143             {'format_id': 'audio-high', 'ext': 'flv', 'preference': 3, 'vcodec': 'none', 'url': TEST_URL
}, 
 144             {'format_id': 'vid', 'ext': 'mp4', 'preference': 4, 'url': TEST_URL
}, 
 146         info_dict 
= _make_result(formats
) 
 148         ydl 
= YDL({'format': 'bestaudio'}) 
 149         ydl
.process_ie_result(info_dict
.copy()) 
 150         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 151         self
.assertEqual(downloaded
['format_id'], 'audio-high') 
 153         ydl 
= YDL({'format': 'worstaudio'}) 
 154         ydl
.process_ie_result(info_dict
.copy()) 
 155         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 156         self
.assertEqual(downloaded
['format_id'], 'audio-low') 
 159             {'format_id': 'vid-low', 'ext': 'mp4', 'preference': 1, 'url': TEST_URL
}, 
 160             {'format_id': 'vid-high', 'ext': 'mp4', 'preference': 2, 'url': TEST_URL
}, 
 162         info_dict 
= _make_result(formats
) 
 164         ydl 
= YDL({'format': 'bestaudio/worstaudio/best'}) 
 165         ydl
.process_ie_result(info_dict
.copy()) 
 166         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 167         self
.assertEqual(downloaded
['format_id'], 'vid-high') 
 169     def test_format_selection_audio_exts(self
): 
 171             {'format_id': 'mp3-64', 'ext': 'mp3', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'}, 
 172             {'format_id': 'ogg-64', 'ext': 'ogg', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'}, 
 173             {'format_id': 'aac-64', 'ext': 'aac', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'}, 
 174             {'format_id': 'mp3-32', 'ext': 'mp3', 'abr': 32, 'url': 'http://_', 'vcodec': 'none'}, 
 175             {'format_id': 'aac-32', 'ext': 'aac', 'abr': 32, 'url': 'http://_', 'vcodec': 'none'}, 
 178         info_dict 
= _make_result(formats
) 
 179         ydl 
= YDL({'format': 'best'}) 
 181         ie
._sort
_formats
(info_dict
['formats']) 
 182         ydl
.process_ie_result(copy
.deepcopy(info_dict
)) 
 183         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 184         self
.assertEqual(downloaded
['format_id'], 'aac-64') 
 186         ydl 
= YDL({'format': 'mp3'}) 
 188         ie
._sort
_formats
(info_dict
['formats']) 
 189         ydl
.process_ie_result(copy
.deepcopy(info_dict
)) 
 190         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 191         self
.assertEqual(downloaded
['format_id'], 'mp3-64') 
 193         ydl 
= YDL({'prefer_free_formats': True}) 
 195         ie
._sort
_formats
(info_dict
['formats']) 
 196         ydl
.process_ie_result(copy
.deepcopy(info_dict
)) 
 197         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 198         self
.assertEqual(downloaded
['format_id'], 'ogg-64') 
 200     def test_format_selection_video(self
): 
 202             {'format_id': 'dash-video-low', 'ext': 'mp4', 'preference': 1, 'acodec': 'none', 'url': TEST_URL
}, 
 203             {'format_id': 'dash-video-high', 'ext': 'mp4', 'preference': 2, 'acodec': 'none', 'url': TEST_URL
}, 
 204             {'format_id': 'vid', 'ext': 'mp4', 'preference': 3, 'url': TEST_URL
}, 
 206         info_dict 
= _make_result(formats
) 
 208         ydl 
= YDL({'format': 'bestvideo'}) 
 209         ydl
.process_ie_result(info_dict
.copy()) 
 210         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 211         self
.assertEqual(downloaded
['format_id'], 'dash-video-high') 
 213         ydl 
= YDL({'format': 'worstvideo'}) 
 214         ydl
.process_ie_result(info_dict
.copy()) 
 215         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 216         self
.assertEqual(downloaded
['format_id'], 'dash-video-low') 
 218     def test_youtube_format_selection(self
): 
 220             '38', '37', '46', '22', '45', '35', '44', '18', '34', '43', '6', '5', '36', '17', '13', 
 221             # Apple HTTP Live Streaming 
 222             '96', '95', '94', '93', '92', '132', '151', 
 224             '85', '84', '102', '83', '101', '82', '100', 
 226             '137', '248', '136', '247', '135', '246', 
 227             '245', '244', '134', '243', '133', '242', '160', 
 229             '141', '172', '140', '171', '139', 
 232         for f1id
, f2id 
in zip(order
, order
[1:]): 
 233             f1 
= YoutubeIE
._formats
[f1id
].copy() 
 234             f1
['format_id'] = f1id
 
 235             f1
['url'] = 'url:' + f1id
 
 236             f2 
= YoutubeIE
._formats
[f2id
].copy() 
 237             f2
['format_id'] = f2id
 
 238             f2
['url'] = 'url:' + f2id
 
 240             info_dict 
= _make_result([f1
, f2
], extractor
='youtube') 
 241             ydl 
= YDL({'format': 'best/bestvideo'}) 
 243             yie
._sort
_formats
(info_dict
['formats']) 
 244             ydl
.process_ie_result(info_dict
) 
 245             downloaded 
= ydl
.downloaded_info_dicts
[0] 
 246             self
.assertEqual(downloaded
['format_id'], f1id
) 
 248             info_dict 
= _make_result([f2
, f1
], extractor
='youtube') 
 249             ydl 
= YDL({'format': 'best/bestvideo'}) 
 251             yie
._sort
_formats
(info_dict
['formats']) 
 252             ydl
.process_ie_result(info_dict
) 
 253             downloaded 
= ydl
.downloaded_info_dicts
[0] 
 254             self
.assertEqual(downloaded
['format_id'], f1id
) 
 256     def test_format_filtering(self
): 
 258             {'format_id': 'A', 'filesize': 500, 'width': 1000}, 
 259             {'format_id': 'B', 'filesize': 1000, 'width': 500}, 
 260             {'format_id': 'C', 'filesize': 1000, 'width': 400}, 
 261             {'format_id': 'D', 'filesize': 2000, 'width': 600}, 
 262             {'format_id': 'E', 'filesize': 3000}, 
 264             {'format_id': 'G', 'filesize': 1000000}, 
 267             f
['url'] = 'http://_/' 
 269         info_dict 
= _make_result(formats
) 
 271         ydl 
= YDL({'format': 'best[filesize<3000]'}) 
 272         ydl
.process_ie_result(info_dict
) 
 273         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 274         self
.assertEqual(downloaded
['format_id'], 'D') 
 276         ydl 
= YDL({'format': 'best[filesize<=3000]'}) 
 277         ydl
.process_ie_result(info_dict
) 
 278         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 279         self
.assertEqual(downloaded
['format_id'], 'E') 
 281         ydl 
= YDL({'format': 'best[filesize <= ? 3000]'}) 
 282         ydl
.process_ie_result(info_dict
) 
 283         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 284         self
.assertEqual(downloaded
['format_id'], 'F') 
 286         ydl 
= YDL({'format': 'best [filesize = 1000] [width>450]'}) 
 287         ydl
.process_ie_result(info_dict
) 
 288         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 289         self
.assertEqual(downloaded
['format_id'], 'B') 
 291         ydl 
= YDL({'format': 'best [filesize = 1000] [width!=450]'}) 
 292         ydl
.process_ie_result(info_dict
) 
 293         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 294         self
.assertEqual(downloaded
['format_id'], 'C') 
 296         ydl 
= YDL({'format': '[filesize>?1]'}) 
 297         ydl
.process_ie_result(info_dict
) 
 298         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 299         self
.assertEqual(downloaded
['format_id'], 'G') 
 301         ydl 
= YDL({'format': '[filesize<1M]'}) 
 302         ydl
.process_ie_result(info_dict
) 
 303         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 304         self
.assertEqual(downloaded
['format_id'], 'E') 
 306         ydl 
= YDL({'format': '[filesize<1MiB]'}) 
 307         ydl
.process_ie_result(info_dict
) 
 308         downloaded 
= ydl
.downloaded_info_dicts
[0] 
 309         self
.assertEqual(downloaded
['format_id'], 'G') 
 312 class TestYoutubeDL(unittest
.TestCase
): 
 313     def test_subtitles(self
): 
 314         def s_formats(lang
, autocaption
=False): 
 317                 'url': 'http://localhost/video.%s.%s' % (lang
, ext
), 
 318                 '_auto': autocaption
, 
 319             } for ext 
in ['vtt', 'srt', 'ass']] 
 320         subtitles 
= dict((l
, s_formats(l
)) for l 
in ['en', 'fr', 'es']) 
 321         auto_captions 
= dict((l
, s_formats(l
, True)) for l 
in ['it', 'pt', 'es']) 
 325             'url': 'http://localhost/video.mp4', 
 326             'subtitles': subtitles
, 
 327             'automatic_captions': auto_captions
, 
 331         def get_info(params
={}): 
 332             params
.setdefault('simulate', True) 
 334             ydl
.report_warning 
= lambda *args
, **kargs
: None 
 335             return ydl
.process_video_result(info_dict
, download
=False) 
 338         self
.assertFalse(result
.get('requested_subtitles')) 
 339         self
.assertEqual(result
['subtitles'], subtitles
) 
 340         self
.assertEqual(result
['automatic_captions'], auto_captions
) 
 342         result 
= get_info({'writesubtitles': True}) 
 343         subs 
= result
['requested_subtitles'] 
 344         self
.assertTrue(subs
) 
 345         self
.assertEqual(set(subs
.keys()), set(['en'])) 
 346         self
.assertTrue(subs
['en'].get('data') is None) 
 347         self
.assertEqual(subs
['en']['ext'], 'ass') 
 349         result 
= get_info({'writesubtitles': True, 'subtitlesformat': 'foo/srt'}) 
 350         subs 
= result
['requested_subtitles'] 
 351         self
.assertEqual(subs
['en']['ext'], 'srt') 
 353         result 
= get_info({'writesubtitles': True, 'subtitleslangs': ['es', 'fr', 'it']}) 
 354         subs 
= result
['requested_subtitles'] 
 355         self
.assertTrue(subs
) 
 356         self
.assertEqual(set(subs
.keys()), set(['es', 'fr'])) 
 358         result 
= get_info({'writesubtitles': True, 'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']}) 
 359         subs 
= result
['requested_subtitles'] 
 360         self
.assertTrue(subs
) 
 361         self
.assertEqual(set(subs
.keys()), set(['es', 'pt'])) 
 362         self
.assertFalse(subs
['es']['_auto']) 
 363         self
.assertTrue(subs
['pt']['_auto']) 
 365         result 
= get_info({'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']}) 
 366         subs 
= result
['requested_subtitles'] 
 367         self
.assertTrue(subs
) 
 368         self
.assertEqual(set(subs
.keys()), set(['es', 'pt'])) 
 369         self
.assertTrue(subs
['es']['_auto']) 
 370         self
.assertTrue(subs
['pt']['_auto']) 
 372     def test_add_extra_info(self
): 
 378             'playlist': 'funny videos', 
 380         YDL
.add_extra_info(test_dict
, extra_info
) 
 381         self
.assertEqual(test_dict
['extractor'], 'Foo') 
 382         self
.assertEqual(test_dict
['playlist'], 'funny videos') 
 384     def test_prepare_filename(self
): 
 392             ydl 
= YoutubeDL({'outtmpl': templ
}) 
 393             return ydl
.prepare_filename(info
) 
 394         self
.assertEqual(fname('%(id)s.%(ext)s'), '1234.mp4') 
 395         self
.assertEqual(fname('%(id)s-%(width)s.%(ext)s'), '1234-NA.mp4') 
 396         # Replace missing fields with 'NA' 
 397         self
.assertEqual(fname('%(uploader_date)s-%(id)s.%(ext)s'), 'NA-1234.mp4') 
 399     def test_format_note(self
): 
 401         self
.assertEqual(ydl
._format
_note
({}), '') 
 402         assertRegexpMatches(self
, ydl
._format
_note
({ 
 406     def test_postprocessors(self
): 
 407         filename 
= 'post-processor-testfile.mp4' 
 408         audiofile 
= filename 
+ '.mp3' 
 410         class SimplePP(PostProcessor
): 
 412                 with open(audiofile
, 'wt') as f
: 
 414                 return [info
['filepath']], info
 
 416         def run_pp(params
, PP
): 
 417             with open(filename
, 'wt') as f
: 
 419             ydl 
= YoutubeDL(params
) 
 420             ydl
.add_post_processor(PP()) 
 421             ydl
.post_process(filename
, {'filepath': filename
}) 
 423         run_pp({'keepvideo': True}, SimplePP
) 
 424         self
.assertTrue(os
.path
.exists(filename
), '%s doesn\'t exist' % filename
) 
 425         self
.assertTrue(os
.path
.exists(audiofile
), '%s doesn\'t exist' % audiofile
) 
 429         run_pp({'keepvideo': False}, SimplePP
) 
 430         self
.assertFalse(os
.path
.exists(filename
), '%s exists' % filename
) 
 431         self
.assertTrue(os
.path
.exists(audiofile
), '%s doesn\'t exist' % audiofile
) 
 434         class ModifierPP(PostProcessor
): 
 436                 with open(info
['filepath'], 'wt') as f
: 
 440         run_pp({'keepvideo': False}, ModifierPP
) 
 441         self
.assertTrue(os
.path
.exists(filename
), '%s doesn\'t exist' % filename
) 
 444     def test_match_filter(self
): 
 445         class FilterYDL(YDL
): 
 446             def __init__(self
, *args
, **kwargs
): 
 447                 super(FilterYDL
, self
).__init
__(*args
, **kwargs
) 
 448                 self
.params
['simulate'] = True 
 450             def process_info(self
, info_dict
): 
 451                 super(YDL
, self
).process_info(info_dict
) 
 453             def _match_entry(self
, info_dict
, incomplete
): 
 454                 res 
= super(FilterYDL
, self
)._match
_entry
(info_dict
, incomplete
) 
 456                     self
.downloaded_info_dicts
.append(info_dict
) 
 465             'filesize': 10 * 1024, 
 473             'description': 'foo', 
 474             'filesize': 5 * 1024, 
 476         videos 
= [first
, second
] 
 478         def get_videos(filter_
=None): 
 479             ydl 
= FilterYDL({'match_filter': filter_
}) 
 481                 ydl
.process_ie_result(v
, download
=True) 
 482             return [v
['id'] for v 
in ydl
.downloaded_info_dicts
] 
 485         self
.assertEqual(res
, ['1', '2']) 
 491                 return 'Video id is not 1' 
 493         self
.assertEqual(res
, ['1']) 
 495         f 
= match_filter_func('duration < 30') 
 497         self
.assertEqual(res
, ['2']) 
 499         f 
= match_filter_func('description = foo') 
 501         self
.assertEqual(res
, ['2']) 
 503         f 
= match_filter_func('description =? foo') 
 505         self
.assertEqual(res
, ['1', '2']) 
 507         f 
= match_filter_func('filesize > 5KiB') 
 509         self
.assertEqual(res
, ['1']) 
 511     def test_playlist_items_selection(self
): 
 514             'title': compat_str(i
), 
 516         } for i 
in range(1, 5)] 
 521             'extractor': 'test:playlist', 
 522             'extractor_key': 'test:playlist', 
 523             'webpage_url': 'http://example.com', 
 528             # make a copy because the dictionary can be modified 
 529             ydl
.process_ie_result(playlist
.copy()) 
 530             return [int(v
['id']) for v 
in ydl
.downloaded_info_dicts
] 
 533         self
.assertEqual(result
, [1, 2, 3, 4]) 
 535         result 
= get_ids({'playlistend': 10}) 
 536         self
.assertEqual(result
, [1, 2, 3, 4]) 
 538         result 
= get_ids({'playlistend': 2}) 
 539         self
.assertEqual(result
, [1, 2]) 
 541         result 
= get_ids({'playliststart': 10}) 
 542         self
.assertEqual(result
, []) 
 544         result 
= get_ids({'playliststart': 2}) 
 545         self
.assertEqual(result
, [2, 3, 4]) 
 547         result 
= get_ids({'playlist_items': '2-4'}) 
 548         self
.assertEqual(result
, [2, 3, 4]) 
 550         result 
= get_ids({'playlist_items': '2,4'}) 
 551         self
.assertEqual(result
, [2, 4]) 
 553         result 
= get_ids({'playlist_items': '10'}) 
 554         self
.assertEqual(result
, []) 
 557 if __name__ 
== '__main__':