kopia lustrzana https://github.com/yt-dlp/yt-dlp
				
				
				
			[cleanup] Deprecate various options (#13821)
Closes #14198, Closes #12909 Authored by: seproDevpull/14268/head
							rodzic
							
								
									98b6b0d339
								
							
						
					
					
						commit
						08d7899683
					
				
							
								
								
									
										24
									
								
								README.md
								
								
								
								
							
							
						
						
									
										24
									
								
								README.md
								
								
								
								
							| 
						 | 
				
			
			@ -241,8 +241,6 @@ The following provide support for impersonating browser requests. This may be re
 | 
			
		|||
 | 
			
		||||
### Deprecated
 | 
			
		||||
 | 
			
		||||
* [**avconv** and **avprobe**](https://www.libav.org) - Now **deprecated** alternative to ffmpeg. License [depends on the build](https://libav.org/legal)
 | 
			
		||||
* [**sponskrub**](https://github.com/faissaloo/SponSkrub) - For using the now **deprecated** [sponskrub options](#sponskrub-options). Licensed under [GPLv3+](https://github.com/faissaloo/SponSkrub/blob/master/LICENCE.md)
 | 
			
		||||
* [**rtmpdump**](http://rtmpdump.mplayerhq.hu) - For downloading `rtmp` streams. ffmpeg can be used instead with `--downloader ffmpeg`. Licensed under [GPLv2+](http://rtmpdump.mplayerhq.hu)
 | 
			
		||||
* [**mplayer**](http://mplayerhq.hu/design7/info.html) or [**mpv**](https://mpv.io) - For downloading `rstp`/`mms` streams. ffmpeg can be used instead with `--downloader ffmpeg`. Licensed under [GPLv2+](https://github.com/mpv-player/mpv/blob/master/Copyright)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2363,10 +2361,6 @@ While these options still work, their use is not recommended since there are oth
 | 
			
		|||
    --hls-prefer-ffmpeg              --downloader "m3u8:ffmpeg"
 | 
			
		||||
    --list-formats-old               --compat-options list-formats (Alias: --no-list-formats-as-table)
 | 
			
		||||
    --list-formats-as-table          --compat-options -list-formats [Default] (Alias: --no-list-formats-old)
 | 
			
		||||
    --youtube-skip-dash-manifest     --extractor-args "youtube:skip=dash" (Alias: --no-youtube-include-dash-manifest)
 | 
			
		||||
    --youtube-skip-hls-manifest      --extractor-args "youtube:skip=hls" (Alias: --no-youtube-include-hls-manifest)
 | 
			
		||||
    --youtube-include-dash-manifest  Default (Alias: --no-youtube-skip-dash-manifest)
 | 
			
		||||
    --youtube-include-hls-manifest   Default (Alias: --no-youtube-skip-hls-manifest)
 | 
			
		||||
    --geo-bypass                     --xff "default"
 | 
			
		||||
    --no-geo-bypass                  --xff "never"
 | 
			
		||||
    --geo-bypass-country CODE        --xff CODE
 | 
			
		||||
| 
						 | 
				
			
			@ -2377,18 +2371,13 @@ These options are not intended to be used by the end-user
 | 
			
		|||
 | 
			
		||||
    --test                           Download only part of video for testing extractors
 | 
			
		||||
    --load-pages                     Load pages dumped by --write-pages
 | 
			
		||||
    --youtube-print-sig-code         For testing youtube signatures
 | 
			
		||||
    --allow-unplayable-formats       List unplayable formats also
 | 
			
		||||
    --no-allow-unplayable-formats    Default
 | 
			
		||||
 | 
			
		||||
#### Old aliases
 | 
			
		||||
These are aliases that are no longer documented for various reasons
 | 
			
		||||
 | 
			
		||||
    --avconv-location                --ffmpeg-location
 | 
			
		||||
    --clean-infojson                 --clean-info-json
 | 
			
		||||
    --cn-verification-proxy URL      --geo-verification-proxy URL
 | 
			
		||||
    --dump-headers                   --print-traffic
 | 
			
		||||
    --dump-intermediate-pages        --dump-pages
 | 
			
		||||
    --force-write-download-archive   --force-write-archive
 | 
			
		||||
    --no-clean-infojson              --no-clean-info-json
 | 
			
		||||
    --no-split-tracks                --no-split-chapters
 | 
			
		||||
| 
						 | 
				
			
			@ -2402,7 +2391,7 @@ These are aliases that are no longer documented for various reasons
 | 
			
		|||
    --yes-overwrites                 --force-overwrites
 | 
			
		||||
 | 
			
		||||
#### Sponskrub Options
 | 
			
		||||
Support for [SponSkrub](https://github.com/faissaloo/SponSkrub) has been deprecated in favor of the `--sponsorblock` options
 | 
			
		||||
Support for [SponSkrub](https://github.com/faissaloo/SponSkrub) has been removed in favor of the `--sponsorblock` options
 | 
			
		||||
 | 
			
		||||
    --sponskrub                      --sponsorblock-mark all
 | 
			
		||||
    --no-sponskrub                   --no-sponsorblock
 | 
			
		||||
| 
						 | 
				
			
			@ -2424,6 +2413,17 @@ These options may no longer work as intended
 | 
			
		|||
    --no-include-ads                 Default
 | 
			
		||||
    --write-annotations              No supported site has annotations now
 | 
			
		||||
    --no-write-annotations           Default
 | 
			
		||||
    --avconv-location                Removed alias for --ffmpeg-location
 | 
			
		||||
    --cn-verification-proxy URL      Removed alias for --geo-verification-proxy URL
 | 
			
		||||
    --dump-headers                   Removed alias for --print-traffic
 | 
			
		||||
    --dump-intermediate-pages        Removed alias for --dump-pages
 | 
			
		||||
    --youtube-skip-dash-manifest     Removed alias for --extractor-args "youtube:skip=dash" (Alias: --no-youtube-include-dash-manifest)
 | 
			
		||||
    --youtube-skip-hls-manifest      Removed alias for --extractor-args "youtube:skip=hls" (Alias: --no-youtube-include-hls-manifest)
 | 
			
		||||
    --youtube-include-dash-manifest  Default (Alias: --no-youtube-skip-dash-manifest)
 | 
			
		||||
    --youtube-include-hls-manifest   Default (Alias: --no-youtube-skip-hls-manifest)
 | 
			
		||||
    --youtube-print-sig-code         Removed testing functionality
 | 
			
		||||
    --dump-user-agent                No longer supported
 | 
			
		||||
    --xattr-set-filesize             No longer supported
 | 
			
		||||
    --compat-options seperate-video-versions  No longer needed
 | 
			
		||||
    --compat-options no-youtube-prefer-utc-upload-date  No longer supported
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,7 +36,6 @@
 | 
			
		|||
    "verbose": true,
 | 
			
		||||
    "writedescription": false,
 | 
			
		||||
    "writeinfojson": true,
 | 
			
		||||
    "writeannotations": false,
 | 
			
		||||
    "writelink": false,
 | 
			
		||||
    "writeurllink": false,
 | 
			
		||||
    "writewebloclink": false,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ import random
 | 
			
		|||
import ssl
 | 
			
		||||
import threading
 | 
			
		||||
 | 
			
		||||
from yt_dlp import socks, traverse_obj
 | 
			
		||||
from yt_dlp import socks
 | 
			
		||||
from yt_dlp.cookies import YoutubeDLCookieJar
 | 
			
		||||
from yt_dlp.dependencies import websockets
 | 
			
		||||
from yt_dlp.networking import Request
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +32,7 @@ from yt_dlp.networking.exceptions import (
 | 
			
		|||
    SSLError,
 | 
			
		||||
    TransportError,
 | 
			
		||||
)
 | 
			
		||||
from yt_dlp.utils.traversal import traverse_obj
 | 
			
		||||
from yt_dlp.utils.networking import HTTPHeaderDict
 | 
			
		||||
 | 
			
		||||
TEST_DIR = os.path.dirname(os.path.abspath(__file__))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,77 +0,0 @@
 | 
			
		|||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
# Allow direct execution
 | 
			
		||||
import os
 | 
			
		||||
import sys
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import xml.etree.ElementTree
 | 
			
		||||
 | 
			
		||||
import yt_dlp.extractor
 | 
			
		||||
import yt_dlp.YoutubeDL
 | 
			
		||||
from test.helper import get_params, is_download_test, try_rm
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class YoutubeDL(yt_dlp.YoutubeDL):
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.to_stderr = self.to_screen
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
params = get_params({
 | 
			
		||||
    'writeannotations': True,
 | 
			
		||||
    'skip_download': True,
 | 
			
		||||
    'writeinfojson': False,
 | 
			
		||||
    'format': 'flv',
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEST_ID = 'gr51aVj-mLg'
 | 
			
		||||
ANNOTATIONS_FILE = TEST_ID + '.annotations.xml'
 | 
			
		||||
EXPECTED_ANNOTATIONS = ['Speech bubble', 'Note', 'Title', 'Spotlight', 'Label']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@is_download_test
 | 
			
		||||
class TestAnnotations(unittest.TestCase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        # Clear old files
 | 
			
		||||
        self.tearDown()
 | 
			
		||||
 | 
			
		||||
    def test_info_json(self):
 | 
			
		||||
        expected = list(EXPECTED_ANNOTATIONS)  # Two annotations could have the same text.
 | 
			
		||||
        ie = yt_dlp.extractor.YoutubeIE()
 | 
			
		||||
        ydl = YoutubeDL(params)
 | 
			
		||||
        ydl.add_info_extractor(ie)
 | 
			
		||||
        ydl.download([TEST_ID])
 | 
			
		||||
        self.assertTrue(os.path.exists(ANNOTATIONS_FILE))
 | 
			
		||||
        annoxml = None
 | 
			
		||||
        with open(ANNOTATIONS_FILE, encoding='utf-8') as annof:
 | 
			
		||||
            annoxml = xml.etree.ElementTree.parse(annof)
 | 
			
		||||
        self.assertTrue(annoxml is not None, 'Failed to parse annotations XML')
 | 
			
		||||
        root = annoxml.getroot()
 | 
			
		||||
        self.assertEqual(root.tag, 'document')
 | 
			
		||||
        annotationsTag = root.find('annotations')
 | 
			
		||||
        self.assertEqual(annotationsTag.tag, 'annotations')
 | 
			
		||||
        annotations = annotationsTag.findall('annotation')
 | 
			
		||||
 | 
			
		||||
        # Not all the annotations have TEXT children and the annotations are returned unsorted.
 | 
			
		||||
        for a in annotations:
 | 
			
		||||
            self.assertEqual(a.tag, 'annotation')
 | 
			
		||||
            if a.get('type') == 'text':
 | 
			
		||||
                textTag = a.find('TEXT')
 | 
			
		||||
                text = textTag.text
 | 
			
		||||
                self.assertTrue(text in expected)  # assertIn only added in python 2.7
 | 
			
		||||
                # remove the first occurrence, there could be more than one annotation with the same text
 | 
			
		||||
                expected.remove(text)
 | 
			
		||||
        # We should have seen (and removed) all the expected annotation texts.
 | 
			
		||||
        self.assertEqual(len(expected), 0, 'Not all expected annotations were found.')
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        try_rm(ANNOTATIONS_FILE)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    unittest.main()
 | 
			
		||||
| 
						 | 
				
			
			@ -304,7 +304,6 @@ class YoutubeDL:
 | 
			
		|||
    clean_infojson:    Remove internal metadata from the infojson
 | 
			
		||||
    getcomments:       Extract video comments. This will not be written to disk
 | 
			
		||||
                       unless writeinfojson is also given
 | 
			
		||||
    writeannotations:  Write the video annotations to a .annotations.xml file
 | 
			
		||||
    writethumbnail:    Write the thumbnail image to a file
 | 
			
		||||
    allow_playlist_files: Whether to write playlists' description, infojson etc
 | 
			
		||||
                       also to disk when using the 'write*' options
 | 
			
		||||
| 
						 | 
				
			
			@ -511,11 +510,11 @@ class YoutubeDL:
 | 
			
		|||
    the downloader (see yt_dlp/downloader/common.py):
 | 
			
		||||
    nopart, updatetime, buffersize, ratelimit, throttledratelimit, min_filesize,
 | 
			
		||||
    max_filesize, test, noresizebuffer, retries, file_access_retries, fragment_retries,
 | 
			
		||||
    continuedl, xattr_set_filesize, hls_use_mpegts, http_chunk_size,
 | 
			
		||||
    external_downloader_args, concurrent_fragment_downloads, progress_delta.
 | 
			
		||||
    continuedl, hls_use_mpegts, http_chunk_size, external_downloader_args,
 | 
			
		||||
    concurrent_fragment_downloads, progress_delta.
 | 
			
		||||
 | 
			
		||||
    The following options are used by the post processors:
 | 
			
		||||
    ffmpeg_location:   Location of the ffmpeg/avconv binary; either the path
 | 
			
		||||
    ffmpeg_location:   Location of the ffmpeg binary; either the path
 | 
			
		||||
                       to the binary or its containing directory.
 | 
			
		||||
    postprocessor_args: A dictionary of postprocessor/executable keys (in lower case)
 | 
			
		||||
                       and a list of additional command-line arguments for the
 | 
			
		||||
| 
						 | 
				
			
			@ -566,32 +565,14 @@ class YoutubeDL:
 | 
			
		|||
    allsubtitles:      - Use subtitleslangs = ['all']
 | 
			
		||||
                       Downloads all the subtitles of the video
 | 
			
		||||
                       (requires writesubtitles or writeautomaticsub)
 | 
			
		||||
    include_ads:       - Doesn't work
 | 
			
		||||
                       Download ads as well
 | 
			
		||||
    call_home:         - Not implemented
 | 
			
		||||
                       Boolean, true if we are allowed to contact the
 | 
			
		||||
                       yt-dlp servers for debugging.
 | 
			
		||||
    post_hooks:        - Register a custom postprocessor
 | 
			
		||||
                       A list of functions that get called as the final step
 | 
			
		||||
                       for each video file, after all postprocessors have been
 | 
			
		||||
                       called. The filename will be passed as the only argument.
 | 
			
		||||
    hls_prefer_native: - Use external_downloader = {'m3u8': 'native'} or {'m3u8': 'ffmpeg'}.
 | 
			
		||||
                       Use the native HLS downloader instead of ffmpeg/avconv
 | 
			
		||||
                       if True, otherwise use ffmpeg/avconv if False, otherwise
 | 
			
		||||
                       Use the native HLS downloader instead of ffmpeg
 | 
			
		||||
                       if True, otherwise use ffmpeg if False, otherwise
 | 
			
		||||
                       use downloader suggested by extractor if None.
 | 
			
		||||
    prefer_ffmpeg:     - avconv support is deprecated
 | 
			
		||||
                       If False, use avconv instead of ffmpeg if both are available,
 | 
			
		||||
                       otherwise prefer ffmpeg.
 | 
			
		||||
    youtube_include_dash_manifest: - Use extractor_args
 | 
			
		||||
                       If True (default), DASH manifests and related
 | 
			
		||||
                       data will be downloaded and processed by extractor.
 | 
			
		||||
                       You can reduce network I/O by disabling it if you don't
 | 
			
		||||
                       care about DASH. (only for youtube)
 | 
			
		||||
    youtube_include_hls_manifest: - Use extractor_args
 | 
			
		||||
                       If True (default), HLS manifests and related
 | 
			
		||||
                       data will be downloaded and processed by extractor.
 | 
			
		||||
                       You can reduce network I/O by disabling it if you don't
 | 
			
		||||
                       care about HLS. (only for youtube)
 | 
			
		||||
    no_color:          Same as `color='no_color'`
 | 
			
		||||
    no_overwrites:     Same as `overwrites=False`
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			@ -750,10 +731,6 @@ class YoutubeDL:
 | 
			
		|||
                return True
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        if check_deprecated('cn_verification_proxy', '--cn-verification-proxy', '--geo-verification-proxy'):
 | 
			
		||||
            if self.params.get('geo_verification_proxy') is None:
 | 
			
		||||
                self.params['geo_verification_proxy'] = self.params['cn_verification_proxy']
 | 
			
		||||
 | 
			
		||||
        check_deprecated('useid', '--id', '-o "%(id)s.%(ext)s"')
 | 
			
		||||
 | 
			
		||||
        for msg in self.params.get('_warnings', []):
 | 
			
		||||
| 
						 | 
				
			
			@ -3335,28 +3312,6 @@ class YoutubeDL:
 | 
			
		|||
        elif _infojson_written is None:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        # Note: Annotations are deprecated
 | 
			
		||||
        annofn = None
 | 
			
		||||
        if self.params.get('writeannotations', False):
 | 
			
		||||
            annofn = self.prepare_filename(info_dict, 'annotation')
 | 
			
		||||
        if annofn:
 | 
			
		||||
            if not self._ensure_dir_exists(annofn):
 | 
			
		||||
                return
 | 
			
		||||
            if not self.params.get('overwrites', True) and os.path.exists(annofn):
 | 
			
		||||
                self.to_screen('[info] Video annotations are already present')
 | 
			
		||||
            elif not info_dict.get('annotations'):
 | 
			
		||||
                self.report_warning('There are no annotations to write.')
 | 
			
		||||
            else:
 | 
			
		||||
                try:
 | 
			
		||||
                    self.to_screen('[info] Writing video annotations to: ' + annofn)
 | 
			
		||||
                    with open(annofn, 'w', encoding='utf-8') as annofile:
 | 
			
		||||
                        annofile.write(info_dict['annotations'])
 | 
			
		||||
                except (KeyError, TypeError):
 | 
			
		||||
                    self.report_warning('There are no annotations to write.')
 | 
			
		||||
                except OSError:
 | 
			
		||||
                    self.report_error('Cannot write annotations file: ' + annofn)
 | 
			
		||||
                    return
 | 
			
		||||
 | 
			
		||||
        # Write internet shortcut files
 | 
			
		||||
        def _write_link_file(link_type):
 | 
			
		||||
            url = try_get(info_dict['webpage_url'], iri_to_uri)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,11 +59,9 @@ from .utils import (
 | 
			
		|||
    render_table,
 | 
			
		||||
    setproctitle,
 | 
			
		||||
    shell_quote,
 | 
			
		||||
    traverse_obj,
 | 
			
		||||
    variadic,
 | 
			
		||||
    write_string,
 | 
			
		||||
)
 | 
			
		||||
from .utils.networking import std_headers
 | 
			
		||||
from .utils._utils import _UnsafeExtensionError
 | 
			
		||||
from .YoutubeDL import YoutubeDL
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -523,7 +521,6 @@ def validate_options(opts):
 | 
			
		|||
 | 
			
		||||
    if report_args_compat('post-processor', opts.postprocessor_args, 'default-compat', 'default'):
 | 
			
		||||
        opts.postprocessor_args['default'] = opts.postprocessor_args.pop('default-compat')
 | 
			
		||||
        opts.postprocessor_args.setdefault('sponskrub', [])
 | 
			
		||||
 | 
			
		||||
    def report_conflict(arg1, opt1, arg2='--allow-unplayable-formats', opt2='allow_unplayable_formats',
 | 
			
		||||
                        val1=NO_DEFAULT, val2=NO_DEFAULT, default=False):
 | 
			
		||||
| 
						 | 
				
			
			@ -548,11 +545,6 @@ def validate_options(opts):
 | 
			
		|||
                    '"--exec before_dl:"', 'exec_cmd', val2=opts.exec_cmd.get('before_dl'))
 | 
			
		||||
    report_conflict('--id', 'useid', '--output', 'outtmpl', val2=opts.outtmpl.get('default'))
 | 
			
		||||
    report_conflict('--remux-video', 'remuxvideo', '--recode-video', 'recodevideo')
 | 
			
		||||
    report_conflict('--sponskrub', 'sponskrub', '--remove-chapters', 'remove_chapters')
 | 
			
		||||
    report_conflict('--sponskrub', 'sponskrub', '--sponsorblock-mark', 'sponsorblock_mark')
 | 
			
		||||
    report_conflict('--sponskrub', 'sponskrub', '--sponsorblock-remove', 'sponsorblock_remove')
 | 
			
		||||
    report_conflict('--sponskrub-cut', 'sponskrub_cut', '--split-chapter', 'split_chapters',
 | 
			
		||||
                    val1=opts.sponskrub and opts.sponskrub_cut)
 | 
			
		||||
 | 
			
		||||
    # Conflicts with --allow-unplayable-formats
 | 
			
		||||
    report_conflict('--embed-metadata', 'addmetadata')
 | 
			
		||||
| 
						 | 
				
			
			@ -565,23 +557,15 @@ def validate_options(opts):
 | 
			
		|||
    report_conflict('--recode-video', 'recodevideo')
 | 
			
		||||
    report_conflict('--remove-chapters', 'remove_chapters', default=[])
 | 
			
		||||
    report_conflict('--remux-video', 'remuxvideo')
 | 
			
		||||
    report_conflict('--sponskrub', 'sponskrub')
 | 
			
		||||
    report_conflict('--sponsorblock-remove', 'sponsorblock_remove', default=set())
 | 
			
		||||
    report_conflict('--xattrs', 'xattrs')
 | 
			
		||||
 | 
			
		||||
    # Fully deprecated options
 | 
			
		||||
    def report_deprecation(val, old, new=None):
 | 
			
		||||
        if not val:
 | 
			
		||||
            return
 | 
			
		||||
    if hasattr(opts, '_deprecated_options'):
 | 
			
		||||
        deprecation_warnings.append(
 | 
			
		||||
            f'{old} is deprecated and may be removed in a future version. Use {new} instead' if new
 | 
			
		||||
            else f'{old} is deprecated and may not work as expected')
 | 
			
		||||
 | 
			
		||||
    report_deprecation(opts.sponskrub, '--sponskrub', '--sponsorblock-mark or --sponsorblock-remove')
 | 
			
		||||
    report_deprecation(not opts.prefer_ffmpeg, '--prefer-avconv', 'ffmpeg')
 | 
			
		||||
    # report_deprecation(opts.include_ads, '--include-ads')  # We may re-implement this in future
 | 
			
		||||
    # report_deprecation(opts.call_home, '--call-home')  # We may re-implement this in future
 | 
			
		||||
    # report_deprecation(opts.writeannotations, '--write-annotations')  # It's just that no website has it
 | 
			
		||||
            f'The following options have been deprecated: {", ".join(opts._deprecated_options)}\n'
 | 
			
		||||
            'Please remove them from your command/configuration to avoid future errors.\n'
 | 
			
		||||
            'See  https://github.com/yt-dlp/yt-dlp/issues/14198  for more details')
 | 
			
		||||
        del opts._deprecated_options
 | 
			
		||||
 | 
			
		||||
    # Dependent options
 | 
			
		||||
    opts.date = DateRange.day(opts.date) if opts.date else DateRange(opts.dateafter, opts.datebefore)
 | 
			
		||||
| 
						 | 
				
			
			@ -712,21 +696,6 @@ def get_postprocessors(opts):
 | 
			
		|||
            'add_metadata': opts.addmetadata,
 | 
			
		||||
            'add_infojson': opts.embed_infojson,
 | 
			
		||||
        }
 | 
			
		||||
    # Deprecated
 | 
			
		||||
    # This should be above EmbedThumbnail since sponskrub removes the thumbnail attachment
 | 
			
		||||
    # but must be below EmbedSubtitle and FFmpegMetadata
 | 
			
		||||
    # See https://github.com/yt-dlp/yt-dlp/issues/204 , https://github.com/faissaloo/SponSkrub/issues/29
 | 
			
		||||
    # If opts.sponskrub is None, sponskrub is used, but it silently fails if the executable can't be found
 | 
			
		||||
    if opts.sponskrub is not False:
 | 
			
		||||
        yield {
 | 
			
		||||
            'key': 'SponSkrub',
 | 
			
		||||
            'path': opts.sponskrub_path,
 | 
			
		||||
            'args': opts.sponskrub_args,
 | 
			
		||||
            'cut': opts.sponskrub_cut,
 | 
			
		||||
            'force': opts.sponskrub_force,
 | 
			
		||||
            'ignoreerror': opts.sponskrub is None,
 | 
			
		||||
            '_from_cli': True,
 | 
			
		||||
        }
 | 
			
		||||
    if opts.embedthumbnail:
 | 
			
		||||
        yield {
 | 
			
		||||
            'key': 'EmbedThumbnail',
 | 
			
		||||
| 
						 | 
				
			
			@ -885,7 +854,6 @@ def parse_options(argv=None):
 | 
			
		|||
        'nopart': opts.nopart,
 | 
			
		||||
        'updatetime': opts.updatetime,
 | 
			
		||||
        'writedescription': opts.writedescription,
 | 
			
		||||
        'writeannotations': opts.writeannotations,
 | 
			
		||||
        'writeinfojson': opts.writeinfojson,
 | 
			
		||||
        'allow_playlist_files': opts.allow_playlist_files,
 | 
			
		||||
        'clean_infojson': opts.clean_infojson,
 | 
			
		||||
| 
						 | 
				
			
			@ -919,7 +887,6 @@ def parse_options(argv=None):
 | 
			
		|||
        'max_views': opts.max_views,
 | 
			
		||||
        'daterange': opts.date,
 | 
			
		||||
        'cachedir': opts.cachedir,
 | 
			
		||||
        'youtube_print_sig_code': opts.youtube_print_sig_code,
 | 
			
		||||
        'age_limit': opts.age_limit,
 | 
			
		||||
        'download_archive': opts.download_archive,
 | 
			
		||||
        'break_on_existing': opts.break_on_existing,
 | 
			
		||||
| 
						 | 
				
			
			@ -937,13 +904,9 @@ def parse_options(argv=None):
 | 
			
		|||
        'socket_timeout': opts.socket_timeout,
 | 
			
		||||
        'bidi_workaround': opts.bidi_workaround,
 | 
			
		||||
        'debug_printtraffic': opts.debug_printtraffic,
 | 
			
		||||
        'prefer_ffmpeg': opts.prefer_ffmpeg,
 | 
			
		||||
        'include_ads': opts.include_ads,
 | 
			
		||||
        'default_search': opts.default_search,
 | 
			
		||||
        'dynamic_mpd': opts.dynamic_mpd,
 | 
			
		||||
        'extractor_args': opts.extractor_args,
 | 
			
		||||
        'youtube_include_dash_manifest': opts.youtube_include_dash_manifest,
 | 
			
		||||
        'youtube_include_hls_manifest': opts.youtube_include_hls_manifest,
 | 
			
		||||
        'encoding': opts.encoding,
 | 
			
		||||
        'extract_flat': opts.extract_flat,
 | 
			
		||||
        'live_from_start': opts.live_from_start,
 | 
			
		||||
| 
						 | 
				
			
			@ -955,7 +918,6 @@ def parse_options(argv=None):
 | 
			
		|||
        'fixup': opts.fixup,
 | 
			
		||||
        'source_address': opts.source_address,
 | 
			
		||||
        'impersonate': opts.impersonate,
 | 
			
		||||
        'call_home': opts.call_home,
 | 
			
		||||
        'sleep_interval_requests': opts.sleep_interval_requests,
 | 
			
		||||
        'sleep_interval': opts.sleep_interval,
 | 
			
		||||
        'max_sleep_interval': opts.max_sleep_interval,
 | 
			
		||||
| 
						 | 
				
			
			@ -965,7 +927,6 @@ def parse_options(argv=None):
 | 
			
		|||
        'force_keyframes_at_cuts': opts.force_keyframes_at_cuts,
 | 
			
		||||
        'list_thumbnails': opts.list_thumbnails,
 | 
			
		||||
        'playlist_items': opts.playlist_items,
 | 
			
		||||
        'xattr_set_filesize': opts.xattr_set_filesize,
 | 
			
		||||
        'match_filter': opts.match_filter,
 | 
			
		||||
        'color': opts.color,
 | 
			
		||||
        'ffmpeg_location': opts.ffmpeg_location,
 | 
			
		||||
| 
						 | 
				
			
			@ -974,7 +935,6 @@ def parse_options(argv=None):
 | 
			
		|||
        'hls_split_discontinuity': opts.hls_split_discontinuity,
 | 
			
		||||
        'external_downloader_args': opts.external_downloader_args,
 | 
			
		||||
        'postprocessor_args': opts.postprocessor_args,
 | 
			
		||||
        'cn_verification_proxy': opts.cn_verification_proxy,
 | 
			
		||||
        'geo_verification_proxy': opts.geo_verification_proxy,
 | 
			
		||||
        'geo_bypass': opts.geo_bypass,
 | 
			
		||||
        'geo_bypass_country': opts.geo_bypass_country,
 | 
			
		||||
| 
						 | 
				
			
			@ -992,12 +952,6 @@ def _real_main(argv=None):
 | 
			
		|||
 | 
			
		||||
    parser, opts, all_urls, ydl_opts = parse_options(argv)
 | 
			
		||||
 | 
			
		||||
    # Dump user agent
 | 
			
		||||
    if opts.dump_user_agent:
 | 
			
		||||
        ua = traverse_obj(opts.headers, 'User-Agent', casesense=False, default=std_headers['User-Agent'])
 | 
			
		||||
        write_string(f'{ua}\n', out=sys.stdout)
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    if print_extractor_information(opts, all_urls):
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,7 +62,6 @@ class FileDownloader:
 | 
			
		|||
    test:               Download only first bytes to test the downloader.
 | 
			
		||||
    min_filesize:       Skip files smaller than this size
 | 
			
		||||
    max_filesize:       Skip files larger than this size
 | 
			
		||||
    xattr_set_filesize: Set ytdl.filesize user xattribute with expected size.
 | 
			
		||||
    progress_delta:     The minimum time between progress output, in seconds
 | 
			
		||||
    external_downloader_args:  A dictionary of downloader keys (in lower case)
 | 
			
		||||
                        and a list of additional command-line arguments for the
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -563,7 +563,7 @@ class FFmpegFD(ExternalFD):
 | 
			
		|||
                    f'{cookie.name}={cookie.value}; path={cookie.path}; domain={cookie.domain};\r\n'
 | 
			
		||||
                    for cookie in cookies)])
 | 
			
		||||
            if fmt.get('http_headers') and is_http:
 | 
			
		||||
                # Trailing \r\n after each HTTP header is important to prevent warning from ffmpeg/avconv:
 | 
			
		||||
                # Trailing \r\n after each HTTP header is important to prevent warning from ffmpeg:
 | 
			
		||||
                # [http @ 00000000003d2fa0] No trailing CRLF found in HTTP header.
 | 
			
		||||
                args.extend(['-headers', ''.join(f'{key}: {val}\r\n' for key, val in fmt['http_headers'].items())])
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -654,10 +654,6 @@ class FFmpegFD(ExternalFD):
 | 
			
		|||
            return retval
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AVconvFD(FFmpegFD):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
_BY_NAME = {
 | 
			
		||||
    klass.get_basename(): klass
 | 
			
		||||
    for name, klass in globals().items()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,12 +13,9 @@ from ..utils import (
 | 
			
		|||
    ContentTooShortError,
 | 
			
		||||
    RetryManager,
 | 
			
		||||
    ThrottledDownload,
 | 
			
		||||
    XAttrMetadataError,
 | 
			
		||||
    XAttrUnavailableError,
 | 
			
		||||
    int_or_none,
 | 
			
		||||
    parse_http_range,
 | 
			
		||||
    try_call,
 | 
			
		||||
    write_xattr,
 | 
			
		||||
)
 | 
			
		||||
from ..utils.networking import HTTPHeaderDict
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -273,12 +270,6 @@ class HttpFD(FileDownloader):
 | 
			
		|||
                        self.report_error(f'unable to open for writing: {err}')
 | 
			
		||||
                        return False
 | 
			
		||||
 | 
			
		||||
                    if self.params.get('xattr_set_filesize', False) and data_len is not None:
 | 
			
		||||
                        try:
 | 
			
		||||
                            write_xattr(ctx.tmpfilename, 'user.ytdl.filesize', str(data_len).encode())
 | 
			
		||||
                        except (XAttrUnavailableError, XAttrMetadataError) as err:
 | 
			
		||||
                            self.report_error(f'unable to set filesize xattr: {err}')
 | 
			
		||||
 | 
			
		||||
                try:
 | 
			
		||||
                    ctx.stream.write(data_block)
 | 
			
		||||
                except OSError as err:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2107,47 +2107,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
 | 
			
		|||
 | 
			
		||||
        return lambda s: ''.join(s[i] for i in cache_spec)
 | 
			
		||||
 | 
			
		||||
    def _print_sig_code(self, func, example_sig):
 | 
			
		||||
        if not self.get_param('youtube_print_sig_code'):
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        def gen_sig_code(idxs):
 | 
			
		||||
            def _genslice(start, end, step):
 | 
			
		||||
                starts = '' if start == 0 else str(start)
 | 
			
		||||
                ends = (':%d' % (end + step)) if end + step >= 0 else ':'
 | 
			
		||||
                steps = '' if step == 1 else (':%d' % step)
 | 
			
		||||
                return f's[{starts}{ends}{steps}]'
 | 
			
		||||
 | 
			
		||||
            step = None
 | 
			
		||||
            # Quelch pyflakes warnings - start will be set when step is set
 | 
			
		||||
            start = '(Never used)'
 | 
			
		||||
            for i, prev in zip(idxs[1:], idxs[:-1]):
 | 
			
		||||
                if step is not None:
 | 
			
		||||
                    if i - prev == step:
 | 
			
		||||
                        continue
 | 
			
		||||
                    yield _genslice(start, prev, step)
 | 
			
		||||
                    step = None
 | 
			
		||||
                    continue
 | 
			
		||||
                if i - prev in [-1, 1]:
 | 
			
		||||
                    step = i - prev
 | 
			
		||||
                    start = prev
 | 
			
		||||
                    continue
 | 
			
		||||
                else:
 | 
			
		||||
                    yield 's[%d]' % prev
 | 
			
		||||
            if step is None:
 | 
			
		||||
                yield 's[%d]' % i
 | 
			
		||||
            else:
 | 
			
		||||
                yield _genslice(start, i, step)
 | 
			
		||||
 | 
			
		||||
        test_string = ''.join(map(chr, range(len(example_sig))))
 | 
			
		||||
        cache_res = func(test_string)
 | 
			
		||||
        cache_spec = [ord(c) for c in cache_res]
 | 
			
		||||
        expr_code = ' + '.join(gen_sig_code(cache_spec))
 | 
			
		||||
        signature_id_tuple = '({})'.format(', '.join(str(len(p)) for p in example_sig.split('.')))
 | 
			
		||||
        code = (f'if tuple(len(p) for p in s.split(\'.\')) == {signature_id_tuple}:\n'
 | 
			
		||||
                f'    return {expr_code}\n')
 | 
			
		||||
        self.to_screen('Extracted signature function:\n' + code)
 | 
			
		||||
 | 
			
		||||
    def _parse_sig_js(self, jscode, player_url):
 | 
			
		||||
        # Examples where `sig` is funcname:
 | 
			
		||||
        # sig=function(a){a=a.split(""); ... ;return a.join("")};
 | 
			
		||||
| 
						 | 
				
			
			@ -2216,7 +2175,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
 | 
			
		|||
        extract_sig = self._cached(
 | 
			
		||||
            self._extract_signature_function, 'sig', player_url, self._signature_cache_id(s))
 | 
			
		||||
        func = extract_sig(video_id, player_url, s)
 | 
			
		||||
        self._print_sig_code(func, s)
 | 
			
		||||
        return func(s)
 | 
			
		||||
 | 
			
		||||
    def _decrypt_nsig(self, s, video_id, player_url):
 | 
			
		||||
| 
						 | 
				
			
			@ -2226,11 +2184,9 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
 | 
			
		|||
        player_url = urljoin('https://www.youtube.com', player_url)
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            jsi, player_id, func_code = self._extract_n_function_code(video_id, player_url)
 | 
			
		||||
            jsi, _, func_code = self._extract_n_function_code(video_id, player_url)
 | 
			
		||||
        except ExtractorError as e:
 | 
			
		||||
            raise ExtractorError('Unable to extract nsig function code', cause=e)
 | 
			
		||||
        if self.get_param('youtube_print_sig_code'):
 | 
			
		||||
            self.to_screen(f'Extracted nsig function from {player_id}:\n{func_code[1]}\n')
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            extract_nsig = self._cached(self._extract_n_function_from_code, self._NSIG_FUNC_CACHE_ID, player_url)
 | 
			
		||||
| 
						 | 
				
			
			@ -3580,23 +3536,12 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
 | 
			
		|||
 | 
			
		||||
        needs_live_processing = self._needs_live_processing(live_status, duration)
 | 
			
		||||
        skip_bad_formats = 'incomplete' not in format_types
 | 
			
		||||
        if self._configuration_arg('include_incomplete_formats'):
 | 
			
		||||
            skip_bad_formats = False
 | 
			
		||||
            self._downloader.deprecated_feature('[youtube] include_incomplete_formats extractor argument is deprecated. '
 | 
			
		||||
                                                'Use formats=incomplete extractor argument instead')
 | 
			
		||||
 | 
			
		||||
        skip_manifests = set(self._configuration_arg('skip'))
 | 
			
		||||
        if (not self.get_param('youtube_include_hls_manifest', True)
 | 
			
		||||
                or needs_live_processing == 'is_live'  # These will be filtered out by YoutubeDL anyway
 | 
			
		||||
        if (needs_live_processing == 'is_live'  # These will be filtered out by YoutubeDL anyway
 | 
			
		||||
                or (needs_live_processing and skip_bad_formats)):
 | 
			
		||||
            skip_manifests.add('hls')
 | 
			
		||||
 | 
			
		||||
        if not self.get_param('youtube_include_dash_manifest', True):
 | 
			
		||||
            skip_manifests.add('dash')
 | 
			
		||||
        if self._configuration_arg('include_live_dash'):
 | 
			
		||||
            self._downloader.deprecated_feature('[youtube] include_live_dash extractor argument is deprecated. '
 | 
			
		||||
                                                'Use formats=incomplete extractor argument instead')
 | 
			
		||||
        elif skip_bad_formats and live_status == 'is_live' and needs_live_processing != 'is_live':
 | 
			
		||||
        if skip_bad_formats and live_status == 'is_live' and needs_live_processing != 'is_live':
 | 
			
		||||
            skip_manifests.add('dash')
 | 
			
		||||
 | 
			
		||||
        def process_manifest_format(f, proto, client_name, itag, missing_pot):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -389,10 +389,6 @@ def create_parser():
 | 
			
		|||
        '--abort-on-error', '--no-ignore-errors',
 | 
			
		||||
        action='store_false', dest='ignoreerrors',
 | 
			
		||||
        help='Abort downloading of further videos if an error occurs (Alias: --no-ignore-errors)')
 | 
			
		||||
    general.add_option(
 | 
			
		||||
        '--dump-user-agent',
 | 
			
		||||
        action='store_true', dest='dump_user_agent', default=False,
 | 
			
		||||
        help='Display the current user-agent and exit')
 | 
			
		||||
    general.add_option(
 | 
			
		||||
        '--list-extractors',
 | 
			
		||||
        action='store_true', dest='list_extractors', default=False,
 | 
			
		||||
| 
						 | 
				
			
			@ -616,10 +612,6 @@ def create_parser():
 | 
			
		|||
        help=(
 | 
			
		||||
            'Use this proxy to verify the IP address for some geo-restricted sites. '
 | 
			
		||||
            'The default proxy specified by --proxy (or none, if the option is not present) is used for the actual downloading'))
 | 
			
		||||
    geo.add_option(
 | 
			
		||||
        '--cn-verification-proxy',
 | 
			
		||||
        dest='cn_verification_proxy', default=None, metavar='URL',
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    geo.add_option(
 | 
			
		||||
        '--xff', metavar='VALUE',
 | 
			
		||||
        dest='geo_bypass', default='default',
 | 
			
		||||
| 
						 | 
				
			
			@ -778,14 +770,6 @@ def create_parser():
 | 
			
		|||
        '--skip-playlist-after-errors', metavar='N',
 | 
			
		||||
        dest='skip_playlist_after_errors', default=None, type=int,
 | 
			
		||||
        help='Number of allowed failures until the rest of the playlist is skipped')
 | 
			
		||||
    selection.add_option(
 | 
			
		||||
        '--include-ads',
 | 
			
		||||
        dest='include_ads', action='store_true',
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    selection.add_option(
 | 
			
		||||
        '--no-include-ads',
 | 
			
		||||
        dest='include_ads', action='store_false',
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
 | 
			
		||||
    authentication = optparse.OptionGroup(parser, 'Authentication Options')
 | 
			
		||||
    authentication.add_option(
 | 
			
		||||
| 
						 | 
				
			
			@ -1071,10 +1055,6 @@ def create_parser():
 | 
			
		|||
        '--no-lazy-playlist',
 | 
			
		||||
        action='store_false', dest='lazy_playlist',
 | 
			
		||||
        help='Process videos in the playlist only after the entire playlist is parsed (default)')
 | 
			
		||||
    downloader.add_option(
 | 
			
		||||
        '--xattr-set-filesize',
 | 
			
		||||
        dest='xattr_set_filesize', action='store_true',
 | 
			
		||||
        help='Set file xattribute ytdl.filesize with expected file size')
 | 
			
		||||
    downloader.add_option(
 | 
			
		||||
        '--hls-prefer-native',
 | 
			
		||||
        dest='hls_prefer_native', action='store_true', default=None,
 | 
			
		||||
| 
						 | 
				
			
			@ -1335,7 +1315,7 @@ def create_parser():
 | 
			
		|||
        action='store_true', dest='verbose', default=False,
 | 
			
		||||
        help='Print various debugging information')
 | 
			
		||||
    verbosity.add_option(
 | 
			
		||||
        '--dump-pages', '--dump-intermediate-pages',
 | 
			
		||||
        '--dump-pages',
 | 
			
		||||
        action='store_true', dest='dump_intermediate_pages', default=False,
 | 
			
		||||
        help='Print downloaded pages encoded using base64 to debug problems (very verbose)')
 | 
			
		||||
    verbosity.add_option(
 | 
			
		||||
| 
						 | 
				
			
			@ -1347,23 +1327,9 @@ def create_parser():
 | 
			
		|||
        action='store_true', dest='load_pages', default=False,
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    verbosity.add_option(
 | 
			
		||||
        '--youtube-print-sig-code',
 | 
			
		||||
        action='store_true', dest='youtube_print_sig_code', default=False,
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    verbosity.add_option(
 | 
			
		||||
        '--print-traffic', '--dump-headers',
 | 
			
		||||
        '--print-traffic',
 | 
			
		||||
        dest='debug_printtraffic', action='store_true', default=False,
 | 
			
		||||
        help='Display sent and read HTTP traffic')
 | 
			
		||||
    verbosity.add_option(
 | 
			
		||||
        '-C', '--call-home',
 | 
			
		||||
        dest='call_home', action='store_true', default=False,
 | 
			
		||||
        # help='Contact the yt-dlp server for debugging')
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    verbosity.add_option(
 | 
			
		||||
        '--no-call-home',
 | 
			
		||||
        dest='call_home', action='store_false',
 | 
			
		||||
        # help='Do not contact the yt-dlp server for debugging (default)')
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
 | 
			
		||||
    filesystem = optparse.OptionGroup(parser, 'Filesystem Options')
 | 
			
		||||
    filesystem.add_option(
 | 
			
		||||
| 
						 | 
				
			
			@ -1488,14 +1454,6 @@ def create_parser():
 | 
			
		|||
        '--no-write-info-json',
 | 
			
		||||
        action='store_false', dest='writeinfojson',
 | 
			
		||||
        help='Do not write video metadata (default)')
 | 
			
		||||
    filesystem.add_option(
 | 
			
		||||
        '--write-annotations',
 | 
			
		||||
        action='store_true', dest='writeannotations', default=False,
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    filesystem.add_option(
 | 
			
		||||
        '--no-write-annotations',
 | 
			
		||||
        action='store_false', dest='writeannotations',
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    filesystem.add_option(
 | 
			
		||||
        '--write-playlist-metafiles',
 | 
			
		||||
        action='store_true', dest='allow_playlist_files', default=None,
 | 
			
		||||
| 
						 | 
				
			
			@ -1755,15 +1713,7 @@ def create_parser():
 | 
			
		|||
            'detect_or_warn (the default; fix the file if we can, warn otherwise), '
 | 
			
		||||
            'force (try fixing even if the file already exists)'))
 | 
			
		||||
    postproc.add_option(
 | 
			
		||||
        '--prefer-avconv', '--no-prefer-ffmpeg',
 | 
			
		||||
        action='store_false', dest='prefer_ffmpeg',
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    postproc.add_option(
 | 
			
		||||
        '--prefer-ffmpeg', '--no-prefer-avconv',
 | 
			
		||||
        action='store_true', dest='prefer_ffmpeg', default=True,
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    postproc.add_option(
 | 
			
		||||
        '--ffmpeg-location', '--avconv-location', metavar='PATH',
 | 
			
		||||
        '--ffmpeg-location', metavar='PATH',
 | 
			
		||||
        dest='ffmpeg_location',
 | 
			
		||||
        help='Location of the ffmpeg binary; either the path to the binary or its containing directory')
 | 
			
		||||
    postproc.add_option(
 | 
			
		||||
| 
						 | 
				
			
			@ -1900,38 +1850,6 @@ def create_parser():
 | 
			
		|||
        default='https://sponsor.ajay.app', dest='sponsorblock_api',
 | 
			
		||||
        help='SponsorBlock API location, defaults to %default')
 | 
			
		||||
 | 
			
		||||
    sponsorblock.add_option(
 | 
			
		||||
        '--sponskrub',
 | 
			
		||||
        action='store_true', dest='sponskrub', default=False,
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    sponsorblock.add_option(
 | 
			
		||||
        '--no-sponskrub',
 | 
			
		||||
        action='store_false', dest='sponskrub',
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    sponsorblock.add_option(
 | 
			
		||||
        '--sponskrub-cut', default=False,
 | 
			
		||||
        action='store_true', dest='sponskrub_cut',
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    sponsorblock.add_option(
 | 
			
		||||
        '--no-sponskrub-cut',
 | 
			
		||||
        action='store_false', dest='sponskrub_cut',
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    sponsorblock.add_option(
 | 
			
		||||
        '--sponskrub-force', default=False,
 | 
			
		||||
        action='store_true', dest='sponskrub_force',
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    sponsorblock.add_option(
 | 
			
		||||
        '--no-sponskrub-force',
 | 
			
		||||
        action='store_true', dest='sponskrub_force',
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    sponsorblock.add_option(
 | 
			
		||||
        '--sponskrub-location', metavar='PATH',
 | 
			
		||||
        dest='sponskrub_path', default='',
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    sponsorblock.add_option(
 | 
			
		||||
        '--sponskrub-args', dest='sponskrub_args', metavar='ARGS',
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
 | 
			
		||||
    extractor = optparse.OptionGroup(parser, 'Extractor Options')
 | 
			
		||||
    extractor.add_option(
 | 
			
		||||
        '--extractor-retries',
 | 
			
		||||
| 
						 | 
				
			
			@ -1967,22 +1885,56 @@ def create_parser():
 | 
			
		|||
        }, help=(
 | 
			
		||||
            'Pass ARGS arguments to the IE_KEY extractor. See "EXTRACTOR ARGUMENTS" for details. '
 | 
			
		||||
            'You can use this option multiple times to give arguments for different extractors'))
 | 
			
		||||
    extractor.add_option(
 | 
			
		||||
        '--youtube-include-dash-manifest', '--no-youtube-skip-dash-manifest',
 | 
			
		||||
        action='store_true', dest='youtube_include_dash_manifest', default=True,
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    extractor.add_option(
 | 
			
		||||
        '--youtube-skip-dash-manifest', '--no-youtube-include-dash-manifest',
 | 
			
		||||
        action='store_false', dest='youtube_include_dash_manifest',
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    extractor.add_option(
 | 
			
		||||
        '--youtube-include-hls-manifest', '--no-youtube-skip-hls-manifest',
 | 
			
		||||
        action='store_true', dest='youtube_include_hls_manifest', default=True,
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    extractor.add_option(
 | 
			
		||||
        '--youtube-skip-hls-manifest', '--no-youtube-include-hls-manifest',
 | 
			
		||||
        action='store_false', dest='youtube_include_hls_manifest',
 | 
			
		||||
        help=optparse.SUPPRESS_HELP)
 | 
			
		||||
 | 
			
		||||
    def _deprecated_option_callback(option, opt_str, value, parser):
 | 
			
		||||
        current = getattr(parser.values, '_deprecated_options', [])
 | 
			
		||||
        parser.values._deprecated_options = [*current, opt_str]
 | 
			
		||||
 | 
			
		||||
    deprecated_switches = [
 | 
			
		||||
        '--xattr-set-filesize',
 | 
			
		||||
        '--dump-user-agent',
 | 
			
		||||
        '--youtube-include-dash-manifest',
 | 
			
		||||
        '--no-youtube-skip-dash-manifest',
 | 
			
		||||
        '--youtube-skip-dash-manifest',
 | 
			
		||||
        '--no-youtube-include-dash-manifest',
 | 
			
		||||
        '--youtube-include-hls-manifest',
 | 
			
		||||
        '--no-youtube-skip-hls-manifest',
 | 
			
		||||
        '--youtube-skip-hls-manifest',
 | 
			
		||||
        '--no-youtube-include-hls-manifest',
 | 
			
		||||
        '--youtube-print-sig-code',
 | 
			
		||||
        '--sponskrub',
 | 
			
		||||
        '--no-sponskrub',
 | 
			
		||||
        '--sponskrub-cut',
 | 
			
		||||
        '--no-sponskrub-cut',
 | 
			
		||||
        '--sponskrub-force',
 | 
			
		||||
        '--no-sponskrub-force',
 | 
			
		||||
        '--prefer-avconv',
 | 
			
		||||
        '--no-prefer-ffmpeg',
 | 
			
		||||
        '--prefer-ffmpeg',
 | 
			
		||||
        '--no-prefer-avconv',
 | 
			
		||||
        '-C',  # this needs to remain deprecated until at least 2028
 | 
			
		||||
        '--call-home',
 | 
			
		||||
        '--no-call-home',
 | 
			
		||||
        '--include-ads',
 | 
			
		||||
        '--no-include-ads',
 | 
			
		||||
        '--write-annotations',
 | 
			
		||||
        '--no-write-annotations',
 | 
			
		||||
    ]
 | 
			
		||||
    deprecated_arguments = [
 | 
			
		||||
        '--sponskrub-location',
 | 
			
		||||
        '--sponskrub-args',
 | 
			
		||||
        '--cn-verification-proxy',
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    for opt in deprecated_switches:
 | 
			
		||||
        parser.add_option(
 | 
			
		||||
            opt, action='callback', callback=_deprecated_option_callback,
 | 
			
		||||
            help=optparse.SUPPRESS_HELP)
 | 
			
		||||
    for opt in deprecated_arguments:
 | 
			
		||||
        parser.add_option(
 | 
			
		||||
            opt, action='callback', callback=_deprecated_option_callback,
 | 
			
		||||
            metavar='ARG', dest='_', type='str',
 | 
			
		||||
            help=optparse.SUPPRESS_HELP)
 | 
			
		||||
 | 
			
		||||
    parser.add_option_group(general)
 | 
			
		||||
    parser.add_option_group(network)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,7 +30,6 @@ from .metadataparser import (
 | 
			
		|||
)
 | 
			
		||||
from .modify_chapters import ModifyChaptersPP
 | 
			
		||||
from .movefilesafterdownload import MoveFilesAfterDownloadPP
 | 
			
		||||
from .sponskrub import SponSkrubPP
 | 
			
		||||
from .sponsorblock import SponsorBlockPP
 | 
			
		||||
from .xattrpp import XAttrMetadataPP
 | 
			
		||||
from ..globals import plugin_pps, postprocessors
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -88,7 +88,6 @@ class FFmpegPostProcessor(PostProcessor):
 | 
			
		|||
 | 
			
		||||
    def __init__(self, downloader=None):
 | 
			
		||||
        PostProcessor.__init__(self, downloader)
 | 
			
		||||
        self._prefer_ffmpeg = self.get_param('prefer_ffmpeg', True)
 | 
			
		||||
        self._paths = self._determine_executables()
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
| 
						 | 
				
			
			@ -100,10 +99,8 @@ class FFmpegPostProcessor(PostProcessor):
 | 
			
		|||
    def get_versions(downloader=None):
 | 
			
		||||
        return FFmpegPostProcessor.get_versions_and_features(downloader)[0]
 | 
			
		||||
 | 
			
		||||
    _ffmpeg_to_avconv = {'ffmpeg': 'avconv', 'ffprobe': 'avprobe'}
 | 
			
		||||
 | 
			
		||||
    def _determine_executables(self):
 | 
			
		||||
        programs = [*self._ffmpeg_to_avconv.keys(), *self._ffmpeg_to_avconv.values()]
 | 
			
		||||
        programs = ['ffmpeg', 'ffprobe']
 | 
			
		||||
 | 
			
		||||
        location = self.get_param('ffmpeg_location', self._ffmpeg_location.get())
 | 
			
		||||
        if location is None:
 | 
			
		||||
| 
						 | 
				
			
			@ -119,8 +116,6 @@ class FFmpegPostProcessor(PostProcessor):
 | 
			
		|||
            filename = os.path.basename(location)
 | 
			
		||||
            basename = next((p for p in programs if p in filename), 'ffmpeg')
 | 
			
		||||
            dirname = os.path.dirname(os.path.abspath(location))
 | 
			
		||||
            if basename in self._ffmpeg_to_avconv:
 | 
			
		||||
                self._prefer_ffmpeg = True
 | 
			
		||||
 | 
			
		||||
        paths = {p: os.path.join(dirname, p) for p in programs}
 | 
			
		||||
        if basename and basename in filename:
 | 
			
		||||
| 
						 | 
				
			
			@ -179,17 +174,12 @@ class FFmpegPostProcessor(PostProcessor):
 | 
			
		|||
 | 
			
		||||
    def _get_version(self, kind):
 | 
			
		||||
        executables = (kind, )
 | 
			
		||||
        if not self._prefer_ffmpeg:
 | 
			
		||||
            executables = (kind, self._ffmpeg_to_avconv[kind])
 | 
			
		||||
        basename, version, features = next(filter(
 | 
			
		||||
            lambda x: x[1], ((p, *self._get_ffmpeg_version(p)) for p in executables)), (None, None, {}))
 | 
			
		||||
        if kind == 'ffmpeg':
 | 
			
		||||
            self.basename, self._features = basename, features
 | 
			
		||||
        else:
 | 
			
		||||
            self.probe_basename = basename
 | 
			
		||||
        if basename == self._ffmpeg_to_avconv[kind]:
 | 
			
		||||
            self.deprecated_feature(f'Support for {self._ffmpeg_to_avconv[kind]} is deprecated and '
 | 
			
		||||
                                    f'may be removed in a future version. Use {kind} instead')
 | 
			
		||||
        return version
 | 
			
		||||
 | 
			
		||||
    @functools.cached_property
 | 
			
		||||
| 
						 | 
				
			
			@ -231,7 +221,7 @@ class FFmpegPostProcessor(PostProcessor):
 | 
			
		|||
        if not self.available:
 | 
			
		||||
            raise FFmpegPostProcessorError('ffmpeg not found. Please install or provide the path using --ffmpeg-location')
 | 
			
		||||
 | 
			
		||||
        required_version = '10-0' if self.basename == 'avconv' else '1.0'
 | 
			
		||||
        required_version = '1.0'
 | 
			
		||||
        if is_outdated_version(self._version, required_version):
 | 
			
		||||
            self.report_warning(f'Your copy of {self.basename} is outdated, update {self.basename} '
 | 
			
		||||
                                f'to version {required_version} or newer if you encounter any errors')
 | 
			
		||||
| 
						 | 
				
			
			@ -842,17 +832,6 @@ class FFmpegMergerPP(FFmpegPostProcessor):
 | 
			
		|||
 | 
			
		||||
    def can_merge(self):
 | 
			
		||||
        # TODO: figure out merge-capable ffmpeg version
 | 
			
		||||
        if self.basename != 'avconv':
 | 
			
		||||
            return True
 | 
			
		||||
 | 
			
		||||
        required_version = '10-0'
 | 
			
		||||
        if is_outdated_version(
 | 
			
		||||
                self._versions[self.basename], required_version):
 | 
			
		||||
            warning = (f'Your copy of {self.basename} is outdated and unable to properly mux separate video and audio files, '
 | 
			
		||||
                       'yt-dlp will download single file media. '
 | 
			
		||||
                       f'Update {self.basename} to version {required_version} or newer to fix this.')
 | 
			
		||||
            self.report_warning(warning)
 | 
			
		||||
            return False
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,97 +0,0 @@
 | 
			
		|||
import os
 | 
			
		||||
import shlex
 | 
			
		||||
import subprocess
 | 
			
		||||
 | 
			
		||||
from .common import PostProcessor
 | 
			
		||||
from ..utils import (
 | 
			
		||||
    Popen,
 | 
			
		||||
    PostProcessingError,
 | 
			
		||||
    check_executable,
 | 
			
		||||
    cli_option,
 | 
			
		||||
    encodeArgument,
 | 
			
		||||
    prepend_extension,
 | 
			
		||||
    shell_quote,
 | 
			
		||||
    str_or_none,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Deprecated in favor of the native implementation
 | 
			
		||||
class SponSkrubPP(PostProcessor):
 | 
			
		||||
    _temp_ext = 'spons'
 | 
			
		||||
    _exe_name = 'sponskrub'
 | 
			
		||||
 | 
			
		||||
    def __init__(self, downloader, path='', args=None, ignoreerror=False, cut=False, force=False, _from_cli=False):
 | 
			
		||||
        PostProcessor.__init__(self, downloader)
 | 
			
		||||
        self.force = force
 | 
			
		||||
        self.cutout = cut
 | 
			
		||||
        self.args = str_or_none(args) or ''  # For backward compatibility
 | 
			
		||||
        self.path = self.get_exe(path)
 | 
			
		||||
 | 
			
		||||
        if not _from_cli:
 | 
			
		||||
            self.deprecation_warning(
 | 
			
		||||
                'yt_dlp.postprocessor.SponSkrubPP support is deprecated and may be removed in a future version. '
 | 
			
		||||
                'Use yt_dlp.postprocessor.SponsorBlock and yt_dlp.postprocessor.ModifyChaptersPP instead')
 | 
			
		||||
 | 
			
		||||
        if not ignoreerror and self.path is None:
 | 
			
		||||
            if path:
 | 
			
		||||
                raise PostProcessingError(f'sponskrub not found in "{path}"')
 | 
			
		||||
            else:
 | 
			
		||||
                raise PostProcessingError('sponskrub not found. Please install or provide the path using --sponskrub-path')
 | 
			
		||||
 | 
			
		||||
    def get_exe(self, path=''):
 | 
			
		||||
        if not path or not check_executable(path, ['-h']):
 | 
			
		||||
            path = os.path.join(path, self._exe_name)
 | 
			
		||||
            if not check_executable(path, ['-h']):
 | 
			
		||||
                return None
 | 
			
		||||
        return path
 | 
			
		||||
 | 
			
		||||
    @PostProcessor._restrict_to(images=False)
 | 
			
		||||
    def run(self, information):
 | 
			
		||||
        if self.path is None:
 | 
			
		||||
            return [], information
 | 
			
		||||
 | 
			
		||||
        filename = information['filepath']
 | 
			
		||||
        if not os.path.exists(filename):  # no download
 | 
			
		||||
            return [], information
 | 
			
		||||
 | 
			
		||||
        if information['extractor_key'].lower() != 'youtube':
 | 
			
		||||
            self.to_screen('Skipping sponskrub since it is not a YouTube video')
 | 
			
		||||
            return [], information
 | 
			
		||||
        if self.cutout and not self.force and not information.get('__real_download', False):
 | 
			
		||||
            self.report_warning(
 | 
			
		||||
                'Skipping sponskrub since the video was already downloaded. '
 | 
			
		||||
                'Use --sponskrub-force to run sponskrub anyway')
 | 
			
		||||
            return [], information
 | 
			
		||||
 | 
			
		||||
        self.to_screen('Trying to %s sponsor sections' % ('remove' if self.cutout else 'mark'))
 | 
			
		||||
        if self.cutout:
 | 
			
		||||
            self.report_warning('Cutting out sponsor segments will cause the subtitles to go out of sync.')
 | 
			
		||||
            if not information.get('__real_download', False):
 | 
			
		||||
                self.report_warning('If sponskrub is run multiple times, unintended parts of the video could be cut out.')
 | 
			
		||||
 | 
			
		||||
        temp_filename = prepend_extension(filename, self._temp_ext)
 | 
			
		||||
        if os.path.exists(temp_filename):
 | 
			
		||||
            os.remove(temp_filename)
 | 
			
		||||
 | 
			
		||||
        cmd = [self.path]
 | 
			
		||||
        if not self.cutout:
 | 
			
		||||
            cmd += ['-chapter']
 | 
			
		||||
        cmd += cli_option(self._downloader.params, '-proxy', 'proxy')
 | 
			
		||||
        cmd += shlex.split(self.args)  # For backward compatibility
 | 
			
		||||
        cmd += self._configuration_args(self._exe_name, use_compat=False)
 | 
			
		||||
        cmd += ['--', information['id'], filename, temp_filename]
 | 
			
		||||
        cmd = [encodeArgument(i) for i in cmd]
 | 
			
		||||
 | 
			
		||||
        self.write_debug(f'sponskrub command line: {shell_quote(cmd)}')
 | 
			
		||||
        stdout, _, returncode = Popen.run(cmd, text=True, stdout=None if self.get_param('verbose') else subprocess.PIPE)
 | 
			
		||||
 | 
			
		||||
        if not returncode:
 | 
			
		||||
            os.replace(temp_filename, filename)
 | 
			
		||||
            self.to_screen('Sponsor sections have been %s' % ('removed' if self.cutout else 'marked'))
 | 
			
		||||
        elif returncode == 3:
 | 
			
		||||
            self.to_screen('No segments in the SponsorBlock database')
 | 
			
		||||
        else:
 | 
			
		||||
            raise PostProcessingError(
 | 
			
		||||
                stdout.strip().splitlines()[0 if stdout.strip().lower().startswith('unrecognised') else -1]
 | 
			
		||||
                or f'sponskrub failed with error code {returncode}')
 | 
			
		||||
        return [], information
 | 
			
		||||
		Ładowanie…
	
		Reference in New Issue