/* This file is part of jellything (https://codeberg.org/metamuffin/jellything) which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2023 metamuffin */ use anyhow::Result; use jellybase::{permission::PermissionSetExt, CONF}; use jellycommon::{ jhls::{JhlsMetadata, JhlsTrack}, stream::StreamSpec, user::{PermissionSet, UserPermission}, LocalTrack, Node, }; use tokio::io::{AsyncWriteExt, DuplexStream}; pub async fn jhls_stream( node: Node, track_sources: Vec, _spec: StreamSpec, mut b: DuplexStream, perms: &PermissionSet, ) -> Result<()> { let media = node.public.media.clone().unwrap(); let tracks = tokio::task::spawn_blocking(move || { media .tracks .iter() .enumerate() .filter_map(|(i, t)| { // TODO can we maybe stream the subtitles as .mks in the future? that would be cool // subtitles can only be supported by snippet_index if we relax constraints on the contents of each cluster if matches!(t.kind, jellycommon::SourceTrackKind::Subtitles) { return Some(Ok(JhlsTrack { info: t.to_owned(), segments: vec![], // clients need to ignore this })); } match jellyremuxer::snippet::snippet_index( &CONF.library_path, &node.public, &track_sources, i, ) { Ok(segments) => Some(Ok::<_, anyhow::Error>(JhlsTrack { info: t.to_owned(), segments, })), Err(e) => Some(Err(e)), } }) .try_collect::>() }) .await??; let out = serde_json::to_string(&JhlsMetadata { tracks, extra_profiles: if perms.check(&UserPermission::Transcode) { CONF.transcoding_profiles.clone() } else { vec![] }, duration: media.duration, })?; tokio::spawn(async move { b.write_all(out.as_bytes()).await }); Ok(()) }