mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-05-17 06:09:29 +00:00
feat(session): replace curl_cffi with rnet for TLS-fingerprinted HTTP
Replace CurlSession (curl_cffi) with RnetSession powered by rnet (Rust/BoringSSL). Benchmarks show 3.5x faster segmented downloads (1.06 GB/s vs 304 MB/s) and 16% faster single-file downloads with near-zero TLS fingerprinting overhead. - Add RnetSession wrapper with requests-compatible API (headers, cookies, proxies, retry logic, prepared requests) - Add RnetResponse wrapper normalizing rnet quirks (status_code as int, text as property, bytes-to-str headers, iter_content re-chunking) - Replace CurlSession isinstance checks across manifests, tracks, DRM - Update downloader with rnet native streaming path and byte-based progress tracking for accurate Rich progress bars - Add speed display column to Rich progress bar (DASH/HLS/URL prefix) - Add rnet dependency, services use exact preset names (e.g. OkHttp4_12)
This commit is contained in:
@@ -16,7 +16,6 @@ from uuid import UUID
|
||||
from zlib import crc32
|
||||
|
||||
import requests
|
||||
from curl_cffi.requests import Session as CurlSession
|
||||
from langcodes import Language, tag_is_valid
|
||||
from lxml.etree import Element, ElementTree
|
||||
from pyplayready.system.pssh import PSSH as PR_PSSH
|
||||
@@ -28,6 +27,7 @@ from unshackle.core.cdm.detect import is_playready_cdm
|
||||
from unshackle.core.constants import DOWNLOAD_CANCELLED, DOWNLOAD_LICENCE_ONLY, AnyTrack
|
||||
from unshackle.core.drm import DRM_T, PlayReady, Widevine
|
||||
from unshackle.core.events import events
|
||||
from unshackle.core.session import RnetSession
|
||||
from unshackle.core.tracks import Audio, Subtitle, Tracks, Video
|
||||
from unshackle.core.utilities import get_debug_logger, is_close_match, try_ensure_utf8
|
||||
from unshackle.core.utils.xml import load_xml
|
||||
@@ -49,7 +49,7 @@ class DASH:
|
||||
self.url = url
|
||||
|
||||
@classmethod
|
||||
def from_url(cls, url: str, session: Optional[Union[Session, CurlSession]] = None, **args: Any) -> DASH:
|
||||
def from_url(cls, url: str, session: Optional[Union[Session, RnetSession]] = None, **args: Any) -> DASH:
|
||||
if not url:
|
||||
raise requests.URLRequired("DASH manifest URL must be provided for relative path computations.")
|
||||
if not isinstance(url, str):
|
||||
@@ -57,8 +57,8 @@ class DASH:
|
||||
|
||||
if not session:
|
||||
session = Session()
|
||||
elif not isinstance(session, (Session, CurlSession)):
|
||||
raise TypeError(f"Expected session to be a {Session} or {CurlSession}, not {session!r}")
|
||||
elif not isinstance(session, (Session, RnetSession)):
|
||||
raise TypeError(f"Expected session to be a {Session} or {RnetSession}, not {session!r}")
|
||||
|
||||
res = session.get(url, **args)
|
||||
if res.url != url:
|
||||
@@ -264,8 +264,8 @@ class DASH:
|
||||
):
|
||||
if not session:
|
||||
session = Session()
|
||||
elif not isinstance(session, (Session, CurlSession)):
|
||||
raise TypeError(f"Expected session to be a {Session} or {CurlSession}, not {session!r}")
|
||||
elif not isinstance(session, (Session, RnetSession)):
|
||||
raise TypeError(f"Expected session to be a {Session} or {RnetSession}, not {session!r}")
|
||||
|
||||
if proxy:
|
||||
session.proxies.update({"all": proxy})
|
||||
@@ -589,7 +589,7 @@ class DASH:
|
||||
manifest: ElementTree,
|
||||
track: AnyTrack,
|
||||
track_url: str,
|
||||
session: Union[Session, CurlSession],
|
||||
session: Union[Session, RnetSession],
|
||||
) -> tuple[
|
||||
Optional[bytes],
|
||||
list[tuple[str, Optional[str]]],
|
||||
|
||||
Reference in New Issue
Block a user