DASH HD playback — WIP behind TORTTUBE_DASH=1 + upstream notes
Sidecar resolve_dash op shipped — returns rustypipe's full video_only_streams + audio_streams (16+ representations for NGGYU, from 360p H.264 through 4K AV1). Addon _build_dash_mpd assembles a valid on-demand MPEG-DASH manifest filtered to H.264 ≤1080p + best AAC audio. Two unblocked-by-WIP issues surfaced during integration: - inputstream.adaptive's libcurl can't open file:// URLs (logged in docs/upstream.md as an enhancement-target). - Rapid Player.Open retries can trigger Kodi's 'two concurrent busydialogs' fatal exit; need lifecycle hardening before re-enabling. Pivoted to localhost HTTP-server serving (ThreadingHTTPServer on a port-0 socket, MPD bytes captured in a per-instance handler subclass). Lifecycle: server.shutdown() runs in a finally block after the SponsorBlockMonitor watcher exits. Works in isolation but Kodi crashed under rapid retry conditions — needs more testing. For v0.0.5: DASH path is gated behind TORTTUBE_DASH=1 env var; default falls through to the stable yt-dlp progressive 360p path that's been verified live. M7 milestone added to track the remaining work; PRs to inputstream.adaptive + Kodi candidates logged in docs/upstream.md.
This commit is contained in:
parent
f610965fcf
commit
45e1306bf3
6 changed files with 329 additions and 14 deletions
|
|
@ -32,6 +32,11 @@ enum Request {
|
|||
/// no inputstream.adaptive needed. Slower than `resolve` but always
|
||||
/// gives a working stream.
|
||||
ResolvePlay { id: String },
|
||||
/// DASH-ready resolve: returns rustypipe's full `video_only_streams`
|
||||
/// + `audio_streams` arrays so the addon can build a DASH MPD with
|
||||
/// all quality rungs and feed it to inputstream.adaptive. Unlocks
|
||||
/// 1080p+ via H.264 hardware decode on RPi.
|
||||
ResolveDash { id: String },
|
||||
Rip { id: String, dest_dir: String },
|
||||
Sponsorblock {
|
||||
id: String,
|
||||
|
|
@ -131,6 +136,10 @@ async fn handle_line(line: &str) -> Response {
|
|||
Ok(v) => Response::ok(v),
|
||||
Err(e) => e.into(),
|
||||
},
|
||||
Request::ResolveDash { id } => match resolve::resolve_dash(&id).await {
|
||||
Ok(v) => Response::ok(v),
|
||||
Err(e) => e.into(),
|
||||
},
|
||||
Request::Rip { id, dest_dir } => match rip::rip(&id, &dest_dir).await {
|
||||
Ok(v) => Response::ok(v),
|
||||
Err(e) => e.into(),
|
||||
|
|
|
|||
|
|
@ -5,6 +5,38 @@ use serde_json::Value;
|
|||
|
||||
use crate::{run_yt_dlp, HandlerError};
|
||||
|
||||
/// DASH-ready resolve: returns rustypipe's full `video_only_streams` +
|
||||
/// `audio_streams` arrays + `details`. The Python addon builds an MPD
|
||||
/// from these and hands it to inputstream.adaptive — unlocks 1080p+ via
|
||||
/// H.264 hardware decode on the RPi (vs the 360p ceiling on progressive).
|
||||
pub(crate) async fn resolve_dash(id: &str) -> Result<Value, HandlerError> {
|
||||
use rustypipe::client::RustyPipe;
|
||||
|
||||
let rp = RustyPipe::new();
|
||||
let player = rp
|
||||
.query()
|
||||
.player(id)
|
||||
.await
|
||||
.map_err(|e| classify_rustypipe_error(&e))?;
|
||||
|
||||
let details_json = serde_json::to_value(&player.details)
|
||||
.map_err(|e| HandlerError::Internal(format!("serialize details: {e}")))?;
|
||||
let video_streams = serde_json::to_value(&player.video_only_streams)
|
||||
.map_err(|e| HandlerError::Internal(format!("serialize video_only_streams: {e}")))?;
|
||||
let audio_streams = serde_json::to_value(&player.audio_streams)
|
||||
.map_err(|e| HandlerError::Internal(format!("serialize audio_streams: {e}")))?;
|
||||
|
||||
tracing::info!(id, "resolve_dash ok via rustypipe");
|
||||
|
||||
Ok(serde_json::json!({
|
||||
"source": "rustypipe",
|
||||
"details": details_json,
|
||||
"video_only_streams": video_streams,
|
||||
"audio_streams": audio_streams,
|
||||
"expires_in_seconds": player.expires_in_seconds,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Playback-ready single-URL resolve. Asks yt-dlp for `best[ext=mp4]/best` —
|
||||
/// a combined audio+video format that Kodi can play as a plain HTTP URL.
|
||||
/// Slower than `resolve()` (~3-5s) but guarantees a working stream.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue