use std::path::PathBuf;
use std::time::Duration;
use crate::error::EncodeError;
use super::trim_inner;
pub struct StreamCopyTrimmer {
input: PathBuf,
output: PathBuf,
start_sec: f64,
end_sec: f64,
}
impl StreamCopyTrimmer {
pub fn new(
input: impl Into<PathBuf>,
start_sec: f64,
end_sec: f64,
output: impl Into<PathBuf>,
) -> Self {
Self {
input: input.into(),
output: output.into(),
start_sec,
end_sec,
}
}
pub fn run(self) -> Result<(), EncodeError> {
if self.start_sec >= self.end_sec {
return Err(EncodeError::InvalidConfig {
reason: format!(
"start_sec ({}) must be less than end_sec ({})",
self.start_sec, self.end_sec
),
});
}
log::debug!(
"stream copy trim start input={} output={} start_sec={} end_sec={}",
self.input.display(),
self.output.display(),
self.start_sec,
self.end_sec,
);
trim_inner::run_trim(&self.input, &self.output, self.start_sec, self.end_sec)
}
}
pub struct StreamCopyTrim {
input: PathBuf,
start: Duration,
end: Duration,
output: PathBuf,
}
impl StreamCopyTrim {
pub fn new(
input: impl Into<PathBuf>,
start: Duration,
end: Duration,
output: impl Into<PathBuf>,
) -> Self {
Self {
input: input.into(),
start,
end,
output: output.into(),
}
}
pub fn run(self) -> Result<(), EncodeError> {
if self.start >= self.end {
return Err(EncodeError::MediaOperationFailed {
reason: format!(
"start ({:?}) must be less than end ({:?})",
self.start, self.end
),
});
}
let start_sec = self.start.as_secs_f64();
let end_sec = self.end.as_secs_f64();
log::debug!(
"stream copy trim start input={} output={} start_sec={start_sec} end_sec={end_sec}",
self.input.display(),
self.output.display(),
);
trim_inner::run_trim(&self.input, &self.output, start_sec, end_sec)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn stream_copy_trimmer_should_reject_start_greater_than_end() {
let result = StreamCopyTrimmer::new("input.mp4", 7.0, 2.0, "output.mp4").run();
assert!(
matches!(result, Err(EncodeError::InvalidConfig { .. })),
"expected InvalidConfig for start > end, got {result:?}"
);
}
#[test]
fn stream_copy_trimmer_should_reject_equal_start_and_end() {
let result = StreamCopyTrimmer::new("input.mp4", 5.0, 5.0, "output.mp4").run();
assert!(
matches!(result, Err(EncodeError::InvalidConfig { .. })),
"expected InvalidConfig for start == end, got {result:?}"
);
}
#[test]
fn stream_copy_trim_should_reject_start_greater_than_end() {
let result = StreamCopyTrim::new(
"input.mp4",
Duration::from_secs(7),
Duration::from_secs(2),
"output.mp4",
)
.run();
assert!(
matches!(result, Err(EncodeError::MediaOperationFailed { .. })),
"expected MediaOperationFailed for start > end, got {result:?}"
);
}
#[test]
fn stream_copy_trim_should_reject_equal_start_and_end() {
let result = StreamCopyTrim::new(
"input.mp4",
Duration::from_secs(5),
Duration::from_secs(5),
"output.mp4",
)
.run();
assert!(
matches!(result, Err(EncodeError::MediaOperationFailed { .. })),
"expected MediaOperationFailed for start == end, got {result:?}"
);
}
}