aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock11
-rw-r--r--Cargo.toml2
-rw-r--r--common/Cargo.toml1
-rw-r--r--common/src/jhls.rs9
-rw-r--r--common/src/lib.rs2
-rw-r--r--server/src/logic/stream.rs2
-rw-r--r--stream/Cargo.toml1
-rw-r--r--stream/src/fragment.rs6
-rw-r--r--stream/src/fragment_index.rs2
-rw-r--r--stream/src/hls.rs4
-rw-r--r--stream/src/lib.rs17
-rw-r--r--stream/src/stream_info.rs8
-rw-r--r--stream/src/webvtt.rs150
-rw-r--r--stream/types/Cargo.toml7
-rw-r--r--stream/types/src/lib.rs (renamed from common/src/stream.rs)4
-rw-r--r--transcoder/Cargo.toml2
-rw-r--r--transcoder/src/fragment.rs2
-rw-r--r--transcoder/src/subtitles.rs9
18 files changed, 119 insertions, 120 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e8cfd9f..ef87500 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1808,6 +1808,7 @@ dependencies = [
"blake3",
"chrono",
"hex",
+ "jellystream-types",
"serde",
]
@@ -1934,6 +1935,7 @@ dependencies = [
"jellycache",
"jellycommon",
"jellyremuxer",
+ "jellystream-types",
"jellytranscoder",
"log",
"serde",
@@ -1943,6 +1945,13 @@ dependencies = [
]
[[package]]
+name = "jellystream-types"
+version = "0.1.0"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "jellything"
version = "0.1.1"
dependencies = [
@@ -2004,8 +2013,8 @@ dependencies = [
"image",
"imgref",
"jellycache",
- "jellycommon",
"jellyremuxer",
+ "jellystream-types",
"libavif-image",
"log",
"rav1e",
diff --git a/Cargo.toml b/Cargo.toml
index 0c750b3..69d7dde 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,6 +13,8 @@ members = [
"server",
"tool",
"transcoder",
+ "stream",
+ "stream/types",
"ui",
]
resolver = "3"
diff --git a/common/Cargo.toml b/common/Cargo.toml
index 90372bc..7baed9f 100644
--- a/common/Cargo.toml
+++ b/common/Cargo.toml
@@ -9,3 +9,4 @@ bincode = { version = "2.0.0-rc.3", features = ["derive"] }
chrono = { version = "0.4.39", features = ["serde"] }
blake3 = "1.5.5"
hex = "0.4.3"
+jellystream-types = { path = "../stream/types" }
diff --git a/common/src/jhls.rs b/common/src/jhls.rs
index 90f48f5..104d9a5 100644
--- a/common/src/jhls.rs
+++ b/common/src/jhls.rs
@@ -3,12 +3,3 @@
which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
-use bincode::{Decode, Encode};
-use serde::{Deserialize, Serialize};
-
-#[derive(Debug, Serialize, Deserialize, Encode, Decode)]
-pub struct SubtitleCue {
- pub start: f64,
- pub end: f64,
- pub content: String,
-}
diff --git a/common/src/lib.rs b/common/src/lib.rs
index 14c82fc..903d519 100644
--- a/common/src/lib.rs
+++ b/common/src/lib.rs
@@ -10,8 +10,8 @@ pub mod helpers;
pub mod r#impl;
pub mod jhls;
pub mod routes;
-pub mod stream;
pub mod user;
+pub use jellystream_types as stream;
pub use chrono;
diff --git a/server/src/logic/stream.rs b/server/src/logic/stream.rs
index 1e518e2..e3650ec 100644
--- a/server/src/logic/stream.rs
+++ b/server/src/logic/stream.rs
@@ -140,7 +140,7 @@ pub async fn r_stream(
}
let media = Arc::new(SMediaInfo {
files: sources,
- info: node,
+ title: node.title.clone(),
});
match jellystream::stream(media, spec, urange).await {
diff --git a/stream/Cargo.toml b/stream/Cargo.toml
index 33741d7..fb8cfe2 100644
--- a/stream/Cargo.toml
+++ b/stream/Cargo.toml
@@ -8,6 +8,7 @@ jellycommon = { path = "../common" }
jellycache = { path = "../cache" }
jellytranscoder = { path = "../transcoder" }
jellyremuxer = { path = "../remuxer" }
+jellystream-types = { path = "types" }
log = { workspace = true }
anyhow = { workspace = true }
diff --git a/stream/src/fragment.rs b/stream/src/fragment.rs
index 49817ca..89ce94f 100644
--- a/stream/src/fragment.rs
+++ b/stream/src/fragment.rs
@@ -5,8 +5,8 @@
*/
use crate::{stream_info, SMediaInfo};
use anyhow::{anyhow, bail, Result};
-use jellycommon::stream::StreamContainer;
use jellyremuxer::{matroska_to_mpeg4, matroska_to_webm::matroska_to_webm};
+use jellystream_types::StreamContainer;
use jellytranscoder::fragment::transcode;
use log::warn;
use std::{
@@ -84,9 +84,7 @@ pub async fn fragment_stream(
}
});
}
- StreamContainer::JVTT => {
-
- }
+ StreamContainer::JVTT => {}
_ => bail!("not yet supported"),
}
} else {
diff --git a/stream/src/fragment_index.rs b/stream/src/fragment_index.rs
index 0632f0a..cb54948 100644
--- a/stream/src/fragment_index.rs
+++ b/stream/src/fragment_index.rs
@@ -5,7 +5,7 @@
*/
use crate::{stream_info, SMediaInfo};
use anyhow::{anyhow, Result};
-use jellycommon::stream::{SegmentNum, TrackNum};
+use jellystream_types::{SegmentNum, TrackNum};
use std::sync::Arc;
use tokio::io::{AsyncWriteExt, DuplexStream};
diff --git a/stream/src/hls.rs b/stream/src/hls.rs
index 41b896b..949ddb4 100644
--- a/stream/src/hls.rs
+++ b/stream/src/hls.rs
@@ -6,9 +6,7 @@
use crate::{stream_info, SMediaInfo};
use anyhow::{anyhow, Result};
-use jellycommon::stream::{
- FormatNum, SegmentNum, StreamContainer, StreamSpec, TrackKind, TrackNum,
-};
+use jellystream_types::{FormatNum, SegmentNum, StreamContainer, StreamSpec, TrackKind, TrackNum};
use std::{fmt::Write, ops::Range, sync::Arc};
use tokio::{
io::{AsyncWriteExt, DuplexStream},
diff --git a/stream/src/lib.rs b/stream/src/lib.rs
index 9c62ac8..5b4e8ed 100644
--- a/stream/src/lib.rs
+++ b/stream/src/lib.rs
@@ -4,20 +4,17 @@
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
#![feature(iterator_try_collect)]
-pub mod fragment;
-pub mod fragment_index;
-pub mod hls;
-pub mod stream_info;
-pub mod webvtt;
+mod fragment;
+mod fragment_index;
+mod hls;
+mod stream_info;
+mod webvtt;
use anyhow::{anyhow, bail, Context, Result};
use fragment::fragment_stream;
use fragment_index::fragment_index_stream;
use hls::{hls_multivariant_stream, hls_supermultivariant_stream, hls_variant_stream};
-use jellycommon::{
- stream::{StreamContainer, StreamSpec},
- Node,
-};
+use jellystream_types::{StreamContainer, StreamSpec};
use serde::{Deserialize, Serialize};
use std::{
collections::BTreeSet,
@@ -53,7 +50,7 @@ static CONF: LazyLock<Config> = LazyLock::new(|| {
#[derive(Debug)]
pub struct SMediaInfo {
- pub info: Arc<Node>,
+ pub title: Option<String>,
pub files: BTreeSet<PathBuf>,
}
diff --git a/stream/src/stream_info.rs b/stream/src/stream_info.rs
index 920ce69..560ec9b 100644
--- a/stream/src/stream_info.rs
+++ b/stream/src/stream_info.rs
@@ -5,13 +5,13 @@
*/
use crate::{SMediaInfo, CONF};
use anyhow::Result;
-use jellycommon::stream::{
- StreamContainer, StreamFormatInfo, StreamInfo, StreamSegmentInfo, StreamTrackInfo, TrackKind,
-};
use jellyremuxer::{
metadata::{matroska_metadata, MatroskaMetadata, MatroskaTrackEntry},
seek_index::get_track_sizes,
};
+use jellystream_types::{
+ StreamContainer, StreamFormatInfo, StreamInfo, StreamSegmentInfo, StreamTrackInfo, TrackKind,
+};
use std::{collections::BTreeMap, path::PathBuf, sync::Arc};
use tokio::{
io::{AsyncWriteExt, DuplexStream},
@@ -76,7 +76,7 @@ pub(crate) async fn stream_info(info: Arc<SMediaInfo>) -> Result<(InternalStream
track_to_file,
},
StreamInfo {
- name: info.info.title.clone(),
+ name: info.title.clone(),
segments: vec![segment],
},
))
diff --git a/stream/src/webvtt.rs b/stream/src/webvtt.rs
index c0bc466..d99111e 100644
--- a/stream/src/webvtt.rs
+++ b/stream/src/webvtt.rs
@@ -3,91 +3,77 @@
which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
-use anyhow::Result;
-use jellycommon::{stream::StreamSpec, Node};
-use std::sync::Arc;
-use tokio::io::DuplexStream;
-pub async fn vtt_stream(
- json: bool,
- node: Arc<Node>,
- spec: StreamSpec,
- b: DuplexStream,
-) -> Result<()> {
- let _ = b;
- let _ = spec;
- let _ = node;
- let _ = json;
- // TODO cache
+// async fn vtt_stream(json: bool, node: Arc<Node>, spec: StreamSpec, b: DuplexStream) -> Result<()> {
+// TODO cache
+// TODO should use fragments too? big films take too long...
- // TODO should use fragments too? big films take too long...
+// let tracki = *spec.track.first().ok_or(anyhow!("no track selected"))?;
+// let local_track = local_tracks.first().ok_or(anyhow!("no tracks"))?.clone();
+// let track = &node.media.as_ref().unwrap().tracks[tracki];
+// let cp = local_track.codec_private.clone();
- // let tracki = *spec.track.first().ok_or(anyhow!("no track selected"))?;
- // let local_track = local_tracks.first().ok_or(anyhow!("no tracks"))?.clone();
- // let track = &node.media.as_ref().unwrap().tracks[tracki];
- // let cp = local_track.codec_private.clone();
+// let subtitles = async_cache_memory(
+// &[
+// "vtt",
+// &format!(
+// "{} {}",
+// local_track.path.to_str().unwrap(),
+// local_track.track
+// ),
+// ],
+// move || async move {
+// let blocks = tokio::task::spawn_blocking(move || {
+// extract_track(CONF.media_path.clone(), local_track)
+// })
+// .await??;
+// let subtitles = parse_subtitles(&track.codec, cp, blocks)?;
+// Ok(subtitles)
+// },
+// )spec.track.first().ok_or(anyhow!("no track selected"))?;
+// let local_track = local_tracks.first().ok_or(anyhow!("no tracks"))?.clone();
+// let track = &node.media.as_ref().unwrap().tracks[tracki];
+// let cp = local_track.codec_private.clone();
- // let subtitles = async_cache_memory(
- // &[
- // "vtt",
- // &format!(
- // "{} {}",
- // local_track.path.to_str().unwrap(),
- // local_track.track
- // ),
- // ],
- // move || async move {
- // let blocks = tokio::task::spawn_blocking(move || {
- // extract_track(CONF.media_path.clone(), local_track)
- // })
- // .await??;
- // let subtitles = parse_subtitles(&track.codec, cp, blocks)?;
- // Ok(subtitles)
- // },
- // )spec.track.first().ok_or(anyhow!("no track selected"))?;
- // let local_track = local_tracks.first().ok_or(anyhow!("no tracks"))?.clone();
- // let track = &node.media.as_ref().unwrap().tracks[tracki];
- // let cp = local_track.codec_private.clone();
+// let subtitles = async_cache_memory(
+// &[
+// "vtt",
+// &format!(
+// "{} {}",
+// local_track.path.to_str().unwrap(),
+// local_track.track
+// ),
+// ],
+// move || async move {
+// let blocks = tokio::task::spawn_blocking(move || {
+// extract_track(CONF.media_path.clone(), local_track)
+// })
+// .await??;
+// let subtitles = parse_subtitles(&track.codec, cp, blocks)?;
+// Ok(subtitles)
+// },
+// )
+// .await?;
- // let subtitles = async_cache_memory(
- // &[
- // "vtt",
- // &format!(
- // "{} {}",
- // local_track.path.to_str().unwrap(),
- // local_track.track
- // ),
- // ],
- // move || async move {
- // let blocks = tokio::task::spawn_blocking(move || {
- // extract_track(CONF.media_path.clone(), local_track)
- // })
- // .await??;
- // let subtitles = parse_subtitles(&track.codec, cp, blocks)?;
- // Ok(subtitles)
- // },
- // )
- // .await?;
+// let output = if json {
+// serde_json::to_string(subtitles.as_ref())?
+// } else {
+// write_webvtt(node.title.clone().unwrap_or_default(), subtitles.as_ref())
+// .context("writing webvtt")?
+// };
+// tokio::task::spawn(async move {
+// let _ = b.write_all(output.as_bytes()).await;
+// });
+// .await?;
- // let output = if json {
- // serde_json::to_string(subtitles.as_ref())?
- // } else {
- // write_webvtt(node.title.clone().unwrap_or_default(), subtitles.as_ref())
- // .context("writing webvtt")?
- // };
- // tokio::task::spawn(async move {
- // let _ = b.write_all(output.as_bytes()).await;
- // });
- // .await?;
-
- // let output = if json {
- // serde_json::to_string(subtitles.as_ref())?
- // } else {
- // write_webvtt(node.title.clone().unwrap_or_default(), subtitles.as_ref())
- // .context("writing webvtt")?
- // };
- // tokio::task::spawn(async move {
- // let _ = b.write_all(output.as_bytes()).await;
- // });
- Ok(())
-}
+// let output = if json {
+// serde_json::to_string(subtitles.as_ref())?
+// } else {
+// write_webvtt(node.title.clone().unwrap_or_default(), subtitles.as_ref())
+// .context("writing webvtt")?
+// };
+// tokio::task::spawn(async move {
+// let _ = b.write_all(output.as_bytes()).await;
+// });
+// Ok(())
+// }
diff --git a/stream/types/Cargo.toml b/stream/types/Cargo.toml
new file mode 100644
index 0000000..f441730
--- /dev/null
+++ b/stream/types/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "jellystream-types"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+serde = { version = "1.0.219", features = ["derive"] }
diff --git a/common/src/stream.rs b/stream/types/src/lib.rs
index b60b349..a90db03 100644
--- a/common/src/stream.rs
+++ b/stream/types/src/lib.rs
@@ -155,7 +155,9 @@ impl StreamSpec {
index,
container,
format,
- } => format!("?fragment&segment={segment}&track={track}&index={index}&container={container}&format={format}"),
+ } => format!(
+ "?fragment&segment={segment}&track={track}&index={index}&container={container}&format={format}"
+ ),
}
}
pub fn to_query_short(&self) -> String {
diff --git a/transcoder/Cargo.toml b/transcoder/Cargo.toml
index f35b101..06dc1aa 100644
--- a/transcoder/Cargo.toml
+++ b/transcoder/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
[dependencies]
jellyremuxer = { path = "../remuxer" }
jellycache = { path = "../cache" }
-jellycommon = { path = "../common" }
+jellystream-types = { path = "../stream/types" }
log = { workspace = true }
# TODO: change this back to crates.io when pr is merged
image = "0.25.5"
diff --git a/transcoder/src/fragment.rs b/transcoder/src/fragment.rs
index dbb8f6d..a71094d 100644
--- a/transcoder/src/fragment.rs
+++ b/transcoder/src/fragment.rs
@@ -6,8 +6,8 @@
use crate::{Config, CONF, LOCAL_VIDEO_TRANSCODING_TASKS};
use anyhow::Result;
use jellycache::{async_cache_file, CachePath};
-use jellycommon::stream::{StreamFormatInfo, TrackKind};
use jellyremuxer::metadata::MatroskaTrackEntry;
+use jellystream_types::{StreamFormatInfo, TrackKind};
use log::info;
use std::fmt::Write;
use std::process::Stdio;
diff --git a/transcoder/src/subtitles.rs b/transcoder/src/subtitles.rs
index d7e7b29..1325b62 100644
--- a/transcoder/src/subtitles.rs
+++ b/transcoder/src/subtitles.rs
@@ -4,9 +4,16 @@
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
use anyhow::{anyhow, bail, Context};
-use jellycommon::jhls::SubtitleCue;
+use serde::{Deserialize, Serialize};
use std::fmt::Write;
+#[derive(Debug, Serialize, Deserialize)]
+pub struct SubtitleCue {
+ pub start: f64,
+ pub end: f64,
+ pub content: String,
+}
+
pub fn parse_subtitles(
codec: &str,
codec_private: Option<Vec<u8>>,