aboutsummaryrefslogtreecommitdiff
path: root/stream/src
diff options
context:
space:
mode:
Diffstat (limited to 'stream/src')
-rw-r--r--stream/src/hls.rs5
-rw-r--r--stream/src/jhls.rs9
-rw-r--r--stream/src/lib.rs6
-rw-r--r--stream/src/webvtt.rs46
4 files changed, 46 insertions, 20 deletions
diff --git a/stream/src/hls.rs b/stream/src/hls.rs
index c036e98..4f83577 100644
--- a/stream/src/hls.rs
+++ b/stream/src/hls.rs
@@ -49,11 +49,14 @@ pub async fn hls_variant_stream(
mut spec: StreamSpec,
mut b: DuplexStream,
) -> Result<()> {
+ let local_track = local_tracks.get(0).ok_or(anyhow!("no track"))?.to_owned();
+ let track_index = spec.tracks[0];
let snips = spawn_blocking(move || {
jellyremuxer::snippet::snippet_index(
&CONF.media_path,
&node.public,
- local_tracks.get(0).ok_or(anyhow!("no track"))?,
+ &local_track,
+ track_index,
)
})
.await??;
diff --git a/stream/src/jhls.rs b/stream/src/jhls.rs
index d5bb575..e26df1b 100644
--- a/stream/src/jhls.rs
+++ b/stream/src/jhls.rs
@@ -16,7 +16,7 @@ use tokio::io::{AsyncWriteExt, DuplexStream};
pub async fn jhls_index(
node: Node,
local_tracks: &[LocalTrack],
- _spec: StreamSpec,
+ spec: StreamSpec,
mut b: DuplexStream,
perms: &PermissionSet,
) -> Result<()> {
@@ -26,7 +26,12 @@ pub async fn jhls_index(
.to_owned();
let segments = tokio::task::spawn_blocking(move || {
- jellyremuxer::snippet::snippet_index(&CONF.media_path, &node.public, &local_track)
+ jellyremuxer::snippet::snippet_index(
+ &CONF.media_path,
+ &node.public,
+ &local_track,
+ spec.tracks[0],
+ )
})
.await??;
diff --git a/stream/src/lib.rs b/stream/src/lib.rs
index ee47857..833af3e 100644
--- a/stream/src/lib.rs
+++ b/stream/src/lib.rs
@@ -25,7 +25,7 @@ use tokio::{
io::{duplex, AsyncReadExt, AsyncSeekExt, AsyncWriteExt, DuplexStream},
};
use tokio_util::io::SyncIoBridge;
-use webvtt::webvtt_stream;
+use webvtt::vtt_stream;
pub struct StreamHead {
pub content_type: &'static str,
@@ -42,6 +42,7 @@ pub fn stream_head(spec: &StreamSpec) -> StreamHead {
StreamFormat::JhlsIndex => StreamHead { content_type: "application/jellything-seekindex+json", range_supported: false },
StreamFormat::Webvtt => StreamHead { content_type: "text/vtt", range_supported: false },
StreamFormat::Snippet => StreamHead { content_type: webm_or_mkv, range_supported: false },
+ StreamFormat::Jvtt => StreamHead { content_type: "applcation/jellything-vtt+json", range_supported: false },
}
}
@@ -87,7 +88,8 @@ pub async fn stream(
StreamFormat::HlsVariant => hls_variant_stream(node, local_tracks, spec, b).await?,
StreamFormat::JhlsIndex => jhls_index(node, &local_tracks, spec, b, perms).await?,
StreamFormat::Snippet => segment_stream(node, local_tracks, spec, b, perms).await?,
- StreamFormat::Webvtt => webvtt_stream(node, local_tracks, spec, b).await?,
+ StreamFormat::Webvtt => vtt_stream(false, node, local_tracks, spec, b).await?,
+ StreamFormat::Jvtt => vtt_stream(true, node, local_tracks, spec, b).await?,
}
Ok(a)
diff --git a/stream/src/webvtt.rs b/stream/src/webvtt.rs
index 48cf8d5..2de9835 100644
--- a/stream/src/webvtt.rs
+++ b/stream/src/webvtt.rs
@@ -5,12 +5,13 @@
*/
use anyhow::{anyhow, bail, Context, Result};
use jellybase::CONF;
-use jellycommon::{stream::StreamSpec, LocalTrack, Node};
+use jellycommon::{jhls::SubtitleCue, stream::StreamSpec, LocalTrack, Node};
use jellyremuxer::extract::extract_track;
-use jellytranscoder::subtitles::webvtt_from_ass_blocks;
+use jellytranscoder::subtitles::{parse_ass_blocks, parse_webvtt_blocks, write_webvtt};
use tokio::io::{AsyncWriteExt, DuplexStream};
-pub async fn webvtt_stream(
+pub async fn vtt_stream(
+ json: bool,
node: Node,
local_tracks: Vec<LocalTrack>,
spec: StreamSpec,
@@ -24,7 +25,29 @@ pub async fn webvtt_stream(
let local_track = local_tracks.get(0).ok_or(anyhow!("no tracks"))?.clone();
let track = &node.public.media.unwrap().tracks[tracki];
+ let write = |blocks: Vec<SubtitleCue>| -> anyhow::Result<()> {
+ let output = if json {
+ serde_json::to_string(&blocks)?
+ } else {
+ write_webvtt(node.public.title.clone().unwrap_or_default(), blocks)
+ .context("writing webvtt")?
+ };
+ tokio::task::spawn(async move {
+ let _ = b.write_all(output.as_bytes()).await;
+ });
+ Ok(())
+ };
+
match track.codec.as_str() {
+ "D_WEBVTT/SUBTITLES" => {
+ let webvtt_blocks = tokio::task::spawn_blocking(move || {
+ extract_track(CONF.media_path.clone(), local_track)
+ })
+ .await??;
+
+ let subtitles = parse_webvtt_blocks(webvtt_blocks).context("parsing subtitles")?;
+ write(subtitles)?;
+ }
"S_TEXT/UTF8" => bail!("no subrip yet"),
"S_VOBSUB" => bail!("no vobsub yet"),
"S_TEXT/ASS" => {
@@ -34,23 +57,16 @@ pub async fn webvtt_stream(
.ok_or(anyhow!("ASS is missing required codec private data"))?;
let ass_blocks = tokio::task::spawn_blocking(move || {
- extract_track(CONF.library_path.clone(), local_track)
+ extract_track(CONF.media_path.clone(), local_track)
})
.await??;
- let webvtt = webvtt_from_ass_blocks(
- node.public.title.clone().unwrap_or_default(),
- codec_private,
- ass_blocks,
- )
- .context("transcoding subtitles")?;
-
- tokio::task::spawn(async move {
- let _ = b.write_all(webvtt.as_bytes()).await;
- });
+ let subtitles =
+ parse_ass_blocks(codec_private, ass_blocks).context("parsing subtitles")?;
+ write(subtitles)?;
}
- _ => bail!("unknown sub codec"),
+ x => bail!("unknown sub codec {x:?}"),
};
Ok(())
}