clippr 0.1.0

Convert MP4 to chunked GitHub-friendly GIFs
Documentation
use crate::error::{Error, Result};
use std::path::Path;
use std::process::Command;

pub struct EncodeParams {
    pub width: u32,
    pub fps: u32,
    pub colors: u32,
    pub start_secs: f64,
    pub duration_secs: f64,
}

pub fn encode(input: &Path, output: &Path, params: &EncodeParams) -> Result<u64> {
    let filter = format!(
        "fps={fps},scale={width}:-1:flags=lanczos,\
         split[s0][s1];\
         [s0]palettegen=max_colors={colors}:stats_mode=diff[p];\
         [s1][p]paletteuse=dither=floyd_steinberg",
        fps = params.fps,
        width = params.width,
        colors = params.colors,
    );

    let mut command = Command::new("ffmpeg");
    command.args(["-y", "-ss", &format!("{:.3}", params.start_secs)]);
    command.args(["-t", &format!("{:.3}", params.duration_secs)]);
    command.args(["-i"]);
    command.arg(input);
    command.args(["-vf", &filter]);
    command.arg(output);

    let result = command.output().map_err(|_| Error::FfmpegNotFound)?;

    if !result.status.success() {
        let stderr = String::from_utf8_lossy(&result.stderr);
        return Err(Error::EncodeFailed(stderr.into_owned()));
    }

    let metadata = std::fs::metadata(output)?;
    Ok(metadata.len())
}