1 from ..utils
import NO_DEFAULT
, determine_protocol
4 def get_suitable_downloader(info_dict
, params
={}, default
=NO_DEFAULT
, protocol
=None, to_stdout
=False):
5 info_dict
['protocol'] = determine_protocol(info_dict
)
6 info_copy
= info_dict
.copy()
7 info_copy
['to_stdout'] = to_stdout
9 protocols
= (protocol
or info_copy
['protocol']).split('+')
10 downloaders
= [_get_suitable_downloader(info_copy
, proto
, params
, default
) for proto
in protocols
]
12 if set(downloaders
) == {FFmpegFD}
and FFmpegFD
.can_merge_formats(info_copy
, params
):
14 elif (set(downloaders
) == {DashSegmentsFD}
15 and not (to_stdout
and len(protocols
) > 1)
16 and set(protocols
) == {'http_dash_segments_generator'}
):
18 elif len(downloaders
) == 1:
23 # Some of these require get_suitable_downloader
24 from .common
import FileDownloader
25 from .dash
import DashSegmentsFD
26 from .external
import FFmpegFD
, get_external_downloader
27 from .f4m
import F4mFD
28 from .fc2
import FC2LiveFD
29 from .hls
import HlsFD
30 from .http
import HttpFD
31 from .ism
import IsmFD
32 from .mhtml
import MhtmlFD
33 from .niconico
import NiconicoDmcFD
34 from .rtmp
import RtmpFD
35 from .rtsp
import RtspFD
36 from .websocket
import WebSocketFragmentFD
37 from .youtube_live_chat
import YoutubeLiveChatFD
42 'rtmp_ffmpeg': FFmpegFD
,
48 'http_dash_segments': DashSegmentsFD
,
49 'http_dash_segments_generator': DashSegmentsFD
,
52 'niconico_dmc': NiconicoDmcFD
,
53 'fc2_live': FC2LiveFD
,
54 'websocket_frag': WebSocketFragmentFD
,
55 'youtube_live_chat': YoutubeLiveChatFD
,
56 'youtube_live_chat_replay': YoutubeLiveChatFD
,
60 def shorten_protocol_name(proto
, simplify
=False):
61 short_protocol_names
= {
62 'm3u8_native': 'm3u8_n',
63 'rtmp_ffmpeg': 'rtmp_f',
64 'http_dash_segments': 'dash',
65 'http_dash_segments_generator': 'dash_g',
66 'niconico_dmc': 'dmc',
67 'websocket_frag': 'WSfrag',
70 short_protocol_names
.update({
73 'm3u8_native': 'm3u8',
74 'http_dash_segments_generator': 'dash',
75 'rtmp_ffmpeg': 'rtmp',
76 'm3u8_frag_urls': 'm3u8',
77 'dash_frag_urls': 'dash',
79 return short_protocol_names
.get(proto
, proto
)
82 def _get_suitable_downloader(info_dict
, protocol
, params
, default
):
83 """Get the downloader class that can handle the info dict."""
84 if default
is NO_DEFAULT
:
87 if (info_dict
.get('section_start') or info_dict
.get('section_end')) and FFmpegFD
.can_download(info_dict
):
90 info_dict
['protocol'] = protocol
91 downloaders
= params
.get('external_downloader')
92 external_downloader
= (
93 downloaders
if isinstance(downloaders
, str) or downloaders
is None
94 else downloaders
.get(shorten_protocol_name(protocol
, True), downloaders
.get('default')))
96 if external_downloader
is None:
97 if info_dict
['to_stdout'] and FFmpegFD
.can_merge_formats(info_dict
, params
):
99 elif external_downloader
.lower() != 'native':
100 ed
= get_external_downloader(external_downloader
)
101 if ed
.can_download(info_dict
, external_downloader
):
104 if protocol
== 'http_dash_segments':
105 if info_dict
.get('is_live') and (external_downloader
or '').lower() != 'native':
108 if protocol
in ('m3u8', 'm3u8_native'):
109 if info_dict
.get('is_live'):
111 elif (external_downloader
or '').lower() == 'native':
113 elif protocol
== 'm3u8_native' and get_suitable_downloader(
114 info_dict
, params
, None, protocol
='m3u8_frag_urls', to_stdout
=info_dict
['to_stdout']):
116 elif params
.get('hls_prefer_native') is True:
118 elif params
.get('hls_prefer_native') is False:
121 return PROTOCOL_MAP
.get(protocol
, default
)
126 'get_suitable_downloader',
127 'shorten_protocol_name',