feat(stream): add stream quality selection and update stream URL handling

This commit is contained in:
2026-03-14 04:03:54 +01:00
parent 8f42164bce
commit cf92cc49c2
11 changed files with 346 additions and 107 deletions

View File

@@ -8,7 +8,7 @@ use chrono::Utc;
use serde::Deserialize;
use uuid::Uuid;
use domain::{DomainError, ScheduleEngineService};
use domain::{DomainError, ScheduleEngineService, StreamQuality};
use crate::{
dto::{CurrentBroadcastResponse, ScheduledSlotResponse},
@@ -130,11 +130,18 @@ pub(super) async fn get_epg(
/// Redirect to the stream URL for whatever is currently playing.
/// Returns 307 Temporary Redirect so the client fetches from the media provider directly.
/// Returns 204 No Content when the channel is in a gap (no-signal).
#[derive(Debug, Deserialize)]
pub(super) struct StreamQuery {
/// "direct" | bitrate in bps as string (e.g. "8000000"). Defaults to "direct".
quality: Option<String>,
}
pub(super) async fn get_stream(
State(state): State<AppState>,
Path(channel_id): Path<Uuid>,
OptionalCurrentUser(user): OptionalCurrentUser,
headers: HeaderMap,
Query(query): Query<StreamQuery>,
) -> Result<Response, ApiError> {
let channel = state.channel_service.find_by_id(channel_id).await?;
@@ -174,9 +181,13 @@ pub(super) async fn get_stream(
)?;
}
let stream_quality = match query.quality.as_deref() {
Some("direct") | None => StreamQuality::Direct,
Some(bps_str) => StreamQuality::Transcode(bps_str.parse::<u32>().unwrap_or(40_000_000)),
};
let url = state
.schedule_engine
.get_stream_url(&broadcast.slot.item.id)
.get_stream_url(&broadcast.slot.item.id, &stream_quality)
.await?;
Ok(Redirect::temporary(&url).into_response())