1
0
mirror of https://github.com/yt-dlp/yt-dlp.git synced 2025-08-15 17:08:29 +00:00

Merge branch 'upstream-master' into misc-2025-08

This commit is contained in:
sepro 2025-07-27 21:54:07 +02:00
commit 8c4d20288e
8 changed files with 110 additions and 8 deletions

View File

@ -242,7 +242,7 @@ jobs:
permissions: permissions:
contents: read contents: read
actions: write # For cleaning up cache actions: write # For cleaning up cache
runs-on: macos-13 runs-on: macos-14
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -261,6 +261,8 @@ jobs:
- name: Install Requirements - name: Install Requirements
run: | run: |
brew install coreutils brew install coreutils
# We need to use system Python in order to roll our own universal2 curl_cffi wheel
brew uninstall --ignore-dependencies python3
python3 -m venv ~/yt-dlp-build-venv python3 -m venv ~/yt-dlp-build-venv
source ~/yt-dlp-build-venv/bin/activate source ~/yt-dlp-build-venv/bin/activate
python3 devscripts/install_deps.py -o --include build python3 devscripts/install_deps.py -o --include build

View File

@ -62,16 +62,22 @@ def parse_options():
def exe(onedir): def exe(onedir):
"""@returns (name, path)""" """@returns (name, path)"""
platform_name, machine, extension = {
'win32': (None, MACHINE, '.exe'),
'darwin': ('macos', None, None),
}.get(OS_NAME, (OS_NAME, MACHINE, None))
name = '_'.join(filter(None, ( name = '_'.join(filter(None, (
'yt-dlp', 'yt-dlp',
{'win32': '', 'darwin': 'macos'}.get(OS_NAME, OS_NAME), platform_name,
MACHINE, machine,
))) )))
return name, ''.join(filter(None, ( return name, ''.join(filter(None, (
'dist/', 'dist/',
onedir and f'{name}/', onedir and f'{name}/',
name, name,
OS_NAME == 'win32' and '.exe', extension,
))) )))

View File

@ -205,7 +205,7 @@ def is_ad_fragment_end(s):
line = line.strip() line = line.strip()
if line: if line:
if not line.startswith('#'): if not line.startswith('#'):
if format_index and discontinuity_count != format_index: if format_index is not None and discontinuity_count != format_index:
continue continue
if ad_frag_next: if ad_frag_next:
continue continue
@ -231,7 +231,7 @@ def is_ad_fragment_end(s):
byte_range = {} byte_range = {}
elif line.startswith('#EXT-X-MAP'): elif line.startswith('#EXT-X-MAP'):
if format_index and discontinuity_count != format_index: if format_index is not None and discontinuity_count != format_index:
continue continue
if frag_index > 0: if frag_index > 0:
self.report_error( self.report_error(

View File

@ -1781,6 +1781,7 @@
RTVEALaCartaIE, RTVEALaCartaIE,
RTVEAudioIE, RTVEAudioIE,
RTVELiveIE, RTVELiveIE,
RTVEProgramIE,
RTVETelevisionIE, RTVETelevisionIE,
) )
from .rtvs import RTVSIE from .rtvs import RTVSIE

View File

@ -9,6 +9,7 @@
class FaulioLiveIE(InfoExtractor): class FaulioLiveIE(InfoExtractor):
_DOMAINS = ( _DOMAINS = (
'aloula.sba.sa', 'aloula.sba.sa',
'bahry.com',
'maraya.sba.net.ae', 'maraya.sba.net.ae',
'sat7plus.org', 'sat7plus.org',
) )
@ -25,6 +26,18 @@ class FaulioLiveIE(InfoExtractor):
'params': { 'params': {
'skip_download': 'Livestream', 'skip_download': 'Livestream',
}, },
}, {
'url': 'https://bahry.com/live/1',
'info_dict': {
'id': 'bahry.faulio.com_1',
'title': str,
'description': str,
'ext': 'mp4',
'live_status': 'is_live',
},
'params': {
'skip_download': 'Livestream',
},
}, { }, {
'url': 'https://maraya.sba.net.ae/live/1', 'url': 'https://maraya.sba.net.ae/live/1',
'info_dict': { 'info_dict': {

View File

@ -34,7 +34,6 @@ class NetEaseMusicBaseIE(InfoExtractor):
'sky', # SVIP tier; 沉浸环绕声 (Surround Audio); flac 'sky', # SVIP tier; 沉浸环绕声 (Surround Audio); flac
) )
_API_BASE = 'http://music.163.com/api/' _API_BASE = 'http://music.163.com/api/'
_GEO_BYPASS = False
def _create_eapi_cipher(self, api_path, query_body, cookies): def _create_eapi_cipher(self, api_path, query_body, cookies):
request_text = json.dumps({**query_body, 'header': cookies}, separators=(',', ':')) request_text = json.dumps({**query_body, 'header': cookies}, separators=(',', ':'))
@ -64,6 +63,8 @@ def _download_eapi_json(self, path, video_id, query_body, headers={}, **kwargs):
'MUSIC_U': ('MUSIC_U', {lambda i: i.value}), 'MUSIC_U': ('MUSIC_U', {lambda i: i.value}),
}), }),
} }
if self._x_forwarded_for_ip:
headers.setdefault('X-Real-IP', self._x_forwarded_for_ip)
return self._download_json( return self._download_json(
urljoin('https://interface3.music.163.com/', f'/eapi{path}'), video_id, urljoin('https://interface3.music.163.com/', f'/eapi{path}'), video_id,
data=self._create_eapi_cipher(f'/api{path}', query_body, cookies), headers={ data=self._create_eapi_cipher(f'/api{path}', query_body, cookies), headers={

View File

@ -6,9 +6,11 @@
from .common import InfoExtractor from .common import InfoExtractor
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
InAdvancePagedList,
clean_html, clean_html,
determine_ext, determine_ext,
float_or_none, float_or_none,
int_or_none,
make_archive_id, make_archive_id,
parse_iso8601, parse_iso8601,
qualities, qualities,
@ -371,3 +373,62 @@ def _real_extract(self, url):
raise ExtractorError('The webpage doesn\'t contain any video', expected=True) raise ExtractorError('The webpage doesn\'t contain any video', expected=True)
return self.url_result(play_url, ie=RTVEALaCartaIE.ie_key()) return self.url_result(play_url, ie=RTVEALaCartaIE.ie_key())
class RTVEProgramIE(RTVEBaseIE):
IE_NAME = 'rtve.es:program'
IE_DESC = 'RTVE.es programs'
_VALID_URL = r'https?://(?:www\.)?rtve\.es/play/videos/(?P<id>[\w-]+)/?(?:[?#]|$)'
_TESTS = [{
'url': 'https://www.rtve.es/play/videos/saber-vivir/',
'info_dict': {
'id': '111570',
'title': 'Saber vivir - Programa de ciencia y futuro en RTVE Play',
},
'playlist_mincount': 400,
}]
_PAGE_SIZE = 60
def _fetch_page(self, program_id, page_num):
return self._download_json(
f'https://www.rtve.es/api/programas/{program_id}/videos',
program_id, note=f'Downloading page {page_num}',
query={
'type': 39816,
'page': page_num,
'size': 60,
})
def _entries(self, page_data):
for video in traverse_obj(page_data, ('page', 'items', lambda _, v: url_or_none(v['htmlUrl']))):
yield self.url_result(
video['htmlUrl'], RTVEALaCartaIE, url_transparent=True,
**traverse_obj(video, {
'id': ('id', {str}),
'title': ('longTitle', {str}),
'description': ('shortDescription', {str}),
'duration': ('duration', {float_or_none(scale=1000)}),
'series': (('programInfo', 'title'), {str}, any),
'season_number': ('temporadaOrden', {int_or_none}),
'season_id': ('temporadaId', {str}),
'season': ('temporada', {str}),
'episode_number': ('episode', {int_or_none}),
'episode': ('title', {str}),
'thumbnail': ('thumbnail', {url_or_none}),
}),
)
def _real_extract(self, url):
program_slug = self._match_id(url)
program_page = self._download_webpage(url, program_slug)
program_id = self._html_search_meta('DC.identifier', program_page, 'Program ID', fatal=True)
first_page = self._fetch_page(program_id, 1)
page_count = traverse_obj(first_page, ('page', 'totalPages', {int})) or 1
entries = InAdvancePagedList(
lambda idx: self._entries(self._fetch_page(program_id, idx + 1) if idx else first_page),
page_count, self._PAGE_SIZE)
return self.playlist_result(entries, program_id, self._html_extract_title(program_page))

View File

@ -139,7 +139,18 @@ def _get_binary_name():
def _get_system_deprecation(): def _get_system_deprecation():
MIN_SUPPORTED, MIN_RECOMMENDED = (3, 9), (3, 9) MIN_SUPPORTED, MIN_RECOMMENDED = (3, 9), (3, 10)
EXE_MSG_TMPL = ('Support for {} has been deprecated. '
'See https://github.com/yt-dlp/yt-dlp/{} for details.\n{}')
STOP_MSG = 'You may stop receiving updates on this version at any time!'
variant = detect_variant()
# Temporary until macos_legacy executable builds are discontinued
if variant == 'darwin_legacy_exe':
return EXE_MSG_TMPL.format(
f'{variant} (the PyInstaller-bundled executable for macOS versions older than 10.15)',
'issues/13856', STOP_MSG)
if sys.version_info > MIN_RECOMMENDED: if sys.version_info > MIN_RECOMMENDED:
return None return None
@ -150,6 +161,13 @@ def _get_system_deprecation():
if sys.version_info < MIN_SUPPORTED: if sys.version_info < MIN_SUPPORTED:
return f'Python version {major}.{minor} is no longer supported! {PYTHON_MSG}' return f'Python version {major}.{minor} is no longer supported! {PYTHON_MSG}'
# Temporary until aarch64/armv7l build flow is bumped to Ubuntu 22.04 and Python 3.10
if variant in ('linux_aarch64_exe', 'linux_armv7l_exe'):
libc_ver = version_tuple(os.confstr('CS_GNU_LIBC_VERSION').partition(' ')[2])
if libc_ver < (2, 35):
return EXE_MSG_TMPL.format('system glibc version < 2.35', 'issues/13858', STOP_MSG)
return None
return f'Support for Python version {major}.{minor} has been deprecated. {PYTHON_MSG}' return f'Support for Python version {major}.{minor} has been deprecated. {PYTHON_MSG}'