diff options
author | metamuffin <metamuffin@disroot.org> | 2025-04-16 21:08:26 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-04-16 21:08:26 +0200 |
commit | 96da47a8bb0a58bc2732c35eef86702f5cd2b5b2 (patch) | |
tree | 5431c7f91528cf6e1f7fee556363f736a09d68f2 | |
parent | afb1bd245b7065d791167611e3a6e84d7d1272f7 (diff) | |
download | jellything-96da47a8bb0a58bc2732c35eef86702f5cd2b5b2.tar jellything-96da47a8bb0a58bc2732c35eef86702f5cd2b5b2.tar.bz2 jellything-96da47a8bb0a58bc2732c35eef86702f5cd2b5b2.tar.zst |
send actual remux bitrate; close #18
-rw-r--r-- | remuxer/src/matroska_to_webm.rs | 5 | ||||
-rw-r--r-- | remuxer/src/seek_index.rs | 7 | ||||
-rw-r--r-- | stream/src/stream_info.rs | 42 |
3 files changed, 38 insertions, 16 deletions
diff --git a/remuxer/src/matroska_to_webm.rs b/remuxer/src/matroska_to_webm.rs index b9a1819..b77062b 100644 --- a/remuxer/src/matroska_to_webm.rs +++ b/remuxer/src/matroska_to_webm.rs @@ -1,3 +1,8 @@ +/* + 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) 2025 metamuffin <metamuffin.org> +*/ use crate::ebml_track_entry; use anyhow::Context; use ebml_struct::{ diff --git a/remuxer/src/seek_index.rs b/remuxer/src/seek_index.rs index 7296d93..82f62fb 100644 --- a/remuxer/src/seek_index.rs +++ b/remuxer/src/seek_index.rs @@ -53,6 +53,13 @@ pub fn get_seek_index(path: &Path) -> anyhow::Result<Arc<BTreeMap<u64, Arc<SeekI }) } +pub fn get_track_sizes(path: &Path) -> Result<BTreeMap<u64, usize>> { + Ok(get_seek_index(path)? + .iter() + .map(|(k, v)| (*k, v.blocks.iter().map(|b| b.size).sum::<usize>())) + .collect()) +} + pub fn import_seek_index(input: &mut EbmlReader) -> Result<BTreeMap<u64, SeekIndex>> { let mut seek_index = BTreeMap::new(); while let Some(item) = input.next() { diff --git a/stream/src/stream_info.rs b/stream/src/stream_info.rs index c3746c6..288ea5c 100644 --- a/stream/src/stream_info.rs +++ b/stream/src/stream_info.rs @@ -7,8 +7,11 @@ use jellybase::{ }, CONF, }; -use jellyremuxer::metadata::{matroska_metadata, MatroskaMetadata}; -use std::{path::PathBuf, sync::Arc}; +use jellyremuxer::{ + metadata::{matroska_metadata, MatroskaMetadata}, + seek_index::get_track_sizes, +}; +use std::{collections::BTreeMap, path::PathBuf, sync::Arc}; use tokio::{ io::{AsyncWriteExt, DuplexStream}, spawn, @@ -21,25 +24,30 @@ async fn async_matroska_metadata(path: PathBuf) -> Result<Arc<MatroskaMetadata>> Ok(spawn_blocking(move || matroska_metadata(&path)).await??) } +async fn async_get_track_sizes(path: PathBuf) -> Result<BTreeMap<u64, usize>> { + Ok(spawn_blocking(move || get_track_sizes(&path)).await??) +} + pub(crate) struct InternalStreamInfo { pub paths: Vec<PathBuf>, pub _metadata: Vec<Arc<MatroskaMetadata>>, pub track_to_file: Vec<(usize, u64)>, } +// TODO cache mem pub(crate) async fn stream_info(info: Arc<SMediaInfo>) -> Result<(InternalStreamInfo, StreamInfo)> { - let mut metadata = Vec::new(); - let mut paths = Vec::new(); - for path in &info.files { - metadata.push(async_matroska_metadata(path.clone()).await?); - paths.push(path.clone()); - } let mut tracks = Vec::new(); let mut track_to_file = Vec::new(); - - for (i, m) in metadata.iter().enumerate() { - if let Some(t) = &m.tracks { + let mut metadata_arr = Vec::new(); + let mut paths = Vec::new(); + for (i, path) in info.files.iter().enumerate() { + let metadata = async_matroska_metadata(path.clone()).await?; + let sizes = async_get_track_sizes(path.clone()).await?; + if let Some(t) = &metadata.tracks { + let duration = media_duration(&metadata); for t in &t.entries { + let bitrate = + sizes.get(&t.track_number).copied().unwrap_or_default() as f64 / duration * 8.; tracks.push(StreamTrackInfo { name: None, kind: match t.track_type { @@ -48,21 +56,23 @@ pub(crate) async fn stream_info(info: Arc<SMediaInfo>) -> Result<(InternalStream 17 => TrackKind::Subtitle, _ => todo!(), }, - formats: stream_formats(t), + formats: stream_formats(t, bitrate), }); track_to_file.push((i, t.track_number)); } } + metadata_arr.push(metadata); + paths.push(path.to_owned()); } let segment = StreamSegmentInfo { name: None, - duration: media_duration(&metadata[0]), + duration: media_duration(&metadata_arr[0]), tracks, }; Ok(( InternalStreamInfo { - _metadata: metadata, + _metadata: metadata_arr, paths, track_to_file, }, @@ -73,12 +83,12 @@ pub(crate) async fn stream_info(info: Arc<SMediaInfo>) -> Result<(InternalStream )) } -fn stream_formats(t: &TrackEntry) -> Vec<StreamFormatInfo> { +fn stream_formats(t: &TrackEntry, remux_bitrate: f64) -> Vec<StreamFormatInfo> { let mut formats = Vec::new(); formats.push(StreamFormatInfo { codec: t.codec_id.to_string(), remux: true, - bitrate: 10_000_000., // TODO + bitrate: remux_bitrate, containers: { let mut x = containers_by_codec(&t.codec_id); // TODO remove this |