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
, NiconicoLiveFD
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 'niconico_live': NiconicoLiveFD
,
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',
65 'rtmp_ffmpeg': 'rtmpF',
66 'http_dash_segments': 'dash',
67 'http_dash_segments_generator': 'dashG',
68 'niconico_dmc': 'dmc',
69 'websocket_frag': 'WSfrag',
72 short_protocol_names
.update({
75 'm3u8': 'm3u8', # Reverse above m3u8 mapping
76 'm3u8_native': 'm3u8',
77 'http_dash_segments_generator': 'dash',
78 'rtmp_ffmpeg': 'rtmp',
79 'm3u8_frag_urls': 'm3u8',
80 'dash_frag_urls': 'dash',
82 return short_protocol_names
.get(proto
, proto
)
85 def _get_suitable_downloader(info_dict
, protocol
, params
, default
):
86 """Get the downloader class that can handle the info dict."""
87 if default
is NO_DEFAULT
:
90 if (info_dict
.get('section_start') or info_dict
.get('section_end')) and FFmpegFD
.can_download(info_dict
):
93 info_dict
['protocol'] = protocol
94 downloaders
= params
.get('external_downloader')
95 external_downloader
= (
96 downloaders
if isinstance(downloaders
, str) or downloaders
is None
97 else downloaders
.get(shorten_protocol_name(protocol
, True), downloaders
.get('default')))
99 if external_downloader
is None:
100 if info_dict
['to_stdout'] and FFmpegFD
.can_merge_formats(info_dict
, params
):
102 elif external_downloader
.lower() != 'native':
103 ed
= get_external_downloader(external_downloader
)
104 if ed
.can_download(info_dict
, external_downloader
):
107 if protocol
== 'http_dash_segments':
108 if info_dict
.get('is_live') and (external_downloader
or '').lower() != 'native':
111 if protocol
in ('m3u8', 'm3u8_native'):
112 if info_dict
.get('is_live'):
114 elif (external_downloader
or '').lower() == 'native':
116 elif protocol
== 'm3u8_native' and get_suitable_downloader(
117 info_dict
, params
, None, protocol
='m3u8_frag_urls', to_stdout
=info_dict
['to_stdout']):
119 elif params
.get('hls_prefer_native') is True:
121 elif params
.get('hls_prefer_native') is False:
124 return PROTOCOL_MAP
.get(protocol
, default
)
129 'get_suitable_downloader',
130 'shorten_protocol_name',