]> jfr.im git - yt-dlp.git/blame - yt_dlp/downloader/__init__.py
Add option `--download-sections` to download video partially
[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
fb198a8a 33from .niconico import NiconicoDmcFD
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,
15dfb392 53 'fc2_live': FC2LiveFD,
e36d50c5 54 'websocket_frag': WebSocketFragmentFD,
c60ee3a2 55 'youtube_live_chat': YoutubeLiveChatFD,
56 'youtube_live_chat_replay': YoutubeLiveChatFD,
a055469f 57}
f89197d7 58
a055469f 59
52a8a1e1 60def shorten_protocol_name(proto, simplify=False):
61 short_protocol_names = {
62 'm3u8_native': 'm3u8_n',
0fa9a1e2 63 'rtmp_ffmpeg': 'rtmp_f',
52a8a1e1 64 'http_dash_segments': 'dash',
adbc4ec4 65 'http_dash_segments_generator': 'dash_g',
52a8a1e1 66 'niconico_dmc': 'dmc',
e36d50c5 67 'websocket_frag': 'WSfrag',
52a8a1e1 68 }
69 if simplify:
70 short_protocol_names.update({
71 'https': 'http',
72 'ftps': 'ftp',
73 'm3u8_native': 'm3u8',
adbc4ec4 74 'http_dash_segments_generator': 'dash',
0fa9a1e2 75 'rtmp_ffmpeg': 'rtmp',
52a8a1e1 76 'm3u8_frag_urls': 'm3u8',
77 'dash_frag_urls': 'dash',
78 })
79 return short_protocol_names.get(proto, proto)
80
81
c111cefa 82def _get_suitable_downloader(info_dict, protocol, params, default):
3bc2ddcc 83 """Get the downloader class that can handle the info dict."""
dbf5416a 84 if default is NO_DEFAULT:
85 default = HttpFD
a055469f 86
5ec1b6b7 87 if (info_dict.get('section_start') or info_dict.get('section_end')) and FFmpegFD.can_download(info_dict):
88 return FFmpegFD
12b84ac8 89
c111cefa 90 info_dict['protocol'] = protocol
52a8a1e1 91 downloaders = params.get('external_downloader')
92 external_downloader = (
8a82af35 93 downloaders if isinstance(downloaders, str) or downloaders is None
52a8a1e1 94 else downloaders.get(shorten_protocol_name(protocol, True), downloaders.get('default')))
52a8a1e1 95
96fccc10 96 if external_downloader is None:
97 if info_dict['to_stdout'] and FFmpegFD.can_merge_formats(info_dict, params):
98 return FFmpegFD
99 elif external_downloader.lower() != 'native':
222516d9 100 ed = get_external_downloader(external_downloader)
7f7de7f9 101 if ed.can_download(info_dict, external_downloader):
222516d9
PH
102 return ed
103
6251555f 104 if protocol == 'http_dash_segments':
45842107 105 if info_dict.get('is_live') and (external_downloader or '').lower() != 'native':
6251555f 106 return FFmpegFD
107
72e1fe96 108 if protocol in ('m3u8', 'm3u8_native'):
5219cb3e 109 if info_dict.get('is_live'):
110 return FFmpegFD
96fccc10 111 elif (external_downloader or '').lower() == 'native':
52a8a1e1 112 return HlsFD
079a7cfc 113 elif protocol == 'm3u8_native' and get_suitable_downloader(
96fccc10 114 info_dict, params, None, protocol='m3u8_frag_urls', to_stdout=info_dict['to_stdout']):
5219cb3e 115 return HlsFD
116 elif params.get('hls_prefer_native') is True:
117 return HlsFD
118 elif params.get('hls_prefer_native') is False:
119 return FFmpegFD
bf09af3a 120
5219cb3e 121 return PROTOCOL_MAP.get(protocol, default)
a055469f 122
14d4e90e
PH
123
124__all__ = [
14d4e90e 125 'FileDownloader',
52a8a1e1 126 'get_suitable_downloader',
127 'shorten_protocol_name',
14d4e90e 128]