]> jfr.im git - yt-dlp.git/blob - yt_dlp/downloader/__init__.py
Option to choose different downloader for different protocols
[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 )
7
8
9 def _get_real_downloader(info_dict, protocol=None, *args, **kwargs):
10 info_copy = info_dict.copy()
11 if protocol:
12 info_copy['protocol'] = protocol
13 return get_suitable_downloader(info_copy, *args, **kwargs)
14
15
16 # Some of these require _get_real_downloader
17 from .common import FileDownloader
18 from .dash import DashSegmentsFD
19 from .f4m import F4mFD
20 from .hls import HlsFD
21 from .http import HttpFD
22 from .rtmp import RtmpFD
23 from .rtsp import RtspFD
24 from .ism import IsmFD
25 from .niconico import NiconicoDmcFD
26 from .youtube_live_chat import YoutubeLiveChatReplayFD
27 from .external import (
28 get_external_downloader,
29 FFmpegFD,
30 )
31
32 PROTOCOL_MAP = {
33 'rtmp': RtmpFD,
34 'm3u8_native': HlsFD,
35 'm3u8': FFmpegFD,
36 'mms': RtspFD,
37 'rtsp': RtspFD,
38 'f4m': F4mFD,
39 'http_dash_segments': DashSegmentsFD,
40 'ism': IsmFD,
41 'niconico_dmc': NiconicoDmcFD,
42 'youtube_live_chat_replay': YoutubeLiveChatReplayFD,
43 }
44
45
46 def shorten_protocol_name(proto, simplify=False):
47 short_protocol_names = {
48 'm3u8_native': 'm3u8_n',
49 'http_dash_segments': 'dash',
50 'niconico_dmc': 'dmc',
51 }
52 if simplify:
53 short_protocol_names.update({
54 'https': 'http',
55 'ftps': 'ftp',
56 'm3u8_native': 'm3u8',
57 'm3u8_frag_urls': 'm3u8',
58 'dash_frag_urls': 'dash',
59 })
60 return short_protocol_names.get(proto, proto)
61
62
63 def get_suitable_downloader(info_dict, params={}, default=HttpFD):
64 """Get the downloader class that can handle the info dict."""
65 protocol = determine_protocol(info_dict)
66 info_dict['protocol'] = protocol
67
68 # 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):
69 # return FFmpegFD
70
71 downloaders = params.get('external_downloader')
72 external_downloader = (
73 downloaders if isinstance(downloaders, compat_str)
74 else downloaders.get(shorten_protocol_name(protocol, True), downloaders.get('default')))
75 if external_downloader and external_downloader.lower() == 'native':
76 external_downloader = 'native'
77
78 if external_downloader not in (None, 'native'):
79 ed = get_external_downloader(external_downloader)
80 if ed.can_download(info_dict, external_downloader):
81 return ed
82
83 if protocol.startswith('m3u8'):
84 if info_dict.get('is_live'):
85 return FFmpegFD
86 elif external_downloader == 'native':
87 return HlsFD
88 elif _get_real_downloader(info_dict, 'frag_urls', params, None):
89 return HlsFD
90 elif params.get('hls_prefer_native') is True:
91 return HlsFD
92 elif params.get('hls_prefer_native') is False:
93 return FFmpegFD
94
95 return PROTOCOL_MAP.get(protocol, default)
96
97
98 __all__ = [
99 'FileDownloader',
100 'get_suitable_downloader',
101 'shorten_protocol_name',
102 ]