1
0
Fork 0

[downloader] Allow streaming unmerged formats to stdout using ffmpeg

For this to work:
1. The downloader must be ffmpeg
2. The selected formats must have the same protocol
3. The formats must be downloadable by ffmpeg to stdout

Partial solution for: https://github.com/ytdl-org/youtube-dl/issues/28146, https://github.com/ytdl-org/youtube-dl/issues/27265
This commit is contained in:
pukkandan 2021-07-31 16:23:54 +05:30
commit 96fccc101f
5 changed files with 36 additions and 15 deletions

View file

@ -7,11 +7,12 @@ from ..utils import (
)
def get_suitable_downloader(info_dict, params={}, default=NO_DEFAULT, protocol=None):
def get_suitable_downloader(info_dict, params={}, default=NO_DEFAULT, protocol=None, to_stdout=False):
info_dict['protocol'] = determine_protocol(info_dict)
info_copy = info_dict.copy()
if protocol:
info_copy['protocol'] = protocol
info_copy['to_stdout'] = to_stdout
return _get_suitable_downloader(info_copy, params, default)
@ -84,10 +85,11 @@ def _get_suitable_downloader(info_dict, params, default):
external_downloader = (
downloaders if isinstance(downloaders, compat_str) or downloaders is None
else downloaders.get(shorten_protocol_name(protocol, True), downloaders.get('default')))
if external_downloader and external_downloader.lower() == 'native':
external_downloader = 'native'
if external_downloader not in (None, 'native'):
if external_downloader is None:
if info_dict['to_stdout'] and FFmpegFD.can_merge_formats(info_dict, params):
return FFmpegFD
elif external_downloader.lower() != 'native':
ed = get_external_downloader(external_downloader)
if ed.can_download(info_dict, external_downloader):
return ed
@ -95,9 +97,10 @@ def _get_suitable_downloader(info_dict, params, default):
if protocol in ('m3u8', 'm3u8_native'):
if info_dict.get('is_live'):
return FFmpegFD
elif external_downloader == 'native':
elif (external_downloader or '').lower() == 'native':
return HlsFD
elif get_suitable_downloader(info_dict, params, None, protocol='m3u8_frag_urls'):
elif get_suitable_downloader(
info_dict, params, None, protocol='m3u8_frag_urls', to_stdout=info_dict['to_stdout']):
return HlsFD
elif params.get('hls_prefer_native') is True:
return HlsFD

View file

@ -22,7 +22,8 @@ class DashSegmentsFD(FragmentFD):
fragments = info_dict['fragments'][:1] if self.params.get(
'test', False) else info_dict['fragments']
real_downloader = get_suitable_downloader(info_dict, self.params, None, protocol='dash_frag_urls')
real_downloader = get_suitable_downloader(
info_dict, self.params, None, protocol='dash_frag_urls', to_stdout=(filename== '-'))
ctx = {
'filename': filename,

View file

@ -36,6 +36,7 @@ from ..utils import (
class ExternalFD(FileDownloader):
SUPPORTED_PROTOCOLS = ('http', 'https', 'ftp', 'ftps')
can_download_to_stdout = False
def real_download(self, filename, info_dict):
self.report_destination(filename)
@ -93,7 +94,9 @@ class ExternalFD(FileDownloader):
@classmethod
def supports(cls, info_dict):
return info_dict['protocol'] in cls.SUPPORTED_PROTOCOLS
return (
(cls.can_download_to_stdout or not info_dict.get('to_stdout'))
and info_dict['protocol'] in cls.SUPPORTED_PROTOCOLS)
@classmethod
def can_download(cls, info_dict, path=None):
@ -341,6 +344,7 @@ class HttpieFD(ExternalFD):
class FFmpegFD(ExternalFD):
SUPPORTED_PROTOCOLS = ('http', 'https', 'ftp', 'ftps', 'm3u8', 'm3u8_native', 'rtsp', 'rtmp', 'rtmp_ffmpeg', 'mms')
can_download_to_stdout = True
@classmethod
def available(cls, path=None):

View file

@ -86,7 +86,8 @@ class HlsFD(FragmentFD):
if is_webvtt:
real_downloader = None # Packing the fragments is not currently supported for external downloader
else:
real_downloader = get_suitable_downloader(info_dict, self.params, None, protocol='m3u8_frag_urls')
real_downloader = get_suitable_downloader(
info_dict, self.params, None, protocol='m3u8_frag_urls', to_stdout=(filename== '-'))
if real_downloader and not real_downloader.supports_manifest(s):
real_downloader = None
if real_downloader: