Rust port of NewPipeExtractor (YT-only). Plugs into Straw via UniFFI.
Second pass through the cruft inventory. All deletes — no behavior change.
Method enum + downloader trait:
* Method::Head / Put / Delete dropped (no caller). Match arms in
request.rs::as_str() and default_impl.rs::execute() collapse to
just Get / Post.
* Request::head builder dropped.
* Downloader trait's get / get_localized / head / post default
methods dropped. Every caller went through execute() directly
anyway; the convenience wrappers carried 4 dead arms each.
Parsing module:
* bootstrap_visitor_data — pub fn, no caller.
* discover_web_client_version + CACHED_WEB_CLIENT_VERSION +
reset_web_client_version_cache — entire sw.js live-version
discovery pipeline, never wired up by any caller. The cache was
never populated, so web_client_version() always returned the
hardcoded constant. Collapsed to just returning the constant.
* Drops once_cell::Lazy, parking_lot::RwLock around the version
cache (consent flag still uses RwLock), Regex import, serde_json::Value
import, downloader/exceptions/Request/InnertubeClientRequestInfo
imports — all only kept alive by the deleted code.
stream_helper:
* get_web_embedded_player_response — pub fn, no caller.
js/player_manager + extractor:
* player_manager::player_hash — pub fn, no caller. Was only kept
alive by its own definition.
* extractor::extract_player_hash — pub fn, only called by the now-
dead player_hash. Test removed alongside.
Stale comments:
* itag.rs:1 header claimed 53 entries; ITAG_TABLE has 57 and the
test at line 179 already asserts it.
* js/mod.rs:12-13 claimed the submodules were 'crate-private
plumbing' but they're declared pub mod. Tightened the comment to
explain the integration-test dependency that keeps them public.
Net delete: ~170 LOC of dead surface across 9 files.
|
||
|---|---|---|
| src | ||
| tests | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| LICENSE | ||
| README.md | ||
strawcore
Rust port of NewPipeExtractor (v0.26.2), YouTube-only. Plugs into Straw via UniFFI.
Why this exists
rustypipe regex-parses YouTube's player.js and reimplements the signature deobfuscator in Rust. Every YT player rotation breaks it. NPE embeds Mozilla Rhino and executes the JS function live — resilient by design, and that's the architecture we're mirroring.
The rustypipe-backed Straw build (vc=15..17) also routed playback through iOS-progressive URLs, which hit a server-side ~917 KiB end-byte cap. NPE uses the Android client + po_token → DASH manifest path, which doesn't see the cap. Same fix, different layer.
See memory/npe-audit-2026-05-24/SPEC.md in the workspace repo for the full plan.
Status
| Phase | Subsystem | Status |
|---|---|---|
| 1 | Foundation (downloader + service spine) | in progress |
| 2 | JS engine (rquickjs + ress) | pending |
| 3 | InnerTube + itag table | pending |
| 4 | Stream extractor + DASH | pending |
| 5 | PoTokenProvider trait + Android JNI bridge | pending |
| 6 | Search + Channel + Playlist + Kiosks | pending |
| 7 | UniFFI surface swap | pending |
| 8 | Delete rustypipe everywhere | pending |
Build + test
cargo build
cargo test --lib # offline unit tests
cargo test --features online-tests # full smoke incl. live httpbin.org
License
GPL-3.0-or-later. NPE is GPL-3.0; this port inherits.