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