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