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:
parent
657810d162
commit
5fbee3dfed
|
@ -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") {
|
||||
|
|
Loading…
Reference in a new issue