]> jfr.im git - yt-dlp.git/blob - yt_dlp/downloader/__init__.py
Calculate more fields for merged formats
[yt-dlp.git] / yt_dlp / downloader / __init__.py
1 from __future__ import unicode_literals
2
3 from ..compat import compat_str
4 from ..utils import (
5 determine_protocol,
6 NO_DEFAULT
7 )
8
9
10 def get_suitable_downloader(info_dict, params={}, default=NO_DEFAULT, protocol=None, to_stdout=False):
11 info_dict['protocol'] = determine_protocol(info_dict)
12 info_copy = info_dict.copy()
13 if protocol:
14 info_copy['protocol'] = protocol
15 info_copy['to_stdout'] = to_stdout
16 return _get_suitable_downloader(info_copy, params, default)
17
18
19 # Some of these require get_suitable_downloader
20 from .common import FileDownloader
21 from .dash import DashSegmentsFD
22 from .f4m import F4mFD
23 from .hls import HlsFD
24 from .http import HttpFD
25 from .rtmp import RtmpFD
26 from .rtsp import RtspFD
27 from .ism import IsmFD
28 from .mhtml import MhtmlFD
29 from .niconico import NiconicoDmcFD
30 from .websocket import WebSocketFragmentFD
31 from .youtube_live_chat import YoutubeLiveChatFD
32 from .external import (
33 get_external_downloader,
34 FFmpegFD,
35 )
36
37 PROTOCOL_MAP = {
38 'rtmp': RtmpFD,
39 'rtmp_ffmpeg': FFmpegFD,
40 'm3u8_native': HlsFD,
41 'm3u8': FFmpegFD,
42 'mms': RtspFD,
43 'rtsp': RtspFD,
44 'f4m': F4mFD,
45 'http_dash_segments': DashSegmentsFD,
46 'ism': IsmFD,
47 'mhtml': MhtmlFD,
48 'niconico_dmc': NiconicoDmcFD,
49 'websocket_frag': WebSocketFragmentFD,
50 'youtube_live_chat': YoutubeLiveChatFD,
51 'youtube_live_chat_replay': YoutubeLiveChatFD,
52 }
53
54
55 def shorten_protocol_name(proto, simplify=False):
56 short_protocol_names = {
57 'm3u8_native': 'm3u8_n',
58 'rtmp_ffmpeg': 'rtmp_f',
59 'http_dash_segments': 'dash',
60 'niconico_dmc': 'dmc',
61 'websocket_frag': 'WSfrag',
62 }
63 if simplify:
64 short_protocol_names.update({
65 'https': 'http',
66 'ftps': 'ftp',
67 'm3u8_native': 'm3u8',
68 'rtmp_ffmpeg': 'rtmp',
69 'm3u8_frag_urls': 'm3u8',
70 'dash_frag_urls': 'dash',
71 })
72 return short_protocol_names.get(proto, proto)
73
74
75 def _get_suitable_downloader(info_dict, params, default):
76 """Get the downloader class that can handle the info dict."""
77 if default is NO_DEFAULT:
78 default = HttpFD
79
80 # 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):
81 # return FFmpegFD
82
83 protocol = info_dict['protocol']
84 downloaders = params.get('external_downloader')
85 external_downloader = (
86 downloaders if isinstance(downloaders, compat_str) or downloaders is None
87 else downloaders.get(shorten_protocol_name(protocol, True), downloaders.get('default')))
88
89 if external_downloader is None:
90 if info_dict['to_stdout'] and FFmpegFD.can_merge_formats(info_dict, params):
91 return FFmpegFD
92 elif external_downloader.lower() != 'native':
93 ed = get_external_downloader(external_downloader)
94 if ed.can_download(info_dict, external_downloader):
95 return ed
96
97 if protocol == 'http_dash_segments':
98 if info_dict.get('is_live') and (external_downloader or '').lower() != 'native':
99 return FFmpegFD
100
101 if protocol in ('m3u8', 'm3u8_native'):
102 if info_dict.get('is_live'):
103 return FFmpegFD
104 elif (external_downloader or '').lower() == 'native':
105 return HlsFD
106 elif get_suitable_downloader(
107 info_dict, params, None, protocol='m3u8_frag_urls', to_stdout=info_dict['to_stdout']):
108 return HlsFD
109 elif params.get('hls_prefer_native') is True:
110 return HlsFD
111 elif params.get('hls_prefer_native') is False:
112 return FFmpegFD
113
114 return PROTOCOL_MAP.get(protocol, default)
115
116
117 __all__ = [
118 'FileDownloader',
119 'get_suitable_downloader',
120 'shorten_protocol_name',
121 ]