Merge branch 'subtitles_rework' (closes PR #1326)
[youtube-dl] / youtube_dl / extractor / subtitles.py
1 from .common import InfoExtractor
2
3 from ..utils import (
4     compat_str,
5     ExtractorError,
6 )
7
8
9 class SubtitlesInfoExtractor(InfoExtractor):
10
11     def _list_available_subtitles(self, video_id):
12         """ outputs the available subtitles for the video """
13         sub_lang_list = self._get_available_subtitles(video_id)
14         sub_lang = ",".join(list(sub_lang_list.keys()))
15         self.to_screen(u'%s: Available subtitles for video: %s' %
16                        (video_id, sub_lang))
17
18     def _extract_subtitles(self, video_id):
19         """ returns {sub_lang: sub} or {} if subtitles not found """
20         available_subs_list = self._get_available_subtitles(video_id)
21         if not available_subs_list:  # error, it didn't get the available subtitles
22             return {}
23         if self._downloader.params.get('allsubtitles', False):
24             sub_lang_list = available_subs_list
25         else:
26             if self._downloader.params.get('writesubtitles', False):
27                 if self._downloader.params.get('subtitleslangs', False):
28                     requested_langs = self._downloader.params.get('subtitleslangs')
29                 elif 'en' in available_subs_list:
30                     requested_langs = ['en']
31                 else:
32                     requested_langs = [list(available_subs_list.keys())[0]]
33
34                 sub_lang_list = {}
35                 for sub_lang in requested_langs:
36                     if not sub_lang in available_subs_list:
37                         self._downloader.report_warning(u'no closed captions found in the specified language "%s"' % sub_lang)
38                         continue
39                     sub_lang_list[sub_lang] = available_subs_list[sub_lang]
40
41         subtitles = {}
42         for sub_lang, url in sub_lang_list.items():
43             subtitle = self._request_subtitle_url(sub_lang, url)
44             if subtitle:
45                 subtitles[sub_lang] = subtitle
46         return subtitles
47
48     def _request_subtitle_url(self, sub_lang, url):
49         """ makes the http request for the subtitle """
50         try:
51             sub = self._download_webpage(url, None, note=False)
52         except ExtractorError as err:
53             self._downloader.report_warning(u'unable to download video subtitles for %s: %s' % (sub_lang, compat_str(err)))
54             return
55         if not sub:
56             self._downloader.report_warning(u'Did not fetch video subtitles')
57             return
58         return sub
59
60     def _get_available_subtitles(self, video_id):
61         """
62         returns {sub_lang: url} or {} if not available
63         Must be redefined by the subclasses
64         """
65         pass
66
67     def _request_automatic_caption(self, video_id, webpage):
68         """
69         returns {sub_lang: sub} or {} if not available
70         Must be redefined by the subclasses that support automatic captions,
71         otherwise it will return {}
72         """
73         self._downloader.report_warning(u'Automatic Captions not supported by this server')
74         return {}
75
76     def extract_subtitles(self, video_id, video_webpage=None):
77         """
78         Extract the subtitles and/or the automatic captions if requested.
79         Returns None or a dictionary in the format {sub_lang: sub}
80         """
81         video_subtitles = None
82         if self._downloader.params.get('writesubtitles', False) or self._downloader.params.get('allsubtitles', False):
83             video_subtitles = self._extract_subtitles(video_id)
84         elif self._downloader.params.get('writeautomaticsub', False):
85             video_subtitles = self._request_automatic_caption(video_id, video_webpage)
86         return video_subtitles