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',
64 'rtmp_ffmpeg': 'rtmpF',
65 'http_dash_segments': 'dash',
66 'http_dash_segments_generator': 'dashG',
67 'niconico_dmc': 'dmc',
68 'websocket_frag': 'WSfrag',
71 short_protocol_names
.update({
74 'm3u8': 'm3u8', # Reverse above m3u8 mapping
75 'm3u8_native': 'm3u8',
76 'http_dash_segments_generator': 'dash',
77 'rtmp_ffmpeg': 'rtmp',
78 'm3u8_frag_urls': 'm3u8',
79 'dash_frag_urls': 'dash',
81 return short_protocol_names
.get(proto
, proto
)
84 def _get_suitable_downloader(info_dict
, protocol
, params
, default
):
85 """Get the downloader class that can handle the info dict."""
86 if default
is NO_DEFAULT
:
89 if (info_dict
.get('section_start') or info_dict
.get('section_end')) and FFmpegFD
.can_download(info_dict
):
92 info_dict
['protocol'] = protocol
93 downloaders
= params
.get('external_downloader')
94 external_downloader
= (
95 downloaders
if isinstance(downloaders
, str) or downloaders
is None
96 else downloaders
.get(shorten_protocol_name(protocol
, True), downloaders
.get('default')))
98 if external_downloader
is None:
99 if info_dict
['to_stdout'] and FFmpegFD
.can_merge_formats(info_dict
, params
):
101 elif external_downloader
.lower() != 'native':
102 ed
= get_external_downloader(external_downloader
)
103 if ed
.can_download(info_dict
, external_downloader
):
106 if protocol
== 'http_dash_segments':
107 if info_dict
.get('is_live') and (external_downloader
or '').lower() != 'native':
110 if protocol
in ('m3u8', 'm3u8_native'):
111 if info_dict
.get('is_live'):
113 elif (external_downloader
or '').lower() == 'native':
115 elif protocol
== 'm3u8_native' and get_suitable_downloader(
116 info_dict
, params
, None, protocol
='m3u8_frag_urls', to_stdout
=info_dict
['to_stdout']):
118 elif params
.get('hls_prefer_native') is True:
120 elif params
.get('hls_prefer_native') is False:
123 return PROTOCOL_MAP
.get(protocol
, default
)
128 'get_suitable_downloader',
129 'shorten_protocol_name',