mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-15 13:43:04 +00:00
Compare commits
2 Commits
e08f72e675
...
962ffcf89c
Author | SHA1 | Date | |
---|---|---|---|
|
962ffcf89c | ||
|
8a40bffaf9 |
@ -457,7 +457,7 @@ title = self._search_regex( # incorrect
|
|||||||
webpage, 'title', group='title')
|
webpage, 'title', group='title')
|
||||||
```
|
```
|
||||||
|
|
||||||
Here the presence or absence of other attributes including `style` is irrelevent for the data we need, and so the regex must not depend on it
|
Here the presence or absence of other attributes including `style` is irrelevant for the data we need, and so the regex must not depend on it
|
||||||
|
|
||||||
|
|
||||||
#### Keep the regular expressions as simple as possible, but no simpler
|
#### Keep the regular expressions as simple as possible, but no simpler
|
||||||
@ -501,7 +501,7 @@ There is a soft limit to keep lines of code under 100 characters long. This mean
|
|||||||
|
|
||||||
For example, you should **never** split long string literals like URLs or some other often copied entities over multiple lines to fit this limit:
|
For example, you should **never** split long string literals like URLs or some other often copied entities over multiple lines to fit this limit:
|
||||||
|
|
||||||
Conversely, don't unecessarily split small lines further. As a rule of thumb, if removing the line split keeps the code under 80 characters, it should be a single line.
|
Conversely, don't unnecessarily split small lines further. As a rule of thumb, if removing the line split keeps the code under 80 characters, it should be a single line.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
|
@ -544,7 +544,7 @@
|
|||||||
* [downloader/ffmpeg] Handle unknown formats better
|
* [downloader/ffmpeg] Handle unknown formats better
|
||||||
* [outtmpl] Handle `-o ""` better
|
* [outtmpl] Handle `-o ""` better
|
||||||
* [outtmpl] Handle hard-coded file extension better
|
* [outtmpl] Handle hard-coded file extension better
|
||||||
* [extractor] Add convinience function `_yes_playlist`
|
* [extractor] Add convenience function `_yes_playlist`
|
||||||
* [extractor] Allow non-fatal `title` extraction
|
* [extractor] Allow non-fatal `title` extraction
|
||||||
* [extractor] Extract video inside `Article` json_ld
|
* [extractor] Extract video inside `Article` json_ld
|
||||||
* [generic] Allow further processing of json_ld URL
|
* [generic] Allow further processing of json_ld URL
|
||||||
@ -1678,7 +1678,7 @@
|
|||||||
* [utils] Generalize `traverse_dict` to `traverse_obj`
|
* [utils] Generalize `traverse_dict` to `traverse_obj`
|
||||||
* [downloader/ffmpeg] Hide FFmpeg banner unless in verbose mode by [fstirlitz](https://github.com/fstirlitz)
|
* [downloader/ffmpeg] Hide FFmpeg banner unless in verbose mode by [fstirlitz](https://github.com/fstirlitz)
|
||||||
* [build] Release `yt-dlp.tar.gz`
|
* [build] Release `yt-dlp.tar.gz`
|
||||||
* [build,update] Add GNU-style SHA512 and prepare updater for simlar SHA256 by [nihil-admirari](https://github.com/nihil-admirari)
|
* [build,update] Add GNU-style SHA512 and prepare updater for similar SHA256 by [nihil-admirari](https://github.com/nihil-admirari)
|
||||||
* [pyinst] Show Python version in exe metadata by [nihil-admirari](https://github.com/nihil-admirari)
|
* [pyinst] Show Python version in exe metadata by [nihil-admirari](https://github.com/nihil-admirari)
|
||||||
* [docs] Improve documentation of dependencies
|
* [docs] Improve documentation of dependencies
|
||||||
* [cleanup] Mark unused files
|
* [cleanup] Mark unused files
|
||||||
|
@ -150,7 +150,7 @@ Some of yt-dlp's default options are different from that of youtube-dl and youtu
|
|||||||
* Some private fields such as filenames are removed by default from the infojson. Use `--no-clean-infojson` or `--compat-options no-clean-infojson` to revert this
|
* Some private fields such as filenames are removed by default from the infojson. Use `--no-clean-infojson` or `--compat-options no-clean-infojson` to revert this
|
||||||
* When `--embed-subs` and `--write-subs` are used together, the subtitles are written to disk and also embedded in the media file. You can use just `--embed-subs` to embed the subs and automatically delete the separate file. See [#630 (comment)](https://github.com/yt-dlp/yt-dlp/issues/630#issuecomment-893659460) for more info. `--compat-options no-keep-subs` can be used to revert this
|
* When `--embed-subs` and `--write-subs` are used together, the subtitles are written to disk and also embedded in the media file. You can use just `--embed-subs` to embed the subs and automatically delete the separate file. See [#630 (comment)](https://github.com/yt-dlp/yt-dlp/issues/630#issuecomment-893659460) for more info. `--compat-options no-keep-subs` can be used to revert this
|
||||||
* `certifi` will be used for SSL root certificates, if installed. If you want to use only system certificates, use `--compat-options no-certifi`
|
* `certifi` will be used for SSL root certificates, if installed. If you want to use only system certificates, use `--compat-options no-certifi`
|
||||||
* youtube-dl tries to remove some superfluous punctuations from filenames. While this can sometimes be helpfull, it is often undesirable. So yt-dlp tries to keep the fields in the filenames as close to their original values as possible. You can use `--compat-options filename-sanitization` to revert to youtube-dl's behavior
|
* youtube-dl tries to remove some superfluous punctuations from filenames. While this can sometimes be helpful, it is often undesirable. So yt-dlp tries to keep the fields in the filenames as close to their original values as possible. You can use `--compat-options filename-sanitization` to revert to youtube-dl's behavior
|
||||||
|
|
||||||
For ease of use, a few more compat options are available:
|
For ease of use, a few more compat options are available:
|
||||||
|
|
||||||
@ -239,7 +239,7 @@ If you [installed using Homebrew](#with-homebrew), run `brew upgrade yt-dlp/taps
|
|||||||
|
|
||||||
File|Description
|
File|Description
|
||||||
:---|:---
|
:---|:---
|
||||||
[yt-dlp](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp)|Platform-independant [zipimport](https://docs.python.org/3/library/zipimport.html) binary. Needs Python (recommended for **Linux/BSD**)
|
[yt-dlp](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp)|Platform-independent [zipimport](https://docs.python.org/3/library/zipimport.html) binary. Needs Python (recommended for **Linux/BSD**)
|
||||||
[yt-dlp.exe](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe)|Windows (Win7 SP1+) standalone x64 binary (recommended for **Windows**)
|
[yt-dlp.exe](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe)|Windows (Win7 SP1+) standalone x64 binary (recommended for **Windows**)
|
||||||
[yt-dlp_macos](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos)|MacOS (10.15+) standalone executable (recommended for **MacOS**)
|
[yt-dlp_macos](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos)|MacOS (10.15+) standalone executable (recommended for **MacOS**)
|
||||||
|
|
||||||
@ -433,7 +433,7 @@ You can also fork the project on github and run your fork's [build workflow](.gi
|
|||||||
"-S=aext:ARG0,abr -x --audio-format ARG0".
|
"-S=aext:ARG0,abr -x --audio-format ARG0".
|
||||||
All defined aliases are listed in the --help
|
All defined aliases are listed in the --help
|
||||||
output. Alias options can trigger more
|
output. Alias options can trigger more
|
||||||
aliases; so be carefull to avoid defining
|
aliases; so be careful to avoid defining
|
||||||
recursive options. As a safety measure, each
|
recursive options. As a safety measure, each
|
||||||
alias may be triggered a maximum of 100
|
alias may be triggered a maximum of 100
|
||||||
times. This option can be used multiple times
|
times. This option can be used multiple times
|
||||||
@ -466,7 +466,7 @@ You can also fork the project on github and run your fork's [build workflow](.gi
|
|||||||
explicitly provided IP block in CIDR notation
|
explicitly provided IP block in CIDR notation
|
||||||
|
|
||||||
## Video Selection:
|
## Video Selection:
|
||||||
-I, --playlist-items ITEM_SPEC Comma seperated playlist_index of the videos
|
-I, --playlist-items ITEM_SPEC Comma separated playlist_index of the videos
|
||||||
to download. You can specify a range using
|
to download. You can specify a range using
|
||||||
"[START]:[STOP][:STEP]". For backward
|
"[START]:[STOP][:STEP]". For backward
|
||||||
compatibility, START-STOP is also supported.
|
compatibility, START-STOP is also supported.
|
||||||
|
@ -44,7 +44,7 @@ def main():
|
|||||||
|
|
||||||
|
|
||||||
def parse_options():
|
def parse_options():
|
||||||
# Compatability with older arguments
|
# Compatibility with older arguments
|
||||||
opts = sys.argv[1:]
|
opts = sys.argv[1:]
|
||||||
if opts[0:1] in (['32'], ['64']):
|
if opts[0:1] in (['32'], ['64']):
|
||||||
if ARCH != opts[0]:
|
if ARCH != opts[0]:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# flake8: noqa: F401
|
# flake8: noqa: F401
|
||||||
"""Imports all optional dependencies for the project.
|
"""Imports all optional dependencies for the project.
|
||||||
An attribute "_yt_dlp__identifier" may be inserted into the module if it uses an ambigious namespace"""
|
An attribute "_yt_dlp__identifier" may be inserted into the module if it uses an ambiguous namespace"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import brotlicffi as brotli
|
import brotlicffi as brotli
|
||||||
|
@ -103,7 +103,7 @@ class AbemaLicenseHandler(urllib.request.BaseHandler):
|
|||||||
HKEY = b'3AF0298C219469522A313570E8583005A642E73EDD58E3EA2FB7339D3DF1597E'
|
HKEY = b'3AF0298C219469522A313570E8583005A642E73EDD58E3EA2FB7339D3DF1597E'
|
||||||
|
|
||||||
def __init__(self, ie: 'AbemaTVIE'):
|
def __init__(self, ie: 'AbemaTVIE'):
|
||||||
# the protcol that this should really handle is 'abematv-license://'
|
# the protocol that this should really handle is 'abematv-license://'
|
||||||
# abematv_license_open is just a placeholder for development purposes
|
# abematv_license_open is just a placeholder for development purposes
|
||||||
# ref. https://github.com/python/cpython/blob/f4c03484da59049eb62a9bf7777b963e2267d187/Lib/urllib/request.py#L510
|
# ref. https://github.com/python/cpython/blob/f4c03484da59049eb62a9bf7777b963e2267d187/Lib/urllib/request.py#L510
|
||||||
setattr(self, 'abematv-license_open', getattr(self, 'abematv_license_open'))
|
setattr(self, 'abematv-license_open', getattr(self, 'abematv_license_open'))
|
||||||
@ -312,7 +312,7 @@ class AbemaTVIE(AbemaTVBaseIE):
|
|||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
# starting download using infojson from this extractor is undefined behavior,
|
# starting download using infojson from this extractor is undefined behavior,
|
||||||
# and never be fixed in the future; you must trigger downloads by directly specifing URL.
|
# and never be fixed in the future; you must trigger downloads by directly specifying URL.
|
||||||
# (unless there's a way to hook before downloading by extractor)
|
# (unless there's a way to hook before downloading by extractor)
|
||||||
video_id, video_type = self._match_valid_url(url).group('id', 'type')
|
video_id, video_type = self._match_valid_url(url).group('id', 'type')
|
||||||
headers = {
|
headers = {
|
||||||
|
@ -391,7 +391,7 @@ class InfoExtractor:
|
|||||||
There must be a key "entries", which is a list, an iterable, or a PagedList
|
There must be a key "entries", which is a list, an iterable, or a PagedList
|
||||||
object, each element of which is a valid dictionary by this specification.
|
object, each element of which is a valid dictionary by this specification.
|
||||||
|
|
||||||
Additionally, playlists can have "id", "title", and any other relevent
|
Additionally, playlists can have "id", "title", and any other relevant
|
||||||
attributes with the same semantics as videos (see above).
|
attributes with the same semantics as videos (see above).
|
||||||
|
|
||||||
It can also have the following optional fields:
|
It can also have the following optional fields:
|
||||||
@ -696,7 +696,7 @@ class InfoExtractor:
|
|||||||
return self._downloader.cookiejar
|
return self._downloader.cookiejar
|
||||||
|
|
||||||
def _initialize_pre_login(self):
|
def _initialize_pre_login(self):
|
||||||
""" Intialization before login. Redefine in subclasses."""
|
""" Initialization before login. Redefine in subclasses."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _perform_login(self, username, password):
|
def _perform_login(self, username, password):
|
||||||
@ -3207,7 +3207,7 @@ class InfoExtractor:
|
|||||||
|
|
||||||
entries = []
|
entries = []
|
||||||
# amp-video and amp-audio are very similar to their HTML5 counterparts
|
# amp-video and amp-audio are very similar to their HTML5 counterparts
|
||||||
# so we wll include them right here (see
|
# so we will include them right here (see
|
||||||
# https://www.ampproject.org/docs/reference/components/amp-video)
|
# https://www.ampproject.org/docs/reference/components/amp-video)
|
||||||
# For dl8-* tags see https://delight-vr.com/documentation/dl8-video/
|
# For dl8-* tags see https://delight-vr.com/documentation/dl8-video/
|
||||||
_MEDIA_TAG_NAME_RE = r'(?:(?:amp|dl8(?:-live)?)-)?(video|audio)'
|
_MEDIA_TAG_NAME_RE = r'(?:(?:amp|dl8(?:-live)?)-)?(video|audio)'
|
||||||
|
@ -142,7 +142,7 @@ class GenericIE(InfoExtractor):
|
|||||||
IE_DESC = 'Generic downloader that works on some sites'
|
IE_DESC = 'Generic downloader that works on some sites'
|
||||||
_VALID_URL = r'.*'
|
_VALID_URL = r'.*'
|
||||||
IE_NAME = 'generic'
|
IE_NAME = 'generic'
|
||||||
_NETRC_MACHINE = False # Supress username warning
|
_NETRC_MACHINE = False # Suppress username warning
|
||||||
_TESTS = [
|
_TESTS = [
|
||||||
# Direct link to a video
|
# Direct link to a video
|
||||||
{
|
{
|
||||||
|
@ -2,19 +2,17 @@ import functools
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
from ..compat import (
|
from ..compat import compat_str, compat_urllib_parse_unquote
|
||||||
compat_str,
|
|
||||||
compat_urllib_parse_unquote,
|
|
||||||
)
|
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
determine_ext,
|
|
||||||
ExtractorError,
|
ExtractorError,
|
||||||
|
HEADRequest,
|
||||||
|
OnDemandPagedList,
|
||||||
|
UnsupportedError,
|
||||||
|
determine_ext,
|
||||||
int_or_none,
|
int_or_none,
|
||||||
mimetype2ext,
|
mimetype2ext,
|
||||||
parse_qs,
|
parse_qs,
|
||||||
OnDemandPagedList,
|
|
||||||
try_get,
|
try_get,
|
||||||
UnsupportedError,
|
|
||||||
urljoin,
|
urljoin,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -91,7 +89,7 @@ class LBRYIE(LBRYBaseIE):
|
|||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
# Video
|
# Video
|
||||||
'url': 'https://lbry.tv/@Mantega:1/First-day-LBRY:1',
|
'url': 'https://lbry.tv/@Mantega:1/First-day-LBRY:1',
|
||||||
'md5': '65bd7ec1f6744ada55da8e4c48a2edf9',
|
'md5': 'fffd15d76062e9a985c22c7c7f2f4805',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '17f983b61f53091fb8ea58a9c56804e4ff8cff4d',
|
'id': '17f983b61f53091fb8ea58a9c56804e4ff8cff4d',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
@ -103,6 +101,19 @@ class LBRYIE(LBRYBaseIE):
|
|||||||
'release_date': '20200721',
|
'release_date': '20200721',
|
||||||
'width': 1280,
|
'width': 1280,
|
||||||
'height': 720,
|
'height': 720,
|
||||||
|
'thumbnail': 'https://spee.ch/7/67f2d809c263288c.png',
|
||||||
|
'license': 'None',
|
||||||
|
'duration': 346,
|
||||||
|
'channel': 'LBRY/Odysee rats united!!!',
|
||||||
|
'channel_id': '1c8ad6a2ab4e889a71146ae4deeb23bb92dab627',
|
||||||
|
'channel_url': 'https://lbry.tv/@Mantega:1c8ad6a2ab4e889a71146ae4deeb23bb92dab627',
|
||||||
|
'tags': [
|
||||||
|
'first day in lbry',
|
||||||
|
'lbc',
|
||||||
|
'lbry',
|
||||||
|
'start',
|
||||||
|
'tutorial'
|
||||||
|
],
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
# Audio
|
# Audio
|
||||||
@ -123,11 +134,13 @@ class LBRYIE(LBRYBaseIE):
|
|||||||
'channel_id': '0ed629d2b9c601300cacf7eabe9da0be79010212',
|
'channel_id': '0ed629d2b9c601300cacf7eabe9da0be79010212',
|
||||||
'channel_url': 'https://lbry.tv/@LBRYFoundation:0ed629d2b9c601300cacf7eabe9da0be79010212',
|
'channel_url': 'https://lbry.tv/@LBRYFoundation:0ed629d2b9c601300cacf7eabe9da0be79010212',
|
||||||
'vcodec': 'none',
|
'vcodec': 'none',
|
||||||
|
'thumbnail': 'https://spee.ch/d/0bc63b0e6bf1492d.png',
|
||||||
|
'license': 'None',
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
# HLS
|
# HLS
|
||||||
'url': 'https://odysee.com/@gardeningincanada:b/plants-i-will-never-grow-again.-the:e',
|
'url': 'https://odysee.com/@gardeningincanada:b/plants-i-will-never-grow-again.-the:e',
|
||||||
'md5': 'fc82f45ea54915b1495dd7cb5cc1289f',
|
'md5': '25049011f3c8bc2f8b60ad88a031837e',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': 'e51671357333fe22ae88aad320bde2f6f96b1410',
|
'id': 'e51671357333fe22ae88aad320bde2f6f96b1410',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
@ -143,12 +156,14 @@ class LBRYIE(LBRYBaseIE):
|
|||||||
'channel_id': 'b8be0e93b423dad221abe29545fbe8ec36e806bc',
|
'channel_id': 'b8be0e93b423dad221abe29545fbe8ec36e806bc',
|
||||||
'channel_url': 'https://odysee.com/@gardeningincanada:b8be0e93b423dad221abe29545fbe8ec36e806bc',
|
'channel_url': 'https://odysee.com/@gardeningincanada:b8be0e93b423dad221abe29545fbe8ec36e806bc',
|
||||||
'formats': 'mincount:3',
|
'formats': 'mincount:3',
|
||||||
|
'thumbnail': 'https://thumbnails.lbry.com/AgHSc_HzrrE',
|
||||||
|
'license': 'Copyrighted (contact publisher)',
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://odysee.com/@BrodieRobertson:5/apple-is-tracking-everything-you-do-on:e',
|
'url': 'https://odysee.com/@BrodieRobertson:5/apple-is-tracking-everything-you-do-on:e',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
}, {
|
}, {
|
||||||
'url': "https://odysee.com/@ScammerRevolts:b0/I-SYSKEY'D-THE-SAME-SCAMMERS-3-TIMES!:b",
|
'url': 'https://odysee.com/@ScammerRevolts:b0/I-SYSKEY\'D-THE-SAME-SCAMMERS-3-TIMES!:b',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://lbry.tv/Episode-1:e7d93d772bd87e2b62d5ab993c1c3ced86ebb396',
|
'url': 'https://lbry.tv/Episode-1:e7d93d772bd87e2b62d5ab993c1c3ced86ebb396',
|
||||||
@ -183,11 +198,12 @@ class LBRYIE(LBRYBaseIE):
|
|||||||
uri = 'lbry://' + display_id
|
uri = 'lbry://' + display_id
|
||||||
result = self._resolve_url(uri, display_id, 'stream')
|
result = self._resolve_url(uri, display_id, 'stream')
|
||||||
if result['value'].get('stream_type') in self._SUPPORTED_STREAM_TYPES:
|
if result['value'].get('stream_type') in self._SUPPORTED_STREAM_TYPES:
|
||||||
claim_id, is_live, headers = result['claim_id'], False, None
|
claim_id, is_live, headers = result['claim_id'], False, {}
|
||||||
streaming_url = self._call_api_proxy(
|
streaming_url = self._call_api_proxy(
|
||||||
'get', claim_id, {'uri': uri}, 'streaming url')['streaming_url']
|
'get', claim_id, {'uri': uri}, 'streaming url')['streaming_url']
|
||||||
final_url = self._request_webpage(
|
final_url = self._request_webpage(
|
||||||
streaming_url, display_id, note='Downloading streaming redirect url info').geturl()
|
HEADRequest(streaming_url), display_id,
|
||||||
|
note='Downloading streaming redirect url info').geturl()
|
||||||
elif result.get('value_type') == 'stream':
|
elif result.get('value_type') == 'stream':
|
||||||
claim_id, is_live = result['signing_channel']['claim_id'], True
|
claim_id, is_live = result['signing_channel']['claim_id'], True
|
||||||
headers = {'referer': 'https://player.odysee.live/'}
|
headers = {'referer': 'https://player.odysee.live/'}
|
||||||
@ -227,7 +243,7 @@ class LBRYChannelIE(LBRYBaseIE):
|
|||||||
'title': 'The LBRY Foundation',
|
'title': 'The LBRY Foundation',
|
||||||
'description': 'Channel for the LBRY Foundation. Follow for updates and news.',
|
'description': 'Channel for the LBRY Foundation. Follow for updates and news.',
|
||||||
},
|
},
|
||||||
'playlist_count': 29,
|
'playlist_mincount': 29,
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://lbry.tv/@LBRYFoundation',
|
'url': 'https://lbry.tv/@LBRYFoundation',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
|
@ -110,7 +110,7 @@ class RokfinIE(InfoExtractor):
|
|||||||
self.raise_login_required('This video is only available to premium users', True, method='cookies')
|
self.raise_login_required('This video is only available to premium users', True, method='cookies')
|
||||||
elif scheduled:
|
elif scheduled:
|
||||||
self.raise_no_formats(
|
self.raise_no_formats(
|
||||||
f'Stream is offline; sheduled for {datetime.fromtimestamp(scheduled).strftime("%Y-%m-%d %H:%M:%S")}',
|
f'Stream is offline; scheduled for {datetime.fromtimestamp(scheduled).strftime("%Y-%m-%d %H:%M:%S")}',
|
||||||
video_id=video_id, expected=True)
|
video_id=video_id, expected=True)
|
||||||
self._sort_formats(formats)
|
self._sort_formats(formats)
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ from ..utils import (
|
|||||||
variadic,
|
variadic,
|
||||||
)
|
)
|
||||||
|
|
||||||
# any clients starting with _ cannot be explicity requested by the user
|
# any clients starting with _ cannot be explicitly requested by the user
|
||||||
INNERTUBE_CLIENTS = {
|
INNERTUBE_CLIENTS = {
|
||||||
'web': {
|
'web': {
|
||||||
'INNERTUBE_API_KEY': 'AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8',
|
'INNERTUBE_API_KEY': 'AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8',
|
||||||
@ -792,7 +792,7 @@ class YoutubeBaseInfoExtractor(InfoExtractor):
|
|||||||
if yt_error:
|
if yt_error:
|
||||||
self._report_alerts([('ERROR', yt_error)], fatal=False)
|
self._report_alerts([('ERROR', yt_error)], fatal=False)
|
||||||
# Downloading page may result in intermittent 5xx HTTP error
|
# Downloading page may result in intermittent 5xx HTTP error
|
||||||
# Sometimes a 404 is also recieved. See: https://github.com/ytdl-org/youtube-dl/issues/28289
|
# Sometimes a 404 is also received. See: https://github.com/ytdl-org/youtube-dl/issues/28289
|
||||||
# We also want to catch all other network exceptions since errors in later pages can be troublesome
|
# We also want to catch all other network exceptions since errors in later pages can be troublesome
|
||||||
# See https://github.com/yt-dlp/yt-dlp/issues/507#issuecomment-880188210
|
# See https://github.com/yt-dlp/yt-dlp/issues/507#issuecomment-880188210
|
||||||
if not isinstance(e.cause, urllib.error.HTTPError) or e.cause.code not in (403, 429):
|
if not isinstance(e.cause, urllib.error.HTTPError) or e.cause.code not in (403, 429):
|
||||||
@ -3504,7 +3504,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
# See: https://github.com/yt-dlp/yt-dlp/issues/340
|
# See: https://github.com/yt-dlp/yt-dlp/issues/340
|
||||||
# List of possible thumbnails - Ref: <https://stackoverflow.com/a/20542029>
|
# List of possible thumbnails - Ref: <https://stackoverflow.com/a/20542029>
|
||||||
thumbnail_names = [
|
thumbnail_names = [
|
||||||
# While the *1,*2,*3 thumbnails are just below their correspnding "*default" variants
|
# While the *1,*2,*3 thumbnails are just below their corresponding "*default" variants
|
||||||
# in resolution, these are not the custom thumbnail. So de-prioritize them
|
# in resolution, these are not the custom thumbnail. So de-prioritize them
|
||||||
'maxresdefault', 'hq720', 'sddefault', 'hqdefault', '0', 'mqdefault', 'default',
|
'maxresdefault', 'hq720', 'sddefault', 'hqdefault', '0', 'mqdefault', 'default',
|
||||||
'sd1', 'sd2', 'sd3', 'hq1', 'hq2', 'hq3', 'mq1', 'mq2', 'mq3', '1', '2', '3'
|
'sd1', 'sd2', 'sd3', 'hq1', 'hq2', 'hq3', 'mq1', 'mq2', 'mq3', '1', '2', '3'
|
||||||
|
@ -206,7 +206,7 @@ class _YoutubeDLOptionParser(optparse.OptionParser):
|
|||||||
return sys.argv[1:] if args is None else list(args)
|
return sys.argv[1:] if args is None else list(args)
|
||||||
|
|
||||||
def _match_long_opt(self, opt):
|
def _match_long_opt(self, opt):
|
||||||
"""Improve ambigious argument resolution by comparing option objects instead of argument strings"""
|
"""Improve ambiguous argument resolution by comparing option objects instead of argument strings"""
|
||||||
try:
|
try:
|
||||||
return super()._match_long_opt(opt)
|
return super()._match_long_opt(opt)
|
||||||
except optparse.AmbiguousOptionError as e:
|
except optparse.AmbiguousOptionError as e:
|
||||||
@ -453,7 +453,7 @@ def create_parser():
|
|||||||
'Eg: --alias get-audio,-X "-S=aext:{0},abr -x --audio-format {0}" creates options '
|
'Eg: --alias get-audio,-X "-S=aext:{0},abr -x --audio-format {0}" creates options '
|
||||||
'"--get-audio" and "-X" that takes an argument (ARG0) and expands to '
|
'"--get-audio" and "-X" that takes an argument (ARG0) and expands to '
|
||||||
'"-S=aext:ARG0,abr -x --audio-format ARG0". All defined aliases are listed in the --help output. '
|
'"-S=aext:ARG0,abr -x --audio-format ARG0". All defined aliases are listed in the --help output. '
|
||||||
'Alias options can trigger more aliases; so be carefull to avoid defining recursive options. '
|
'Alias options can trigger more aliases; so be careful to avoid defining recursive options. '
|
||||||
f'As a safety measure, each alias may be triggered a maximum of {_YoutubeDLOptionParser.ALIAS_TRIGGER_LIMIT} times. '
|
f'As a safety measure, each alias may be triggered a maximum of {_YoutubeDLOptionParser.ALIAS_TRIGGER_LIMIT} times. '
|
||||||
'This option can be used multiple times'))
|
'This option can be used multiple times'))
|
||||||
|
|
||||||
@ -525,7 +525,7 @@ def create_parser():
|
|||||||
'-I', '--playlist-items',
|
'-I', '--playlist-items',
|
||||||
dest='playlist_items', metavar='ITEM_SPEC', default=None,
|
dest='playlist_items', metavar='ITEM_SPEC', default=None,
|
||||||
help=(
|
help=(
|
||||||
'Comma seperated playlist_index of the videos to download. '
|
'Comma separated playlist_index of the videos to download. '
|
||||||
'You can specify a range using "[START]:[STOP][:STEP]". For backward compatibility, START-STOP is also supported. '
|
'You can specify a range using "[START]:[STOP][:STEP]". For backward compatibility, START-STOP is also supported. '
|
||||||
'Use negative indices to count from the right and negative STEP to download in reverse order. '
|
'Use negative indices to count from the right and negative STEP to download in reverse order. '
|
||||||
'Eg: "-I 1:3,7,-5::2" used on a playlist of size 15 will download the videos at index 1,2,3,7,11,13,15'))
|
'Eg: "-I 1:3,7,-5::2" used on a playlist of size 15 will download the videos at index 1,2,3,7,11,13,15'))
|
||||||
|
@ -586,7 +586,7 @@ class FFmpegEmbedSubtitlePP(FFmpegPostProcessor):
|
|||||||
|
|
||||||
filename = info['filepath']
|
filename = info['filepath']
|
||||||
|
|
||||||
# Disabled temporarily. There needs to be a way to overide this
|
# Disabled temporarily. There needs to be a way to override this
|
||||||
# in case of duration actually mismatching in extractor
|
# in case of duration actually mismatching in extractor
|
||||||
# See: https://github.com/yt-dlp/yt-dlp/issues/1870, https://github.com/yt-dlp/yt-dlp/issues/1385
|
# See: https://github.com/yt-dlp/yt-dlp/issues/1870, https://github.com/yt-dlp/yt-dlp/issues/1385
|
||||||
'''
|
'''
|
||||||
|
@ -234,7 +234,7 @@ class Updater:
|
|||||||
|
|
||||||
def run_update(ydl):
|
def run_update(ydl):
|
||||||
"""Update the program file with the latest version from the repository
|
"""Update the program file with the latest version from the repository
|
||||||
@returns Whether there was a successfull update (No update = False)
|
@returns Whether there was a successful update (No update = False)
|
||||||
"""
|
"""
|
||||||
return Updater(ydl).update()
|
return Updater(ydl).update()
|
||||||
|
|
||||||
|
@ -2994,7 +2994,7 @@ def read_batch_urls(batch_fd):
|
|||||||
if not url or url.startswith(('#', ';', ']')):
|
if not url or url.startswith(('#', ';', ']')):
|
||||||
return False
|
return False
|
||||||
# "#" cannot be stripped out since it is part of the URI
|
# "#" cannot be stripped out since it is part of the URI
|
||||||
# However, it can be safely stipped out if follwing a whitespace
|
# However, it can be safely stripped out if following a whitespace
|
||||||
return re.split(r'\s#', url, 1)[0].rstrip()
|
return re.split(r'\s#', url, 1)[0].rstrip()
|
||||||
|
|
||||||
with contextlib.closing(batch_fd) as fd:
|
with contextlib.closing(batch_fd) as fd:
|
||||||
|
@ -11,4 +11,4 @@ class SamplePluginIE(InfoExtractor):
|
|||||||
_VALID_URL = r'^sampleplugin:'
|
_VALID_URL = r'^sampleplugin:'
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
self.to_screen('URL "%s" sucessfully captured' % url)
|
self.to_screen('URL "%s" successfully captured' % url)
|
||||||
|
Loading…
Reference in New Issue
Block a user