/* 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 */ use anyhow::{anyhow, Result}; use jellycache::cache_memory; use jellyremuxer::demuxers::create_demuxer_autodetect; use serde::{Deserialize, Serialize}; use std::{collections::BTreeMap, fs::File, path::Path, sync::Arc}; #[derive(Serialize, Deserialize, Default)] pub struct TrackStat { pub num_blocks: usize, pub total_size: u64, } #[derive(Clone, Copy, Serialize, Deserialize)] pub struct GeneratedCue { pub position: u64, pub time: u64, } #[derive(Serialize, Deserialize)] pub struct StatsAndCues { pub stats: BTreeMap, pub cues: Vec, } pub fn generate_cues(path: &Path) -> Result> { cache_memory("generated-cues", path, move || { let media = File::open(path)?; let mut media = create_demuxer_autodetect(Box::new(media))?.ok_or(anyhow!("media format unknown"))?; let info = media.info()?; media.seek_cluster(None)?; let mut stats = BTreeMap::::new(); let mut cues = Vec::new(); while let Some((position, cluster)) = media.read_cluster()? { cues.push(GeneratedCue { position, time: cluster.timestamp * info.timestamp_scale, }); for block in cluster.simple_blocks { let e = stats.entry(block.track).or_default(); e.num_blocks += 1; e.total_size += block.data.len() as u64; } } Ok(StatsAndCues { stats, cues }) }) }