Merge branch 'subtitles_rework' (closes PR #1326)

This commit is contained in:
Jaime Marquínez Ferrándiz 2013-09-11 17:37:57 +02:00
commit 542cca0e8c
8 changed files with 259 additions and 163 deletions

6
.gitignore vendored
View File

@ -18,3 +18,9 @@ youtube-dl.tar.gz
cover/ cover/
updates_key.pem updates_key.pem
*.egg-info *.egg-info
*.srt
*.sbv
*.vtt
*.flv
*.mp4
*.part

View File

@ -38,7 +38,6 @@
"writedescription": false, "writedescription": false,
"writeinfojson": true, "writeinfojson": true,
"writesubtitles": false, "writesubtitles": false,
"onlysubtitles": false,
"allsubtitles": false, "allsubtitles": false,
"listssubtitles": false "listssubtitles": false
} }

View File

@ -0,0 +1,69 @@
#!/usr/bin/env python
import sys
import unittest
import json
import io
import hashlib
# Allow direct execution
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from youtube_dl.extractor import DailymotionIE
from youtube_dl.utils import *
from helper import FakeYDL
md5 = lambda s: hashlib.md5(s.encode('utf-8')).hexdigest()
class TestDailymotionSubtitles(unittest.TestCase):
def setUp(self):
self.DL = FakeYDL()
self.url = 'http://www.dailymotion.com/video/xczg00'
def getInfoDict(self):
IE = DailymotionIE(self.DL)
info_dict = IE.extract(self.url)
return info_dict
def getSubtitles(self):
info_dict = self.getInfoDict()
return info_dict[0]['subtitles']
def test_no_writesubtitles(self):
subtitles = self.getSubtitles()
self.assertEqual(subtitles, None)
def test_subtitles(self):
self.DL.params['writesubtitles'] = True
subtitles = self.getSubtitles()
self.assertEqual(md5(subtitles['en']), '976553874490cba125086bbfea3ff76f')
def test_subtitles_lang(self):
self.DL.params['writesubtitles'] = True
self.DL.params['subtitleslangs'] = ['fr']
subtitles = self.getSubtitles()
self.assertEqual(md5(subtitles['fr']), '594564ec7d588942e384e920e5341792')
def test_allsubtitles(self):
self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles()
self.assertEqual(len(subtitles.keys()), 5)
def test_list_subtitles(self):
self.DL.params['listsubtitles'] = True
info_dict = self.getInfoDict()
self.assertEqual(info_dict, None)
def test_automatic_captions(self):
self.DL.params['writeautomaticsub'] = True
self.DL.params['subtitleslang'] = ['en']
subtitles = self.getSubtitles()
self.assertTrue(len(subtitles.keys()) == 0)
def test_nosubtitles(self):
self.url = 'http://www.dailymotion.com/video/x12u166_le-zapping-tele-star-du-08-aout-2013_tv'
self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles()
self.assertEqual(len(subtitles), 0)
def test_multiple_langs(self):
self.DL.params['writesubtitles'] = True
langs = ['es', 'fr', 'de']
self.DL.params['subtitleslangs'] = langs
subtitles = self.getSubtitles()
for lang in langs:
self.assertTrue(subtitles.get(lang) is not None, u'Subtitles for \'%s\' not extracted' % lang)
if __name__ == '__main__':
unittest.main()

View File

@ -18,85 +18,63 @@ md5 = lambda s: hashlib.md5(s.encode('utf-8')).hexdigest()
class TestYoutubeSubtitles(unittest.TestCase): class TestYoutubeSubtitles(unittest.TestCase):
def setUp(self): def setUp(self):
DL = FakeYDL() self.DL = FakeYDL()
DL.params['allsubtitles'] = False self.url = 'QRS8MkLhQmM'
DL.params['writesubtitles'] = False def getInfoDict(self):
DL.params['subtitlesformat'] = 'srt' IE = YoutubeIE(self.DL)
DL.params['listsubtitles'] = False info_dict = IE.extract(self.url)
def test_youtube_no_subtitles(self): return info_dict
DL = FakeYDL() def getSubtitles(self):
DL.params['writesubtitles'] = False info_dict = self.getInfoDict()
IE = YoutubeIE(DL) return info_dict[0]['subtitles']
info_dict = IE.extract('QRS8MkLhQmM') def test_youtube_no_writesubtitles(self):
subtitles = info_dict[0]['subtitles'] self.DL.params['writesubtitles'] = False
subtitles = self.getSubtitles()
self.assertEqual(subtitles, None) self.assertEqual(subtitles, None)
def test_youtube_subtitles(self): def test_youtube_subtitles(self):
DL = FakeYDL() self.DL.params['writesubtitles'] = True
DL.params['writesubtitles'] = True subtitles = self.getSubtitles()
IE = YoutubeIE(DL) self.assertEqual(md5(subtitles['en']), '4cd9278a35ba2305f47354ee13472260')
info_dict = IE.extract('QRS8MkLhQmM') def test_youtube_subtitles_lang(self):
sub = info_dict[0]['subtitles']['en'] self.DL.params['writesubtitles'] = True
self.assertEqual(md5(sub), '4cd9278a35ba2305f47354ee13472260') self.DL.params['subtitleslangs'] = ['it']
def test_youtube_subtitles_it(self): subtitles = self.getSubtitles()
DL = FakeYDL() self.assertEqual(md5(subtitles['it']), '164a51f16f260476a05b50fe4c2f161d')
DL.params['writesubtitles'] = True
DL.params['subtitleslangs'] = ['it']
IE = YoutubeIE(DL)
info_dict = IE.extract('QRS8MkLhQmM')
sub = info_dict[0]['subtitles']['it']
self.assertEqual(md5(sub), '164a51f16f260476a05b50fe4c2f161d')
def test_youtube_onlysubtitles(self):
DL = FakeYDL()
DL.params['writesubtitles'] = True
DL.params['onlysubtitles'] = True
IE = YoutubeIE(DL)
info_dict = IE.extract('QRS8MkLhQmM')
sub = info_dict[0]['subtitles']['en']
self.assertEqual(md5(sub), '4cd9278a35ba2305f47354ee13472260')
def test_youtube_allsubtitles(self): def test_youtube_allsubtitles(self):
DL = FakeYDL() self.DL.params['allsubtitles'] = True
DL.params['allsubtitles'] = True subtitles = self.getSubtitles()
IE = YoutubeIE(DL)
info_dict = IE.extract('QRS8MkLhQmM')
subtitles = info_dict[0]['subtitles']
self.assertEqual(len(subtitles.keys()), 13) self.assertEqual(len(subtitles.keys()), 13)
def test_youtube_subtitles_sbv_format(self): def test_youtube_subtitles_sbv_format(self):
DL = FakeYDL() self.DL.params['writesubtitles'] = True
DL.params['writesubtitles'] = True self.DL.params['subtitlesformat'] = 'sbv'
DL.params['subtitlesformat'] = 'sbv' subtitles = self.getSubtitles()
IE = YoutubeIE(DL) self.assertEqual(md5(subtitles['en']), '13aeaa0c245a8bed9a451cb643e3ad8b')
info_dict = IE.extract('QRS8MkLhQmM')
sub = info_dict[0]['subtitles']['en']
self.assertEqual(md5(sub), '13aeaa0c245a8bed9a451cb643e3ad8b')
def test_youtube_subtitles_vtt_format(self): def test_youtube_subtitles_vtt_format(self):
DL = FakeYDL() self.DL.params['writesubtitles'] = True
DL.params['writesubtitles'] = True self.DL.params['subtitlesformat'] = 'vtt'
DL.params['subtitlesformat'] = 'vtt' subtitles = self.getSubtitles()
IE = YoutubeIE(DL) self.assertEqual(md5(subtitles['en']), '356cdc577fde0c6783b9b822e7206ff7')
info_dict = IE.extract('QRS8MkLhQmM')
sub = info_dict[0]['subtitles']['en']
self.assertEqual(md5(sub), '356cdc577fde0c6783b9b822e7206ff7')
def test_youtube_list_subtitles(self): def test_youtube_list_subtitles(self):
DL = FakeYDL() self.DL.params['listsubtitles'] = True
DL.params['listsubtitles'] = True info_dict = self.getInfoDict()
IE = YoutubeIE(DL)
info_dict = IE.extract('QRS8MkLhQmM')
self.assertEqual(info_dict, None) self.assertEqual(info_dict, None)
def test_youtube_automatic_captions(self): def test_youtube_automatic_captions(self):
DL = FakeYDL() self.url = '8YoUxe5ncPo'
DL.params['writeautomaticsub'] = True self.DL.params['writeautomaticsub'] = True
DL.params['subtitleslangs'] = ['it'] self.DL.params['subtitleslangs'] = ['it']
IE = YoutubeIE(DL) subtitles = self.getSubtitles()
info_dict = IE.extract('8YoUxe5ncPo') self.assertTrue(subtitles['it'] is not None)
sub = info_dict[0]['subtitles']['it'] def test_youtube_nosubtitles(self):
self.assertTrue(sub is not None) self.url = 'sAjKT8FhjI8'
self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles()
self.assertEqual(len(subtitles), 0)
def test_youtube_multiple_langs(self): def test_youtube_multiple_langs(self):
DL = FakeYDL() self.url = 'QRS8MkLhQmM'
DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
langs = ['it', 'fr', 'de'] langs = ['it', 'fr', 'de']
DL.params['subtitleslangs'] = langs self.DL.params['subtitleslangs'] = langs
IE = YoutubeIE(DL) subtitles = self.getSubtitles()
subtitles = IE.extract('QRS8MkLhQmM')[0]['subtitles']
for lang in langs: for lang in langs:
self.assertTrue(subtitles.get(lang) is not None, u'Subtitles for \'%s\' not extracted' % lang) self.assertTrue(subtitles.get(lang) is not None, u'Subtitles for \'%s\' not extracted' % lang)

View File

@ -205,13 +205,10 @@ def parseOpts(overrideArguments=None):
subtitles.add_option('--write-sub', '--write-srt', subtitles.add_option('--write-sub', '--write-srt',
action='store_true', dest='writesubtitles', action='store_true', dest='writesubtitles',
help='write subtitle file (currently youtube only)', default=False) help='write subtitle file', default=False)
subtitles.add_option('--write-auto-sub', '--write-automatic-sub', subtitles.add_option('--write-auto-sub', '--write-automatic-sub',
action='store_true', dest='writeautomaticsub', action='store_true', dest='writeautomaticsub',
help='write automatic subtitle file (currently youtube only)', default=False) help='write automatic subtitle file (youtube only)', default=False)
subtitles.add_option('--only-sub',
action='store_true', dest='skip_download',
help='[deprecated] alias of --skip-download', default=False)
subtitles.add_option('--all-subs', subtitles.add_option('--all-subs',
action='store_true', dest='allsubtitles', action='store_true', dest='allsubtitles',
help='downloads all the available subtitles of the video', default=False) help='downloads all the available subtitles of the video', default=False)
@ -222,7 +219,7 @@ def parseOpts(overrideArguments=None):
action='store', dest='subtitlesformat', metavar='FORMAT', action='store', dest='subtitlesformat', metavar='FORMAT',
help='subtitle format (default=srt) ([sbv/vtt] youtube only)', default='srt') help='subtitle format (default=srt) ([sbv/vtt] youtube only)', default='srt')
subtitles.add_option('--sub-lang', '--sub-langs', '--srt-lang', subtitles.add_option('--sub-lang', '--sub-langs', '--srt-lang',
action='callback', dest='subtitleslang', metavar='LANGS', type='str', action='callback', dest='subtitleslangs', metavar='LANGS', type='str',
default=[], callback=_comma_separated_values_options_callback, default=[], callback=_comma_separated_values_options_callback,
help='languages of the subtitles to download (optional) separated by commas, use IETF language tags like \'en,pt\'') help='languages of the subtitles to download (optional) separated by commas, use IETF language tags like \'en,pt\'')
@ -593,7 +590,7 @@ def _real_main(argv=None):
'allsubtitles': opts.allsubtitles, 'allsubtitles': opts.allsubtitles,
'listsubtitles': opts.listsubtitles, 'listsubtitles': opts.listsubtitles,
'subtitlesformat': opts.subtitlesformat, 'subtitlesformat': opts.subtitlesformat,
'subtitleslangs': opts.subtitleslang, 'subtitleslangs': opts.subtitleslangs,
'matchtitle': decodeOption(opts.matchtitle), 'matchtitle': decodeOption(opts.matchtitle),
'rejecttitle': decodeOption(opts.rejecttitle), 'rejecttitle': decodeOption(opts.rejecttitle),
'max_downloads': opts.max_downloads, 'max_downloads': opts.max_downloads,

View File

@ -3,15 +3,19 @@ import json
import itertools import itertools
from .common import InfoExtractor from .common import InfoExtractor
from .subtitles import SubtitlesInfoExtractor
from ..utils import ( from ..utils import (
compat_urllib_request, compat_urllib_request,
compat_str,
get_element_by_attribute, get_element_by_attribute,
get_element_by_id, get_element_by_id,
ExtractorError, ExtractorError,
) )
class DailymotionIE(InfoExtractor):
class DailymotionIE(SubtitlesInfoExtractor):
"""Information Extractor for Dailymotion""" """Information Extractor for Dailymotion"""
_VALID_URL = r'(?i)(?:https?://)?(?:www\.)?dailymotion\.[a-z]{2,3}/(?:embed/)?video/([^/]+)' _VALID_URL = r'(?i)(?:https?://)?(?:www\.)?dailymotion\.[a-z]{2,3}/(?:embed/)?video/([^/]+)'
@ -73,6 +77,12 @@ class DailymotionIE(InfoExtractor):
raise ExtractorError(u'Unable to extract video URL') raise ExtractorError(u'Unable to extract video URL')
video_url = info[max_quality] video_url = info[max_quality]
# subtitles
video_subtitles = self.extract_subtitles(video_id)
if self._downloader.params.get('listsubtitles', False):
self._list_available_subtitles(video_id)
return
return [{ return [{
'id': video_id, 'id': video_id,
'url': video_url, 'url': video_url,
@ -80,9 +90,25 @@ class DailymotionIE(InfoExtractor):
'upload_date': video_upload_date, 'upload_date': video_upload_date,
'title': self._og_search_title(webpage), 'title': self._og_search_title(webpage),
'ext': video_extension, 'ext': video_extension,
'subtitles': video_subtitles,
'thumbnail': info['thumbnail_url'] 'thumbnail': info['thumbnail_url']
}] }]
def _get_available_subtitles(self, video_id):
try:
sub_list = self._download_webpage(
'https://api.dailymotion.com/video/%s/subtitles?fields=id,language,url' % video_id,
video_id, note=False)
except ExtractorError as err:
self._downloader.report_warning(u'unable to download video subtitles: %s' % compat_str(err))
return {}
info = json.loads(sub_list)
if (info['total'] > 0):
sub_lang_list = dict((l['language'], l['url']) for l in info['list'])
return sub_lang_list
self._downloader.report_warning(u'video doesn\'t have subtitles')
return {}
class DailymotionPlaylistIE(InfoExtractor): class DailymotionPlaylistIE(InfoExtractor):
_VALID_URL = r'(?:https?://)?(?:www\.)?dailymotion\.[a-z]{2,3}/playlist/(?P<id>.+?)/' _VALID_URL = r'(?:https?://)?(?:www\.)?dailymotion\.[a-z]{2,3}/playlist/(?P<id>.+?)/'

View File

@ -0,0 +1,86 @@
from .common import InfoExtractor
from ..utils import (
compat_str,
ExtractorError,
)
class SubtitlesInfoExtractor(InfoExtractor):
def _list_available_subtitles(self, video_id):
""" outputs the available subtitles for the video """
sub_lang_list = self._get_available_subtitles(video_id)
sub_lang = ",".join(list(sub_lang_list.keys()))
self.to_screen(u'%s: Available subtitles for video: %s' %
(video_id, sub_lang))
def _extract_subtitles(self, video_id):
""" returns {sub_lang: sub} or {} if subtitles not found """
available_subs_list = self._get_available_subtitles(video_id)
if not available_subs_list: # error, it didn't get the available subtitles
return {}
if self._downloader.params.get('allsubtitles', False):
sub_lang_list = available_subs_list
else:
if self._downloader.params.get('writesubtitles', False):
if self._downloader.params.get('subtitleslangs', False):
requested_langs = self._downloader.params.get('subtitleslangs')
elif 'en' in available_subs_list:
requested_langs = ['en']
else:
requested_langs = [list(available_subs_list.keys())[0]]
sub_lang_list = {}
for sub_lang in requested_langs:
if not sub_lang in available_subs_list:
self._downloader.report_warning(u'no closed captions found in the specified language "%s"' % sub_lang)
continue
sub_lang_list[sub_lang] = available_subs_list[sub_lang]
subtitles = {}
for sub_lang, url in sub_lang_list.items():
subtitle = self._request_subtitle_url(sub_lang, url)
if subtitle:
subtitles[sub_lang] = subtitle
return subtitles
def _request_subtitle_url(self, sub_lang, url):
""" makes the http request for the subtitle """
try:
sub = self._download_webpage(url, None, note=False)
except ExtractorError as err:
self._downloader.report_warning(u'unable to download video subtitles for %s: %s' % (sub_lang, compat_str(err)))
return
if not sub:
self._downloader.report_warning(u'Did not fetch video subtitles')
return
return sub
def _get_available_subtitles(self, video_id):
"""
returns {sub_lang: url} or {} if not available
Must be redefined by the subclasses
"""
pass
def _request_automatic_caption(self, video_id, webpage):
"""
returns {sub_lang: sub} or {} if not available
Must be redefined by the subclasses that support automatic captions,
otherwise it will return {}
"""
self._downloader.report_warning(u'Automatic Captions not supported by this server')
return {}
def extract_subtitles(self, video_id, video_webpage=None):
"""
Extract the subtitles and/or the automatic captions if requested.
Returns None or a dictionary in the format {sub_lang: sub}
"""
video_subtitles = None
if self._downloader.params.get('writesubtitles', False) or self._downloader.params.get('allsubtitles', False):
video_subtitles = self._extract_subtitles(video_id)
elif self._downloader.params.get('writeautomaticsub', False):
video_subtitles = self._request_automatic_caption(video_id, video_webpage)
return video_subtitles

View File

@ -7,6 +7,7 @@ import socket
import itertools import itertools
from .common import InfoExtractor, SearchInfoExtractor from .common import InfoExtractor, SearchInfoExtractor
from .subtitles import SubtitlesInfoExtractor
from ..utils import ( from ..utils import (
compat_http_client, compat_http_client,
compat_parse_qs, compat_parse_qs,
@ -130,7 +131,8 @@ class YoutubeBaseInfoExtractor(InfoExtractor):
return return
self._confirm_age() self._confirm_age()
class YoutubeIE(YoutubeBaseInfoExtractor):
class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor):
IE_DESC = u'YouTube.com' IE_DESC = u'YouTube.com'
_VALID_URL = r"""^ _VALID_URL = r"""^
( (
@ -397,19 +399,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
"""Report attempt to download video info webpage.""" """Report attempt to download video info webpage."""
self.to_screen(u'%s: Downloading video info webpage' % video_id) self.to_screen(u'%s: Downloading video info webpage' % video_id)
def report_video_subtitles_download(self, video_id):
"""Report attempt to download video info webpage."""
self.to_screen(u'%s: Checking available subtitles' % video_id)
def report_video_subtitles_request(self, video_id, sub_lang, format):
"""Report attempt to download video info webpage."""
self.to_screen(u'%s: Downloading video subtitles for %s.%s' % (video_id, sub_lang, format))
def report_video_subtitles_available(self, video_id, sub_lang_list):
"""Report available subtitles."""
sub_lang = ",".join(list(sub_lang_list.keys()))
self.to_screen(u'%s: Available subtitles for video: %s' % (video_id, sub_lang))
def report_information_extraction(self, video_id): def report_information_extraction(self, video_id):
"""Report attempt to extract video information.""" """Report attempt to extract video information."""
self.to_screen(u'%s: Extracting video information' % video_id) self.to_screen(u'%s: Extracting video information' % video_id)
@ -464,48 +453,31 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
# Fallback to the other algortihms # Fallback to the other algortihms
return self._decrypt_signature(s) return self._decrypt_signature(s)
def _get_available_subtitles(self, video_id): def _get_available_subtitles(self, video_id):
self.report_video_subtitles_download(video_id)
request = compat_urllib_request.Request('http://video.google.com/timedtext?hl=en&type=list&v=%s' % video_id)
try: try:
sub_list = compat_urllib_request.urlopen(request).read().decode('utf-8') sub_list = self._download_webpage(
except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: 'http://video.google.com/timedtext?hl=en&type=list&v=%s' % video_id,
video_id, note=False)
except ExtractorError as err:
self._downloader.report_warning(u'unable to download video subtitles: %s' % compat_str(err)) self._downloader.report_warning(u'unable to download video subtitles: %s' % compat_str(err))
return {} return {}
sub_lang_list = re.findall(r'name="([^"]*)"[^>]+lang_code="([\w\-]+)"', sub_list) lang_list = re.findall(r'name="([^"]*)"[^>]+lang_code="([\w\-]+)"', sub_list)
sub_lang_list = dict((l[1], l[0]) for l in sub_lang_list)
sub_lang_list = {}
for l in lang_list:
lang = l[1]
params = compat_urllib_parse.urlencode({
'lang': lang,
'v': video_id,
'fmt': self._downloader.params.get('subtitlesformat'),
})
url = u'http://www.youtube.com/api/timedtext?' + params
sub_lang_list[lang] = url
if not sub_lang_list: if not sub_lang_list:
self._downloader.report_warning(u'video doesn\'t have subtitles') self._downloader.report_warning(u'video doesn\'t have subtitles')
return {} return {}
return sub_lang_list return sub_lang_list
def _list_available_subtitles(self, video_id):
sub_lang_list = self._get_available_subtitles(video_id)
self.report_video_subtitles_available(video_id, sub_lang_list)
def _request_subtitle(self, sub_lang, sub_name, video_id, format):
"""
Return the subtitle as a string or None if they are not found
"""
self.report_video_subtitles_request(video_id, sub_lang, format)
params = compat_urllib_parse.urlencode({
'lang': sub_lang,
'name': sub_name,
'v': video_id,
'fmt': format,
})
url = 'http://www.youtube.com/api/timedtext?' + params
try:
sub = compat_urllib_request.urlopen(url).read().decode('utf-8')
except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err:
self._downloader.report_warning(u'unable to download video subtitles for %s: %s' % (sub_lang, compat_str(err)))
return
if not sub:
self._downloader.report_warning(u'Did not fetch video subtitles')
return
return sub
def _request_automatic_caption(self, video_id, webpage): def _request_automatic_caption(self, video_id, webpage):
"""We need the webpage for getting the captions url, pass it as an """We need the webpage for getting the captions url, pass it as an
argument to speed up the process.""" argument to speed up the process."""
@ -538,38 +510,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
self._downloader.report_warning(err_msg) self._downloader.report_warning(err_msg)
return {} return {}
def _extract_subtitles(self, video_id):
"""
Return a dictionary: {language: subtitles} or {} if the subtitles
couldn't be found
"""
available_subs_list = self._get_available_subtitles(video_id)
sub_format = self._downloader.params.get('subtitlesformat')
if not available_subs_list: #There was some error, it didn't get the available subtitles
return {}
if self._downloader.params.get('allsubtitles', False):
sub_lang_list = available_subs_list
else:
if self._downloader.params.get('subtitleslangs', False):
reqested_langs = self._downloader.params.get('subtitleslangs')
elif 'en' in available_subs_list:
reqested_langs = ['en']
else:
reqested_langs = [list(available_subs_list.keys())[0]]
sub_lang_list = {}
for sub_lang in reqested_langs:
if not sub_lang in available_subs_list:
self._downloader.report_warning(u'no closed captions found in the specified language "%s"' % sub_lang)
continue
sub_lang_list[sub_lang] = available_subs_list[sub_lang]
subtitles = {}
for sub_lang in sub_lang_list:
subtitle = self._request_subtitle(sub_lang, sub_lang_list[sub_lang].encode('utf-8'), video_id, sub_format)
if subtitle:
subtitles[sub_lang] = subtitle
return subtitles
def _print_formats(self, formats): def _print_formats(self, formats):
print('Available formats:') print('Available formats:')
for x in formats: for x in formats:
@ -768,12 +708,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
video_description = u'' video_description = u''
# subtitles # subtitles
video_subtitles = None video_subtitles = self.extract_subtitles(video_id, video_webpage)
if self._downloader.params.get('writesubtitles', False) or self._downloader.params.get('allsubtitles', False):
video_subtitles = self._extract_subtitles(video_id)
elif self._downloader.params.get('writeautomaticsub', False):
video_subtitles = self._request_automatic_caption(video_id, video_webpage)
if self._downloader.params.get('listsubtitles', False): if self._downloader.params.get('listsubtitles', False):
self._list_available_subtitles(video_id) self._list_available_subtitles(video_id)