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