1 from ..compat
import compat_str
2 from ..utils
import NO_DEFAULT
, determine_protocol
5 def get_suitable_downloader(info_dict
, params
={}, default
=NO_DEFAULT
, protocol
=None, to_stdout
=False):
6 info_dict
['protocol'] = determine_protocol(info_dict
)
7 info_copy
= info_dict
.copy()
8 info_copy
['to_stdout'] = to_stdout
10 protocols
= (protocol
or info_copy
['protocol']).split('+')
11 downloaders
= [_get_suitable_downloader(info_copy
, proto
, params
, default
) for proto
in protocols
]
13 if set(downloaders
) == {FFmpegFD}
and FFmpegFD
.can_merge_formats(info_copy
, params
):
15 elif (set(downloaders
) == {DashSegmentsFD}
16 and not (to_stdout
and len(protocols
) > 1)
17 and set(protocols
) == {'http_dash_segments_generator'}
):
19 elif len(downloaders
) == 1:
24 # Some of these require get_suitable_downloader
25 from .common
import FileDownloader
26 from .dash
import DashSegmentsFD
27 from .external
import FFmpegFD
, get_external_downloader
28 from .f4m
import F4mFD
29 from .fc2
import FC2LiveFD
30 from .hls
import HlsFD
31 from .http
import HttpFD
32 from .ism
import IsmFD
33 from .mhtml
import MhtmlFD
34 from .niconico
import NiconicoDmcFD
35 from .rtmp
import RtmpFD
36 from .rtsp
import RtspFD
37 from .websocket
import WebSocketFragmentFD
38 from .youtube_live_chat
import YoutubeLiveChatFD
43 'rtmp_ffmpeg': FFmpegFD
,
49 'http_dash_segments': DashSegmentsFD
,
50 'http_dash_segments_generator': DashSegmentsFD
,
53 'niconico_dmc': NiconicoDmcFD
,
54 'fc2_live': FC2LiveFD
,
55 'websocket_frag': WebSocketFragmentFD
,
56 'youtube_live_chat': YoutubeLiveChatFD
,
57 'youtube_live_chat_replay': YoutubeLiveChatFD
,
61 def shorten_protocol_name(proto
, simplify
=False):
62 short_protocol_names
= {
63 'm3u8_native': 'm3u8_n',
64 'rtmp_ffmpeg': 'rtmp_f',
65 'http_dash_segments': 'dash',
66 'http_dash_segments_generator': 'dash_g',
67 'niconico_dmc': 'dmc',
68 'websocket_frag': 'WSfrag',
71 short_protocol_names
.update({
74 'm3u8_native': 'm3u8',
75 'http_dash_segments_generator': 'dash',
76 'rtmp_ffmpeg': 'rtmp',
77 'm3u8_frag_urls': 'm3u8',
78 'dash_frag_urls': 'dash',
80 return short_protocol_names
.get(proto
, proto
)
83 def _get_suitable_downloader(info_dict
, protocol
, params
, default
):
84 """Get the downloader class that can handle the info dict."""
85 if default
is NO_DEFAULT
:
88 # if (info_dict.get('start_time') or info_dict.get('end_time')) and not info_dict.get('requested_formats') and FFmpegFD.can_download(info_dict):
91 info_dict
['protocol'] = protocol
92 downloaders
= params
.get('external_downloader')
93 external_downloader
= (
94 downloaders
if isinstance(downloaders
, compat_str
) or downloaders
is None
95 else downloaders
.get(shorten_protocol_name(protocol
, True), downloaders
.get('default')))
97 if external_downloader
is None:
98 if info_dict
['to_stdout'] and FFmpegFD
.can_merge_formats(info_dict
, params
):
100 elif external_downloader
.lower() != 'native':
101 ed
= get_external_downloader(external_downloader
)
102 if ed
.can_download(info_dict
, external_downloader
):
105 if protocol
== 'http_dash_segments':
106 if info_dict
.get('is_live') and (external_downloader
or '').lower() != 'native':
109 if protocol
in ('m3u8', 'm3u8_native'):
110 if info_dict
.get('is_live'):
112 elif (external_downloader
or '').lower() == 'native':
114 elif protocol
== 'm3u8_native' and get_suitable_downloader(
115 info_dict
, params
, None, protocol
='m3u8_frag_urls', to_stdout
=info_dict
['to_stdout']):
117 elif params
.get('hls_prefer_native') is True:
119 elif params
.get('hls_prefer_native') is False:
122 return PROTOCOL_MAP
.get(protocol
, default
)
127 'get_suitable_downloader',
128 'shorten_protocol_name',