diff options
Diffstat (limited to 'remuxer')
-rw-r--r-- | remuxer/src/lib.rs | 2 | ||||
-rw-r--r-- | remuxer/src/snippet.rs | 80 |
2 files changed, 62 insertions, 20 deletions
diff --git a/remuxer/src/lib.rs b/remuxer/src/lib.rs index ffefcae..96aeca1 100644 --- a/remuxer/src/lib.rs +++ b/remuxer/src/lib.rs @@ -82,7 +82,7 @@ pub fn ebml_track_entry( els.push(MatroskaTag::BitDepth(bit_depth.try_into().unwrap())); } SourceTrackKind::Subtitles => { - els.push(MatroskaTag::TrackType(19)); + els.push(MatroskaTag::TrackType(17)); } } if let Some(d) = &codec_private { diff --git a/remuxer/src/snippet.rs b/remuxer/src/snippet.rs index 4c3c47f..5b271e4 100644 --- a/remuxer/src/snippet.rs +++ b/remuxer/src/snippet.rs @@ -9,7 +9,7 @@ use crate::{ segment_extractor::SegmentExtractIter, }; use anyhow::{anyhow, Context, Result}; -use jellycommon::{LocalTrack, NodePublic}; +use jellycommon::{LocalTrack, NodePublic, SourceTrackKind}; use jellymatroska::{read::EbmlReader, write::EbmlWriter, Master, MatroskaTag}; use log::{debug, info}; use std::{ @@ -25,6 +25,7 @@ pub fn snippet_index( path_base: &Path, item: &NodePublic, local_track: &LocalTrack, + track_index: usize, ) -> Result<Vec<Range<f64>>> { let media_info = item.media.as_ref().unwrap(); let source_path = path_base.join(&local_track.path); @@ -32,20 +33,46 @@ pub fn snippet_index( let index = index .get(&(local_track.track as u64)) .ok_or(anyhow!("seek index track missing"))?; - let average_kf_interval = media_info.duration / index.keyframes.len() as f64; + + // everything is a keyframe (even though nothing is...) + let force_kf = matches!( + media_info.tracks[track_index].kind, + SourceTrackKind::Subtitles { .. } + ); + + let n_kf = if force_kf { + index.blocks.len() + } else { + index.keyframes.len() + }; + + let average_kf_interval = media_info.duration / n_kf as f64; let kf_per_snip = (SNIPPET_LENGTH / average_kf_interval).ceil() as usize; debug!("average keyframe interval: {average_kf_interval}"); debug!(" => keyframes per snippet {kf_per_snip}"); - let n_snips = index.keyframes.len().div_ceil(kf_per_snip); + let n_snips = n_kf.div_ceil(kf_per_snip); Ok((0..n_snips) .map(|i| { - let start = index.blocks[index.keyframes[i * kf_per_snip]].pts as f64 / 1000.; - let end = index - .keyframes - .get((i + 1) * kf_per_snip) - .map(|i| index.blocks[*i].pts as f64 / 1000.) - .unwrap_or(media_info.duration); + let start = index.blocks[if force_kf { + i * kf_per_snip + } else { + index.keyframes[i * kf_per_snip] + }] + .pts as f64 + / 1000.; + let end = if force_kf { + let n = (i + 1) * kf_per_snip; + if n >= index.blocks.len() { + None + } else { + Some(n) + } + } else { + index.keyframes.get((i + 1) * kf_per_snip).copied() + } + .map(|i| index.blocks[i].pts as f64 / 1000.) + .unwrap_or(media_info.duration); start..end }) .collect()) @@ -62,7 +89,6 @@ pub fn write_snippet_into( ) -> anyhow::Result<()> { info!("writing snippet {n} of {:?} (track {track})", item.title); let mut output = EbmlWriter::new(BufWriter::new(writer), 0); - let media_info = item.media.as_ref().unwrap(); let info = media_info .tracks @@ -85,19 +111,33 @@ pub fn write_snippet_into( debug!("\t seek index: {} blocks loaded", index.blocks.len()); let mut reader = EbmlReader::new(file); - let average_kf_interval = media_info.duration / index.keyframes.len() as f64; + let force_kf = matches!(info.kind, SourceTrackKind::Subtitles { .. }); + let n_kf = if force_kf { + index.blocks.len() + } else { + index.keyframes.len() + }; + + let average_kf_interval = media_info.duration / n_kf as f64; let kf_per_snip = (SNIPPET_LENGTH / average_kf_interval).ceil() as usize; debug!("average keyframe interval: {average_kf_interval}"); debug!(" => keyframes per snippet {kf_per_snip}"); - let start_block_index = *index - .keyframes - .get(n * kf_per_snip) - .ok_or(anyhow!("snippet index out of range"))?; - let end_block_index = *index - .keyframes - .get((n + 1) * kf_per_snip) - .unwrap_or(&index.blocks.len()); + let (start_block_index, end_block_index) = if force_kf { + (n * kf_per_snip, (n + 1) * kf_per_snip) + } else { + ( + *index + .keyframes + .get(n * kf_per_snip) + .ok_or(anyhow!("snippet index out of range"))?, + *index + .keyframes + .get((n + 1) * kf_per_snip) + .unwrap_or(&index.blocks.len()), + ) + }; + let start_block = &index.blocks[start_block_index]; let last_block = &index.blocks[end_block_index - 1]; @@ -152,5 +192,7 @@ pub fn write_snippet_into( } output.write_tag(&MatroskaTag::Segment(Master::End))?; + + debug!("wrote {} bytes", output.position()); Ok(()) } |