use bytes::Bytes;
use super::audio::PreparedAudio;
#[derive(Clone)]
pub struct Clip {
pub input: Bytes,
pub start: Option<f64>,
pub end: Option<f64>,
}
impl Clip {
pub fn new(input: impl Into<Bytes>) -> Self {
Self { input: input.into(), start: None, end: None }
}
pub fn trimmed(input: impl Into<Bytes>, start: Option<f64>, end: Option<f64>) -> Self {
Self { input: input.into(), start, end }
}
}
pub(super) fn trim_frame(sec: Option<f64>, fps: f64) -> Option<u64> {
sec.map(|s| (s.max(0.0) * fps).ceil() as u64)
}
pub(super) fn trim_audio(
audio: Option<&PreparedAudio>,
start: Option<f64>,
end: Option<f64>,
) -> Option<PreparedAudio> {
let a = audio?;
if start.is_none() && end.is_none() {
return Some(a.clone());
}
let ticks_per_sec = a.info.timescale.max(1) as f64;
let start_tick = (start.unwrap_or(0.0).max(0.0) * ticks_per_sec) as u64;
let end_tick = end.map(|e| (e.max(0.0) * ticks_per_sec) as u64);
let mut acc: u64 = 0;
let mut kept = Vec::new();
for (payload, dur) in &a.samples {
let sample_start = acc;
acc += *dur as u64;
if sample_start < start_tick {
continue;
}
if end_tick.is_some_and(|et| sample_start >= et) {
break;
}
kept.push((payload.clone(), *dur));
}
Some(PreparedAudio { info: a.info.clone(), samples: kept, handling: a.handling.clone() })
}