Rewriting simpler ffmpeg calls using the API (#372)

* Use ffmpeg API for get_keyframes

* Use ffmpeg API for has_audio

* Remove unused function get_frame_types
This commit is contained in:
Josh Holmer 2021-10-04 09:17:11 -04:00 committed by GitHub
parent 657810d162
commit 5fbee3dfed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,6 +1,6 @@
use crate::{into_vec, regex};
use crate::into_vec;
use ffmpeg_next::format::input;
use ffmpeg_next::media::Type;
use ffmpeg_next::media::Type as MediaType;
use ffmpeg_next::Error::StreamNotFound;
use path_abs::{PathAbs, PathInfo};
use std::{
@ -27,7 +27,10 @@ pub fn compose_ffmpeg_pipe(params: Vec<String>) -> Vec<String> {
/// Get frame count. Direct counting of frame count using ffmpeg
pub fn num_frames(source: &Path) -> anyhow::Result<usize> {
let mut ictx = input(&source)?;
let input = ictx.streams().best(Type::Video).ok_or(StreamNotFound)?;
let input = ictx
.streams()
.best(MediaType::Video)
.ok_or(StreamNotFound)?;
let video_stream_index = input.index();
Ok(
@ -40,33 +43,22 @@ pub fn num_frames(source: &Path) -> anyhow::Result<usize> {
/// Returns vec of all keyframes
pub fn get_keyframes<P: AsRef<Path>>(source: P) -> Vec<usize> {
let source = source.as_ref();
let mut cmd = Command::new("ffmpeg");
let mut ictx = input(&source).unwrap();
let input = ictx
.streams()
.best(MediaType::Video)
.ok_or(StreamNotFound)
.unwrap();
let video_stream_index = input.index();
cmd.stdout(Stdio::piped());
cmd.stderr(Stdio::piped());
cmd.args(&[
"-hide_banner",
"-i",
source.to_str().unwrap(),
"-vf",
r"select=eq(pict_type\,PICT_TYPE_I)",
"-f",
"null",
"-loglevel",
"debug",
"-",
]);
let out = cmd.output().unwrap();
assert!(out.status.success());
let output = String::from_utf8(out.stderr).unwrap();
let mut kfs: Vec<usize> = vec![];
for found in regex!(r".*n:([0-9]+)\.[0-9]+ pts:.+key:1").captures_iter(&output) {
kfs.push(found.get(1).unwrap().as_str().parse::<usize>().unwrap());
}
let kfs = ictx
.packets()
.filter(|(stream, _)| stream.index() == video_stream_index)
.map(|(_, packet)| packet)
.enumerate()
.filter(|(_, packet)| packet.is_key())
.map(|(i, _)| i)
.collect::<Vec<_>>();
if kfs.is_empty() {
return vec![0];
@ -77,18 +69,8 @@ pub fn get_keyframes<P: AsRef<Path>>(source: P) -> Vec<usize> {
/// Returns true if input file have audio in it
pub fn has_audio(file: &Path) -> bool {
let mut cmd = Command::new("ffmpeg");
cmd.stdout(Stdio::piped());
cmd.stderr(Stdio::piped());
cmd.args(&["-hide_banner", "-i", file.to_str().unwrap()]);
let out = cmd.output().unwrap();
let output = String::from_utf8(out.stderr).unwrap();
regex!(r".*Stream.+(Audio)").is_match(&output)
let ictx = input(&file).unwrap();
ictx.streams().best(MediaType::Audio).is_some()
}
/// Encodes the audio using FFmpeg, blocking the current thread.
@ -134,42 +116,6 @@ pub fn encode_audio<S: AsRef<OsStr>>(
}
}
/// Returns list of frame types of the video
pub fn get_frame_types(file: &Path) -> Vec<String> {
let mut cmd = Command::new("ffmpeg");
cmd.stdout(Stdio::piped());
cmd.stderr(Stdio::piped());
let args = [
"ffmpeg",
"-hide_banner",
"-i",
file.to_str().unwrap(),
"-vf",
"showinfo",
"-f",
"null",
"-loglevel",
"debug",
"-",
];
cmd.args(args);
let out = cmd.output().unwrap();
assert!(out.status.success());
let output = String::from_utf8(out.stderr).unwrap();
let str_vec = output.split('\n').collect::<Vec<_>>();
let string_vec: Vec<String> = str_vec.iter().map(|s| (*s).to_string()).collect();
string_vec
}
/// Escapes paths in ffmpeg filters if on windows
pub fn escape_path_in_filter(path: impl AsRef<Path>) -> String {
if cfg!(target_os = "windows") {