shrivel 0.1.3

Cross-platform FFmpeg orchestrator that batch re-encodes videos to H.265/HEVC
//! Terminal progress bars for the batch and the active video conversion.

use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
use std::time::Duration;

/// Progress indicators shared by the batch loop and a single conversion.
pub struct ProgressBars {
    multi: MultiProgress,
    overall: ProgressBar,
}

impl ProgressBars {
    pub fn new(total: u64) -> Self {
        let multi = MultiProgress::new();
        let overall = multi.add(ProgressBar::new(total));
        overall.set_style(
            ProgressStyle::with_template(
                "[{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} {msg}",
            )
            .unwrap()
            .progress_chars("=> "),
        );
        overall.enable_steady_tick(Duration::from_millis(250));
        Self { multi, overall }
    }

    pub fn set_message(&self, message: impl Into<String>) {
        self.overall.set_message(message.into());
    }

    pub fn advance(&self) {
        self.overall.inc(1);
    }

    pub fn println(&self, message: impl Into<String>) {
        self.overall.println(message.into());
    }

    pub fn file(&self, duration: f64) -> Option<FileProgress> {
        if duration <= 0.0 {
            return None;
        }

        // Keep a visible bar for clips shorter than one second too.
        let bar = self
            .multi
            .add(ProgressBar::new(duration.ceil().max(1.0) as u64));
        bar.set_style(
            ProgressStyle::with_template("           [{bar:30.cyan/blue}] {pos}/{len}s {msg}")
                .unwrap()
                .progress_chars("=> "),
        );
        bar.set_message("Encoding");
        Some(FileProgress { bar })
    }

    pub fn clear(&self) -> anyhow::Result<()> {
        self.overall.finish_and_clear();
        self.multi.clear()?;
        Ok(())
    }
}

pub struct FileProgress {
    bar: ProgressBar,
}

impl FileProgress {
    pub fn set_seconds(&self, seconds: f64) {
        self.bar.set_position(seconds as u64);
    }

    pub fn finish(self) {
        self.bar.finish_and_clear();
    }
}