[cleanup] misc

This commit is contained in:
pukkandan 2021-10-23 02:07:20 +05:30
parent 457f6d6866
commit 49a57e70a9
No known key found for this signature in database
GPG Key ID: 0F00D95A001F4698
17 changed files with 104 additions and 69 deletions

View File

@ -33,7 +33,7 @@ body:
attributes: attributes:
label: Example URLs label: Example URLs
description: | description: |
Provide all kinds of example URLs, support for which should be included. Replace following example URLs by yours Provide all kinds of example URLs for which support should be added
value: | value: |
- Single video: https://www.youtube.com/watch?v=BaW_jenozKc - Single video: https://www.youtube.com/watch?v=BaW_jenozKc
- Single video: https://youtu.be/BaW_jenozKc - Single video: https://youtu.be/BaW_jenozKc

View File

@ -13,6 +13,8 @@ body:
required: true required: true
- label: I've verified that I'm running yt-dlp version **2021.10.10**. ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) - label: I've verified that I'm running yt-dlp version **2021.10.10**. ([update instructions](https://github.com/yt-dlp/yt-dlp#update))
required: true required: true
- label: I've checked that all provided URLs are alive and playable in a browser
required: true
- label: I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues including closed ones. DO NOT post duplicates - label: I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues including closed ones. DO NOT post duplicates
required: true required: true
- label: I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue) - label: I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)
@ -24,6 +26,16 @@ body:
label: Region label: Region
description: "Enter the region the site is accessible from" description: "Enter the region the site is accessible from"
placeholder: "India" placeholder: "India"
- type: textarea
id: example-urls
attributes:
label: Example URLs
description: |
Example URLs that can be used to demonstrate the requested feature
value: |
https://www.youtube.com/watch?v=BaW_jenozKc
validations:
required: true
- type: textarea - type: textarea
id: description id: description
attributes: attributes:

View File

@ -11,11 +11,11 @@ body:
options: options:
- label: I'm asking a question and not reporting a bug/feature request - label: I'm asking a question and not reporting a bug/feature request
required: true required: true
- label: I've looked through the [README](https://github.com/yt-dlp/yt-dlp) - label: I've looked through the [README](https://github.com/yt-dlp/yt-dlp#readme)
required: true required: true
- label: I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue) - label: I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)
required: true required: true
- label: I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues) for similar questions including closed ones - label: I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar questions including closed ones
required: true required: true
- type: textarea - type: textarea
id: question id: question

View File

@ -33,7 +33,7 @@ body:
attributes: attributes:
label: Example URLs label: Example URLs
description: | description: |
Provide all kinds of example URLs, support for which should be included. Replace following example URLs by yours Provide all kinds of example URLs for which support should be added
value: | value: |
- Single video: https://www.youtube.com/watch?v=BaW_jenozKc - Single video: https://www.youtube.com/watch?v=BaW_jenozKc
- Single video: https://youtu.be/BaW_jenozKc - Single video: https://youtu.be/BaW_jenozKc

View File

@ -13,6 +13,8 @@ body:
required: true required: true
- label: I've verified that I'm running yt-dlp version **%(version)s**. ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) - label: I've verified that I'm running yt-dlp version **%(version)s**. ([update instructions](https://github.com/yt-dlp/yt-dlp#update))
required: true required: true
- label: I've checked that all provided URLs are alive and playable in a browser
required: true
- label: I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues including closed ones. DO NOT post duplicates - label: I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues including closed ones. DO NOT post duplicates
required: true required: true
- label: I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue) - label: I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)
@ -24,6 +26,16 @@ body:
label: Region label: Region
description: "Enter the region the site is accessible from" description: "Enter the region the site is accessible from"
placeholder: "India" placeholder: "India"
- type: textarea
id: example-urls
attributes:
label: Example URLs
description: |
Example URLs that can be used to demonstrate the requested feature
value: |
https://www.youtube.com/watch?v=BaW_jenozKc
validations:
required: true
- type: textarea - type: textarea
id: description id: description
attributes: attributes:

View File

@ -11,11 +11,11 @@ body:
options: options:
- label: I'm asking a question and not reporting a bug/feature request - label: I'm asking a question and not reporting a bug/feature request
required: true required: true
- label: I've looked through the [README](https://github.com/yt-dlp/yt-dlp) - label: I've looked through the [README](https://github.com/yt-dlp/yt-dlp#readme)
required: true required: true
- label: I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue) - label: I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)
required: true required: true
- label: I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues) for similar questions including closed ones - label: I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar questions including closed ones
required: true required: true
- type: textarea - type: textarea
id: question id: question

View File

@ -53,7 +53,7 @@ jobs:
- name: Build lazy extractors - name: Build lazy extractors
id: lazy_extractors id: lazy_extractors
run: python devscripts/make_lazy_extractors.py yt_dlp/extractor/lazy_extractors.py run: python devscripts/make_lazy_extractors.py
- name: Run Make - name: Run Make
run: make all tar run: make all tar
- name: Get SHA2-256SUMS for yt-dlp - name: Get SHA2-256SUMS for yt-dlp
@ -115,10 +115,12 @@ jobs:
release_name: yt-dlp ${{ steps.bump_version.outputs.ytdlp_version }} release_name: yt-dlp ${{ steps.bump_version.outputs.ytdlp_version }}
commitish: ${{ steps.push_update.outputs.head_sha }} commitish: ${{ steps.push_update.outputs.head_sha }}
body: | body: |
See [this](https://github.com/yt-dlp/yt-dlp#release-files) for a description of the files ### Changelog:
#### Changelog:
${{ env.changelog }} ${{ env.changelog }}
---
### See [this](https://github.com/yt-dlp/yt-dlp#release-files) for a description of the release files
draft: false draft: false
prerelease: false prerelease: false
- name: Upload yt-dlp Unix binary - name: Upload yt-dlp Unix binary
@ -162,7 +164,7 @@ jobs:
run: /usr/bin/python3 devscripts/update-version.py run: /usr/bin/python3 devscripts/update-version.py
- name: Build lazy extractors - name: Build lazy extractors
id: lazy_extractors id: lazy_extractors
run: /usr/bin/python3 devscripts/make_lazy_extractors.py yt_dlp/extractor/lazy_extractors.py run: /usr/bin/python3 devscripts/make_lazy_extractors.py
- name: Run PyInstaller Script - name: Run PyInstaller Script
run: /usr/bin/python3 pyinst.py --target-architecture universal2 --onefile run: /usr/bin/python3 pyinst.py --target-architecture universal2 --onefile
- name: Upload yt-dlp MacOS binary - name: Upload yt-dlp MacOS binary
@ -233,7 +235,7 @@ jobs:
run: python devscripts/update-version.py run: python devscripts/update-version.py
- name: Build lazy extractors - name: Build lazy extractors
id: lazy_extractors id: lazy_extractors
run: python devscripts/make_lazy_extractors.py yt_dlp/extractor/lazy_extractors.py run: python devscripts/make_lazy_extractors.py
- name: Run PyInstaller Script - name: Run PyInstaller Script
run: python pyinst.py run: python pyinst.py
- name: Upload yt-dlp.exe Windows binary - name: Upload yt-dlp.exe Windows binary
@ -320,7 +322,7 @@ jobs:
run: python devscripts/update-version.py run: python devscripts/update-version.py
- name: Build lazy extractors - name: Build lazy extractors
id: lazy_extractors id: lazy_extractors
run: python devscripts/make_lazy_extractors.py yt_dlp/extractor/lazy_extractors.py run: python devscripts/make_lazy_extractors.py
- name: Run PyInstaller Script for 32 Bit - name: Run PyInstaller Script for 32 Bit
run: python pyinst.py run: python pyinst.py
- name: Upload Executable yt-dlp_x86.exe - name: Upload Executable yt-dlp_x86.exe

View File

@ -28,6 +28,6 @@ jobs:
- name: Install flake8 - name: Install flake8
run: pip install flake8 run: pip install flake8
- name: Make lazy extractors - name: Make lazy extractors
run: python devscripts/make_lazy_extractors.py yt_dlp/extractor/lazy_extractors.py run: python devscripts/make_lazy_extractors.py
- name: Run flake8 - name: Run flake8
run: flake8 . run: flake8 .

View File

@ -205,7 +205,7 @@ #### Alternatives
:---|:--- :---|:---
[yt-dlp_macos](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos)|MacOS standalone executable [yt-dlp_macos](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos)|MacOS standalone executable
[yt-dlp_x86.exe](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_x86.exe)|Windows standalone x86 (32bit) binary [yt-dlp_x86.exe](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_x86.exe)|Windows standalone x86 (32bit) binary
[yt-dlp_min.exe](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_x86.exe)|Windows standalone x64 binary built with `py2exe`.<br/> Does not contain `pycryptodomex`, needs VC++14 [yt-dlp_min.exe](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_min.exe)|Windows standalone x64 binary built with `py2exe`.<br/> Does not contain `pycryptodomex`, needs VC++14
[yt-dlp_win.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_win.zip)|Unpackaged windows executable (No auto-update) [yt-dlp_win.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_win.zip)|Unpackaged windows executable (No auto-update)
[yt-dlp_macos.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos.zip)|Unpackaged MacOS executable (No auto-update) [yt-dlp_macos.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos.zip)|Unpackaged MacOS executable (No auto-update)
@ -248,11 +248,10 @@ ### DEPENDENCIES
### COMPILE ### COMPILE
**For Windows**: **For Windows**:
To build the Windows executable, you must have pyinstaller (and optionally mutagen, pycryptodomex, websockets) To build the Windows executable, you must have pyinstaller (and optionally mutagen, pycryptodomex, websockets). Once you have all the necessary dependencies installed, (optionally) build lazy extractors using `devscripts/make_lazy_extractors.py`, and then just run `pyinst.py`. The executable will be built for the same architecture (32/64 bit) as the python used to build it.
Once you have all the necessary dependencies installed, just run `pyinst.py`. The executable will be built for the same architecture (32/64 bit) as the python used to build it.
py -m pip install -U pyinstaller -r requirements.txt py -m pip install -U pyinstaller -r requirements.txt
py devscripts/make_lazy_extractors.py
py pyinst.py py pyinst.py
Note that pyinstaller [does not support](https://github.com/pyinstaller/pyinstaller#requirements-and-tested-platforms) Python installed from the Windows store without using a virtual environment Note that pyinstaller [does not support](https://github.com/pyinstaller/pyinstaller#requirements-and-tested-platforms) Python installed from the Windows store without using a virtual environment
@ -261,7 +260,7 @@ ### COMPILE
You will need the required build tools: `python`, `make` (GNU), `pandoc`, `zip`, `pytest` You will need the required build tools: `python`, `make` (GNU), `pandoc`, `zip`, `pytest`
Then simply run `make`. You can also run `make yt-dlp` instead to compile only the binary without updating any of the additional files Then simply run `make`. You can also run `make yt-dlp` instead to compile only the binary without updating any of the additional files
**Note**: In either platform, `devscripts\update-version.py` can be used to automatically update the version number **Note**: In either platform, `devscripts/update-version.py` can be used to automatically update the version number
# USAGE AND OPTIONS # USAGE AND OPTIONS
@ -1156,11 +1155,13 @@ # OUTPUT TEMPLATE
- `category_names` (list): Friendly names of the categories - `category_names` (list): Friendly names of the categories
- `name` (string): Friendly name of the smallest category - `name` (string): Friendly name of the smallest category
Each aforementioned sequence when referenced in an output template will be replaced by the actual value corresponding to the sequence name. Note that some of the sequences are not guaranteed to be present since they depend on the metadata obtained by a particular extractor. Such sequences will be replaced with placeholder value provided with `--output-na-placeholder` (`NA` by default). Each aforementioned sequence when referenced in an output template will be replaced by the actual value corresponding to the sequence name. For example for `-o %(title)s-%(id)s.%(ext)s` and an mp4 video with title `yt-dlp test video` and id `BaW_jenozKc`, this will result in a `yt-dlp test video-BaW_jenozKc.mp4` file created in the current directory.
For example for `-o %(title)s-%(id)s.%(ext)s` and an mp4 video with title `yt-dlp test video` and id `BaW_jenozKc`, this will result in a `yt-dlp test video-BaW_jenozKc.mp4` file created in the current directory. Note that some of the sequences are not guaranteed to be present since they depend on the metadata obtained by a particular extractor. Such sequences will be replaced with placeholder value provided with `--output-na-placeholder` (`NA` by default).
For numeric sequences you can use numeric related formatting, for example, `%(view_count)05d` will result in a string with view count padded with zeros up to 5 characters, like in `00042`. **Tip**: Look at the `-j` output to identify which fields are available for the purticular URL
For numeric sequences you can use [numeric related formatting](https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting), for example, `%(view_count)05d` will result in a string with view count padded with zeros up to 5 characters, like in `00042`.
Output templates can also contain arbitrary hierarchical path, e.g. `-o '%(playlist)s/%(playlist_index)s - %(title)s.%(ext)s'` which will result in downloading each video in a directory corresponding to this path template. Any missing directory will be automatically created for you. Output templates can also contain arbitrary hierarchical path, e.g. `-o '%(playlist)s/%(playlist_index)s - %(title)s.%(ext)s'` which will result in downloading each video in a directory corresponding to this path template. Any missing directory will be automatically created for you.
@ -1309,7 +1310,7 @@ ## Sorting Formats
- `width`: Width of video - `width`: Width of video
- `res`: Video resolution, calculated as the smallest dimension. - `res`: Video resolution, calculated as the smallest dimension.
- `fps`: Framerate of video - `fps`: Framerate of video
- `hdr`: The dynamic range of the video (`DV` > `HDR12` > `HDR10+` > `HDR10` > `SDR`) - `hdr`: The dynamic range of the video (`DV` > `HDR12` > `HDR10+` > `HDR10` > `HLG` > `SDR`)
- `tbr`: Total average bitrate in KBit/s - `tbr`: Total average bitrate in KBit/s
- `vbr`: Average video bitrate in KBit/s - `vbr`: Average video bitrate in KBit/s
- `abr`: Average audio bitrate in KBit/s - `abr`: Average audio bitrate in KBit/s
@ -1627,6 +1628,8 @@ # EMBEDDING YT-DLP
See the public functions in [`yt_dlp/YoutubeDL.py`](yt_dlp/YoutubeDL.py) for other available functions. Eg: `ydl.download`, `ydl.download_with_info_file` See the public functions in [`yt_dlp/YoutubeDL.py`](yt_dlp/YoutubeDL.py) for other available functions. Eg: `ydl.download`, `ydl.download_with_info_file`
**Tip**: If you are porting your code from youtube-dl to yt-dlp, one important point to look out for is that we do not guarantee the return value of `YoutubeDL.extract_info` to be json serializable, or even be a dictionary. It will be dictionary-like, but if you want to ensure it is a serializable dictionary, pass it through `YoutubeDL.sanitize_info` as shown in the example above
# DEPRECATED OPTIONS # DEPRECATED OPTIONS

View File

@ -9,7 +9,7 @@
sys.path.insert(0, dirn(dirn((os.path.abspath(__file__))))) sys.path.insert(0, dirn(dirn((os.path.abspath(__file__)))))
lazy_extractors_filename = sys.argv[1] lazy_extractors_filename = sys.argv[1] if len(sys.argv) > 1 else 'yt_dlp/extractor/lazy_extractors.py'
if os.path.exists(lazy_extractors_filename): if os.path.exists(lazy_extractors_filename):
os.remove(lazy_extractors_filename) os.remove(lazy_extractors_filename)

View File

@ -24,16 +24,15 @@ def main():
opts = parse_options() opts = parse_options()
version = read_version() version = read_version()
suffix = '_x86' if ARCH == '32' else '_macos' if OS_NAME == 'Darwin' else '' suffix = '_macos' if OS_NAME == 'Darwin' else '_x86' if ARCH == '32' else ''
final_file = 'dist/%syt-dlp%s%s' % ( final_file = 'dist/%syt-dlp%s%s' % (
'yt-dlp/' if '--onedir' in opts else '', suffix, '.exe' if OS_NAME == 'Windows' else '') 'yt-dlp/' if '--onedir' in opts else '', suffix, '.exe' if OS_NAME == 'Windows' else '')
print(f'Building yt-dlp v{version} {ARCH}bit for {OS_NAME} with options {opts}') print(f'Building yt-dlp v{version} {ARCH}bit for {OS_NAME} with options {opts}')
print('Remember to update the version using "devscripts/update-version.py"') print('Remember to update the version using "devscripts/update-version.py"')
if not os.path.isfile('yt_dlp/extractor/lazy_extractors.py'): if not os.path.isfile('yt_dlp/extractor/lazy_extractors.py'):
print('WARNING: Building without lazy_extractors. Run ' print('WARNING: Building without lazy_extractors. Run '
'"devscripts/make_lazy_extractors.py" "yt_dlp/extractor/lazy_extractors.py" ' '"devscripts/make_lazy_extractors.py" to build lazy extractors', file=sys.stderr)
'to build lazy extractors', file=sys.stderr)
print(f'Destination: {final_file}\n') print(f'Destination: {final_file}\n')
opts = [ opts = [

View File

@ -307,7 +307,7 @@ class YoutubeDL(object):
cookiefile: File name where cookies should be read from and dumped to cookiefile: File name where cookies should be read from and dumped to
cookiesfrombrowser: A tuple containing the name of the browser and the profile cookiesfrombrowser: A tuple containing the name of the browser and the profile
name/path from where cookies are loaded. name/path from where cookies are loaded.
Eg: ('chrome', ) or (vivaldi, 'default') Eg: ('chrome', ) or ('vivaldi', 'default')
nocheckcertificate:Do not verify SSL certificates nocheckcertificate:Do not verify SSL certificates
prefer_insecure: Use HTTP instead of HTTPS to retrieve information. prefer_insecure: Use HTTP instead of HTTPS to retrieve information.
At the moment, this is only supported by YouTube. At the moment, this is only supported by YouTube.
@ -503,7 +503,7 @@ class YoutubeDL(object):
def __init__(self, params=None, auto_init=True): def __init__(self, params=None, auto_init=True):
"""Create a FileDownloader object with the given options. """Create a FileDownloader object with the given options.
@param auto_init Whether to load the default extractors and print header (if verbose). @param auto_init Whether to load the default extractors and print header (if verbose).
Set to 'no_verbose_header' to not ptint the header Set to 'no_verbose_header' to not print the header
""" """
if params is None: if params is None:
params = {} params = {}
@ -551,7 +551,7 @@ def check_deprecated(param, option, suggestion):
check_deprecated('usetitle', '--title', '-o "%(title)s-%(id)s.%(ext)s"') check_deprecated('usetitle', '--title', '-o "%(title)s-%(id)s.%(ext)s"')
check_deprecated('useid', '--id', '-o "%(id)s.%(ext)s"') check_deprecated('useid', '--id', '-o "%(id)s.%(ext)s"')
for msg in self.params.get('warnings', []): for msg in self.params.get('_warnings', []):
self.report_warning(msg) self.report_warning(msg)
if 'overwrites' not in self.params and self.params.get('nooverwrites') is not None: if 'overwrites' not in self.params and self.params.get('nooverwrites') is not None:
@ -584,7 +584,9 @@ def check_deprecated(param, option, suggestion):
self._output_channel = os.fdopen(master, 'rb') self._output_channel = os.fdopen(master, 'rb')
except OSError as ose: except OSError as ose:
if ose.errno == errno.ENOENT: if ose.errno == errno.ENOENT:
self.report_warning('Could not find fribidi executable, ignoring --bidi-workaround . Make sure that fribidi is an executable file in one of the directories in your $PATH.') self.report_warning(
'Could not find fribidi executable, ignoring --bidi-workaround. '
'Make sure that fribidi is an executable file in one of the directories in your $PATH.')
else: else:
raise raise
@ -631,7 +633,7 @@ def preload_download_archive(fn):
"""Preload the archive, if any is specified""" """Preload the archive, if any is specified"""
if fn is None: if fn is None:
return False return False
self.write_debug('Loading archive file %r\n' % fn) self.write_debug(f'Loading archive file {fn!r}')
try: try:
with locked_file(fn, 'r', encoding='utf-8') as archive_file: with locked_file(fn, 'r', encoding='utf-8') as archive_file:
for line in archive_file: for line in archive_file:
@ -658,7 +660,7 @@ def warn_if_short_id(self, argv):
) )
self.report_warning( self.report_warning(
'Long argument string detected. ' 'Long argument string detected. '
'Use -- to separate parameters and URLs, like this:\n%s\n' % 'Use -- to separate parameters and URLs, like this:\n%s' %
args_to_str(correct_argv)) args_to_str(correct_argv))
def add_info_extractor(self, ie): def add_info_extractor(self, ie):
@ -1550,7 +1552,7 @@ def get_entry(i):
playlistitems = list(range(playliststart, playliststart + n_entries)) playlistitems = list(range(playliststart, playliststart + n_entries))
ie_result['requested_entries'] = playlistitems ie_result['requested_entries'] = playlistitems
if self.params.get('allow_playlist_files', True): if not self.params.get('simulate') and self.params.get('allow_playlist_files', True):
ie_copy = { ie_copy = {
'playlist': playlist, 'playlist': playlist,
'playlist_id': ie_result.get('id'), 'playlist_id': ie_result.get('id'),
@ -1558,6 +1560,7 @@ def get_entry(i):
'playlist_uploader': ie_result.get('uploader'), 'playlist_uploader': ie_result.get('uploader'),
'playlist_uploader_id': ie_result.get('uploader_id'), 'playlist_uploader_id': ie_result.get('uploader_id'),
'playlist_index': 0, 'playlist_index': 0,
'n_entries': n_entries,
} }
ie_copy.update(dict(ie_result)) ie_copy.update(dict(ie_result))
@ -1883,6 +1886,7 @@ def _merge(formats_pair):
'height': the_only_video.get('height'), 'height': the_only_video.get('height'),
'resolution': the_only_video.get('resolution') or self.format_resolution(the_only_video), 'resolution': the_only_video.get('resolution') or self.format_resolution(the_only_video),
'fps': the_only_video.get('fps'), 'fps': the_only_video.get('fps'),
'dynamic_range': the_only_video.get('dynamic_range'),
'vcodec': the_only_video.get('vcodec'), 'vcodec': the_only_video.get('vcodec'),
'vbr': the_only_video.get('vbr'), 'vbr': the_only_video.get('vbr'),
'stretched_ratio': the_only_video.get('stretched_ratio'), 'stretched_ratio': the_only_video.get('stretched_ratio'),
@ -2381,7 +2385,7 @@ def is_wellformed(f):
new_info['__original_infodict'] = info_dict new_info['__original_infodict'] = info_dict
new_info.update(fmt) new_info.update(fmt)
self.process_info(new_info) self.process_info(new_info)
# We update the info dict with the best quality format (backwards compatibility) # We update the info dict with the selected best quality format (backwards compatibility)
if formats_to_download: if formats_to_download:
info_dict.update(formats_to_download[-1]) info_dict.update(formats_to_download[-1])
return info_dict return info_dict
@ -3250,35 +3254,40 @@ def urlopen(self, req):
def print_debug_header(self): def print_debug_header(self):
if not self.params.get('verbose'): if not self.params.get('verbose'):
return return
get_encoding = lambda stream: getattr(stream, 'encoding', 'missing (%s)' % type(stream).__name__)
encoding_str = ( def get_encoding(stream):
'[debug] Encodings: locale %s, fs %s, stdout %s, stderr %s, pref %s\n' % ( ret = getattr(stream, 'encoding', 'missing (%s)' % type(stream).__name__)
locale.getpreferredencoding(), if not supports_terminal_sequences(stream):
sys.getfilesystemencoding(), ret += ' (No ANSI)'
get_encoding(self._screen_file), get_encoding(self._err_file), return ret
self.get_encoding()))
encoding_str = 'Encodings: locale %s, fs %s, out %s, err %s, pref %s' % (
locale.getpreferredencoding(),
sys.getfilesystemencoding(),
get_encoding(self._screen_file), get_encoding(self._err_file),
self.get_encoding())
logger = self.params.get('logger') logger = self.params.get('logger')
if logger: if logger:
write_debug = lambda msg: logger.debug(f'[debug] {msg}') write_debug = lambda msg: logger.debug(f'[debug] {msg}')
write_debug(encoding_str) write_debug(encoding_str)
else: else:
write_debug = lambda msg: self._write_string(f'[debug] {msg}') write_string(f'[debug] {encoding_str}', encoding=None)
write_string(encoding_str, encoding=None) write_debug = lambda msg: self._write_string(f'[debug] {msg}\n')
source = detect_variant() source = detect_variant()
write_debug('yt-dlp version %s%s\n' % (__version__, '' if source == 'unknown' else f' ({source})')) write_debug('yt-dlp version %s%s' % (__version__, '' if source == 'unknown' else f' ({source})'))
if not _LAZY_LOADER: if not _LAZY_LOADER:
if os.environ.get('YTDLP_NO_LAZY_EXTRACTORS'): if os.environ.get('YTDLP_NO_LAZY_EXTRACTORS'):
write_debug('Lazy loading extractors is forcibly disabled\n') write_debug('Lazy loading extractors is forcibly disabled')
else: else:
write_debug('Lazy loading extractors is disabled\n') write_debug('Lazy loading extractors is disabled')
if plugin_extractors or plugin_postprocessors: if plugin_extractors or plugin_postprocessors:
write_debug('Plugins: %s\n' % [ write_debug('Plugins: %s' % [
'%s%s' % (klass.__name__, '' if klass.__name__ == name else f' as {name}') '%s%s' % (klass.__name__, '' if klass.__name__ == name else f' as {name}')
for name, klass in itertools.chain(plugin_extractors.items(), plugin_postprocessors.items())]) for name, klass in itertools.chain(plugin_extractors.items(), plugin_postprocessors.items())])
if self.params.get('compat_opts'): if self.params.get('compat_opts'):
write_debug('Compatibility options: %s\n' % ', '.join(self.params.get('compat_opts'))) write_debug('Compatibility options: %s' % ', '.join(self.params.get('compat_opts')))
try: try:
sp = Popen( sp = Popen(
['git', 'rev-parse', '--short', 'HEAD'], ['git', 'rev-parse', '--short', 'HEAD'],
@ -3287,7 +3296,7 @@ def print_debug_header(self):
out, err = sp.communicate_or_kill() out, err = sp.communicate_or_kill()
out = out.decode().strip() out = out.decode().strip()
if re.match('[0-9a-f]+', out): if re.match('[0-9a-f]+', out):
write_debug('Git HEAD: %s\n' % out) write_debug('Git HEAD: %s' % out)
except Exception: except Exception:
try: try:
sys.exc_clear() sys.exc_clear()
@ -3300,7 +3309,7 @@ def python_implementation():
return impl_name + ' version %d.%d.%d' % sys.pypy_version_info[:3] return impl_name + ' version %d.%d.%d' % sys.pypy_version_info[:3]
return impl_name return impl_name
write_debug('Python version %s (%s %s) - %s\n' % ( write_debug('Python version %s (%s %s) - %s' % (
platform.python_version(), platform.python_version(),
python_implementation(), python_implementation(),
platform.architecture()[0], platform.architecture()[0],
@ -3312,7 +3321,7 @@ def python_implementation():
exe_str = ', '.join( exe_str = ', '.join(
f'{exe} {v}' for exe, v in sorted(exe_versions.items()) if v f'{exe} {v}' for exe, v in sorted(exe_versions.items()) if v
) or 'none' ) or 'none'
write_debug('exe versions: %s\n' % exe_str) write_debug('exe versions: %s' % exe_str)
from .downloader.websocket import has_websockets from .downloader.websocket import has_websockets
from .postprocessor.embedthumbnail import has_mutagen from .postprocessor.embedthumbnail import has_mutagen
@ -3325,21 +3334,18 @@ def python_implementation():
SQLITE_AVAILABLE and 'sqlite', SQLITE_AVAILABLE and 'sqlite',
KEYRING_AVAILABLE and 'keyring', KEYRING_AVAILABLE and 'keyring',
)))) or 'none' )))) or 'none'
write_debug('Optional libraries: %s\n' % lib_str) write_debug('Optional libraries: %s' % lib_str)
write_debug('ANSI escape support: stdout = %s, stderr = %s\n' % (
supports_terminal_sequences(self._screen_file),
supports_terminal_sequences(self._err_file)))
proxy_map = {} proxy_map = {}
for handler in self._opener.handlers: for handler in self._opener.handlers:
if hasattr(handler, 'proxies'): if hasattr(handler, 'proxies'):
proxy_map.update(handler.proxies) proxy_map.update(handler.proxies)
write_debug('Proxy map: ' + compat_str(proxy_map) + '\n') write_debug(f'Proxy map: {proxy_map}')
if self.params.get('call_home', False): # Not implemented
if False and self.params.get('call_home'):
ipaddr = self.urlopen('https://yt-dl.org/ip').read().decode('utf-8') ipaddr = self.urlopen('https://yt-dl.org/ip').read().decode('utf-8')
write_debug('Public IP address: %s\n' % ipaddr) write_debug('Public IP address: %s' % ipaddr)
return
latest_version = self.urlopen( latest_version = self.urlopen(
'https://yt-dl.org/latest/version').read().decode('utf-8') 'https://yt-dl.org/latest/version').read().decode('utf-8')
if version_tuple(latest_version) > version_tuple(__version__): if version_tuple(latest_version) > version_tuple(__version__):

View File

@ -745,7 +745,7 @@ def report_args_compat(arg, name):
'geo_bypass': opts.geo_bypass, 'geo_bypass': opts.geo_bypass,
'geo_bypass_country': opts.geo_bypass_country, 'geo_bypass_country': opts.geo_bypass_country,
'geo_bypass_ip_block': opts.geo_bypass_ip_block, 'geo_bypass_ip_block': opts.geo_bypass_ip_block,
'warnings': warnings, '_warnings': warnings,
'compat_opts': compat_opts, 'compat_opts': compat_opts,
} }

View File

@ -370,7 +370,8 @@ def download_and_append_fragments_multiple(self, *args, pack_func=None, finish_f
if max_progress == 1: if max_progress == 1:
return self.download_and_append_fragments(*args[0], pack_func=pack_func, finish_func=finish_func) return self.download_and_append_fragments(*args[0], pack_func=pack_func, finish_func=finish_func)
max_workers = self.params.get('concurrent_fragment_downloads', max_progress) max_workers = self.params.get('concurrent_fragment_downloads', max_progress)
self._prepare_multiline_status(max_progress) if max_progress > 1:
self._prepare_multiline_status(max_progress)
def thread_func(idx, ctx, fragments, info_dict, tpe): def thread_func(idx, ctx, fragments, info_dict, tpe):
ctx['max_progress'] = max_progress ctx['max_progress'] = max_progress

View File

@ -448,7 +448,9 @@ class InfoExtractor(object):
} }
def __init__(self, downloader=None): def __init__(self, downloader=None):
"""Constructor. Receives an optional downloader.""" """Constructor. Receives an optional downloader (a YoutubeDL instance).
If a downloader is not passed during initialization,
it must be set using "set_downloader()" before "extract()" is called"""
self._ready = False self._ready = False
self._x_forwarded_for_ip = None self._x_forwarded_for_ip = None
self._printed_messages = set() self._printed_messages = set()
@ -664,7 +666,7 @@ def _request_webpage(self, url_or_request, video_id, note=None, errnote=None, fa
See _download_webpage docstring for arguments specification. See _download_webpage docstring for arguments specification.
""" """
if not self._downloader._first_webpage_request: if not self._downloader._first_webpage_request:
sleep_interval = float_or_none(self.get_param('sleep_interval_requests')) or 0 sleep_interval = self.get_param('sleep_interval_requests') or 0
if sleep_interval > 0: if sleep_interval > 0:
self.to_screen('Sleeping %s seconds ...' % sleep_interval) self.to_screen('Sleeping %s seconds ...' % sleep_interval)
time.sleep(sleep_interval) time.sleep(sleep_interval)

View File

@ -855,7 +855,7 @@ def _real_extract(self, url):
class SoundcloudSearchIE(SearchInfoExtractor, SoundcloudIE): class SoundcloudSearchIE(SearchInfoExtractor, SoundcloudIE):
IE_NAME = 'soundcloud:search' IE_NAME = 'soundcloud:search'
IE_DESC = 'Soundcloud search' IE_DESC = 'Soundcloud search, "scsearch" keyword'
_MAX_RESULTS = float('inf') _MAX_RESULTS = float('inf')
_TESTS = [{ _TESTS = [{
'url': 'scsearch15:post-avant jazzcore', 'url': 'scsearch15:post-avant jazzcore',

View File

@ -4304,9 +4304,7 @@ class YoutubePlaylistIE(InfoExtractor):
def suitable(cls, url): def suitable(cls, url):
if YoutubeTabIE.suitable(url): if YoutubeTabIE.suitable(url):
return False return False
# Hack for lazy extractors until more generic solution is implemented from ..utils import parse_qs
# (see #28780)
from .youtube import parse_qs
qs = parse_qs(url) qs = parse_qs(url)
if qs.get('v', [None])[0]: if qs.get('v', [None])[0]:
return False return False