use anyhow::anyhow; use std::io::Read; use std::path::Path; use std::process::Command; use anyhow::Result; use super::Previewable; pub struct AudioPath<'a>(pub &'a Path); const COLOR: &str = "#dc322f"; // solarized red impl<'a> Previewable for AudioPath<'a> { fn get_thumbnail(&self) -> Result>> { let outfile = tempfile::Builder::new().suffix(".webp").tempfile()?; let thumbnail_cmd = Command::new("ffmpeg") .args(["-i", &self.0.to_string_lossy()]) .args([ "-filter_complex", &format!( "[0:a]aformat=channel_layouts=mono, compand=gain=-2, showwavespic=s=860x256:colors={COLOR}, drawbox=x=(iw-w)/2:y=(ih-h)/2:w=iw:h=1:color={COLOR}" ), ]) .args(["-vframes", "1"]) .arg(&*outfile.path().to_string_lossy()) .arg("-y") .output()?; if !thumbnail_cmd.status.success() { return Err(anyhow!( "Failed to render thumbnail: {:?}", String::from_utf8_lossy(&thumbnail_cmd.stderr) )); } let mut buffer = Vec::new(); outfile.as_file().read_to_end(&mut buffer)?; Ok(Some(buffer)) } }