]>
Commit | Line | Data |
---|---|---|
f8271158 | 1 | from ..utils import NO_DEFAULT, determine_protocol |
5219cb3e | 2 | |
3 | ||
96fccc10 | 4 | def get_suitable_downloader(info_dict, params={}, default=NO_DEFAULT, protocol=None, to_stdout=False): |
dbf5416a | 5 | info_dict['protocol'] = determine_protocol(info_dict) |
5219cb3e | 6 | info_copy = info_dict.copy() |
96fccc10 | 7 | info_copy['to_stdout'] = to_stdout |
c111cefa | 8 | |
adbc4ec4 THD |
9 | protocols = (protocol or info_copy['protocol']).split('+') |
10 | downloaders = [_get_suitable_downloader(info_copy, proto, params, default) for proto in protocols] | |
11 | ||
c111cefa | 12 | if set(downloaders) == {FFmpegFD} and FFmpegFD.can_merge_formats(info_copy, params): |
13 | return FFmpegFD | |
adbc4ec4 THD |
14 | elif (set(downloaders) == {DashSegmentsFD} |
15 | and not (to_stdout and len(protocols) > 1) | |
16 | and set(protocols) == {'http_dash_segments_generator'}): | |
17 | return DashSegmentsFD | |
c111cefa | 18 | elif len(downloaders) == 1: |
19 | return downloaders[0] | |
20 | return None | |
5219cb3e | 21 | |
22 | ||
dbf5416a | 23 | # Some of these require get_suitable_downloader |
3bc2ddcc | 24 | from .common import FileDownloader |
5219cb3e | 25 | from .dash import DashSegmentsFD |
f8271158 | 26 | from .external import FFmpegFD, get_external_downloader |
222516d9 | 27 | from .f4m import F4mFD |
15dfb392 | 28 | from .fc2 import FC2LiveFD |
3bc2ddcc JMF |
29 | from .hls import HlsFD |
30 | from .http import HttpFD | |
b2758123 | 31 | from .ism import IsmFD |
cdb19aa4 | 32 | from .mhtml import MhtmlFD |
f8f9250f | 33 | from .niconico import NiconicoDmcFD, NiconicoLiveFD |
f8271158 | 34 | from .rtmp import RtmpFD |
35 | from .rtsp import RtspFD | |
e36d50c5 | 36 | from .websocket import WebSocketFragmentFD |
c60ee3a2 | 37 | from .youtube_live_chat import YoutubeLiveChatFD |
3bc2ddcc | 38 | |
a055469f PH |
39 | PROTOCOL_MAP = { |
40 | 'rtmp': RtmpFD, | |
f304da8a | 41 | 'rtmpe': RtmpFD, |
0fa9a1e2 | 42 | 'rtmp_ffmpeg': FFmpegFD, |
12b84ac8 | 43 | 'm3u8_native': HlsFD, |
44 | 'm3u8': FFmpegFD, | |
be24916a | 45 | 'mms': RtspFD, |
46 | 'rtsp': RtspFD, | |
a055469f | 47 | 'f4m': F4mFD, |
423d2be5 | 48 | 'http_dash_segments': DashSegmentsFD, |
adbc4ec4 | 49 | 'http_dash_segments_generator': DashSegmentsFD, |
b2758123 | 50 | 'ism': IsmFD, |
cdb19aa4 | 51 | 'mhtml': MhtmlFD, |
fb198a8a | 52 | 'niconico_dmc': NiconicoDmcFD, |
f8f9250f | 53 | 'niconico_live': NiconicoLiveFD, |
15dfb392 | 54 | 'fc2_live': FC2LiveFD, |
e36d50c5 | 55 | 'websocket_frag': WebSocketFragmentFD, |
c60ee3a2 | 56 | 'youtube_live_chat': YoutubeLiveChatFD, |
57 | 'youtube_live_chat_replay': YoutubeLiveChatFD, | |
a055469f | 58 | } |
f89197d7 | 59 | |
a055469f | 60 | |
52a8a1e1 | 61 | def shorten_protocol_name(proto, simplify=False): |
62 | short_protocol_names = { | |
ae61d108 | 63 | 'm3u8_native': 'm3u8', |
64 | 'm3u8': 'm3u8F', | |
65 | 'rtmp_ffmpeg': 'rtmpF', | |
52a8a1e1 | 66 | 'http_dash_segments': 'dash', |
ae61d108 | 67 | 'http_dash_segments_generator': 'dashG', |
52a8a1e1 | 68 | 'niconico_dmc': 'dmc', |
e36d50c5 | 69 | 'websocket_frag': 'WSfrag', |
52a8a1e1 | 70 | } |
71 | if simplify: | |
72 | short_protocol_names.update({ | |
73 | 'https': 'http', | |
74 | 'ftps': 'ftp', | |
ae61d108 | 75 | 'm3u8': 'm3u8', # Reverse above m3u8 mapping |
52a8a1e1 | 76 | 'm3u8_native': 'm3u8', |
adbc4ec4 | 77 | 'http_dash_segments_generator': 'dash', |
0fa9a1e2 | 78 | 'rtmp_ffmpeg': 'rtmp', |
52a8a1e1 | 79 | 'm3u8_frag_urls': 'm3u8', |
80 | 'dash_frag_urls': 'dash', | |
81 | }) | |
82 | return short_protocol_names.get(proto, proto) | |
83 | ||
84 | ||
c111cefa | 85 | def _get_suitable_downloader(info_dict, protocol, params, default): |
3bc2ddcc | 86 | """Get the downloader class that can handle the info dict.""" |
dbf5416a | 87 | if default is NO_DEFAULT: |
88 | default = HttpFD | |
a055469f | 89 | |
5ec1b6b7 | 90 | if (info_dict.get('section_start') or info_dict.get('section_end')) and FFmpegFD.can_download(info_dict): |
91 | return FFmpegFD | |
12b84ac8 | 92 | |
c111cefa | 93 | info_dict['protocol'] = protocol |
52a8a1e1 | 94 | downloaders = params.get('external_downloader') |
95 | external_downloader = ( | |
8a82af35 | 96 | downloaders if isinstance(downloaders, str) or downloaders is None |
52a8a1e1 | 97 | else downloaders.get(shorten_protocol_name(protocol, True), downloaders.get('default'))) |
52a8a1e1 | 98 | |
96fccc10 | 99 | if external_downloader is None: |
100 | if info_dict['to_stdout'] and FFmpegFD.can_merge_formats(info_dict, params): | |
101 | return FFmpegFD | |
102 | elif external_downloader.lower() != 'native': | |
222516d9 | 103 | ed = get_external_downloader(external_downloader) |
7f7de7f9 | 104 | if ed.can_download(info_dict, external_downloader): |
222516d9 PH |
105 | return ed |
106 | ||
6251555f | 107 | if protocol == 'http_dash_segments': |
45842107 | 108 | if info_dict.get('is_live') and (external_downloader or '').lower() != 'native': |
6251555f | 109 | return FFmpegFD |
110 | ||
72e1fe96 | 111 | if protocol in ('m3u8', 'm3u8_native'): |
5219cb3e | 112 | if info_dict.get('is_live'): |
113 | return FFmpegFD | |
96fccc10 | 114 | elif (external_downloader or '').lower() == 'native': |
52a8a1e1 | 115 | return HlsFD |
079a7cfc | 116 | elif protocol == 'm3u8_native' and get_suitable_downloader( |
96fccc10 | 117 | info_dict, params, None, protocol='m3u8_frag_urls', to_stdout=info_dict['to_stdout']): |
5219cb3e | 118 | return HlsFD |
119 | elif params.get('hls_prefer_native') is True: | |
120 | return HlsFD | |
121 | elif params.get('hls_prefer_native') is False: | |
122 | return FFmpegFD | |
bf09af3a | 123 | |
5219cb3e | 124 | return PROTOCOL_MAP.get(protocol, default) |
a055469f | 125 | |
14d4e90e PH |
126 | |
127 | __all__ = [ | |
14d4e90e | 128 | 'FileDownloader', |
52a8a1e1 | 129 | 'get_suitable_downloader', |
130 | 'shorten_protocol_name', | |
14d4e90e | 131 | ] |