fix: conditionally disable audio track merging
This commit is contained in:
parent
0475c52529
commit
dd2616f0e5
2 changed files with 30 additions and 13 deletions
|
@ -23,9 +23,10 @@ struct FfprobeOut {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
struct StreamInfo {
|
#[serde(tag = "codec_type", rename_all = "lowercase")]
|
||||||
width: usize,
|
enum StreamInfo {
|
||||||
height: usize,
|
Video { width: usize, height: usize },
|
||||||
|
Audio,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
|
@ -37,6 +38,7 @@ struct FormatInfo {
|
||||||
pub struct VideoMeta {
|
pub struct VideoMeta {
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
pub height: usize,
|
pub height: usize,
|
||||||
|
pub audio_streams: usize,
|
||||||
pub duration_us: usize,
|
pub duration_us: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,10 +64,8 @@ pub async fn get_video_meta(path: &Path) -> Result<VideoMeta> {
|
||||||
.args([
|
.args([
|
||||||
"-v",
|
"-v",
|
||||||
"error",
|
"error",
|
||||||
"-select_streams",
|
|
||||||
"v:0",
|
|
||||||
"-show_entries",
|
"-show_entries",
|
||||||
"stream=width,height : format=duration",
|
"stream=width,height,codec_type : format=duration",
|
||||||
"-of",
|
"-of",
|
||||||
"json",
|
"json",
|
||||||
])
|
])
|
||||||
|
@ -77,17 +77,28 @@ pub async fn get_video_meta(path: &Path) -> Result<VideoMeta> {
|
||||||
let str = String::from_utf8(output.stdout)?;
|
let str = String::from_utf8(output.stdout)?;
|
||||||
let output: FfprobeOut = serde_json::from_str(&str)?;
|
let output: FfprobeOut = serde_json::from_str(&str)?;
|
||||||
|
|
||||||
let stream = output
|
let (width, height) = output
|
||||||
.streams
|
.streams
|
||||||
.first()
|
.iter()
|
||||||
|
.find_map(|s| match s {
|
||||||
|
StreamInfo::Video { width, height } => Some((*width, *height)),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
.wrap_err("could not get stream information from ffprobe")?;
|
.wrap_err("could not get stream information from ffprobe")?;
|
||||||
|
|
||||||
|
let audio_streams = output
|
||||||
|
.streams
|
||||||
|
.iter()
|
||||||
|
.filter(|s| matches!(s, StreamInfo::Audio))
|
||||||
|
.count();
|
||||||
|
|
||||||
let duration_sec = output.format.duration.parse::<f64>()?;
|
let duration_sec = output.format.duration.parse::<f64>()?;
|
||||||
let duration_us = (duration_sec * 1_000_000.0).ceil() as usize;
|
let duration_us = (duration_sec * 1_000_000.0).ceil() as usize;
|
||||||
|
|
||||||
Ok(VideoMeta {
|
Ok(VideoMeta {
|
||||||
width: stream.width,
|
width,
|
||||||
height: stream.height,
|
height,
|
||||||
|
audio_streams,
|
||||||
duration_us,
|
duration_us,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -115,7 +126,6 @@ pub async fn convert_video(
|
||||||
Codec::VP9 => &["-c:v", "libvpx-vp9", "-row-mt", "1"],
|
Codec::VP9 => &["-c:v", "libvpx-vp9", "-row-mt", "1"],
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: maybe check if the video has 2 audio tracks? or at least use a "fail-safe" method
|
|
||||||
let merge_args: &[&str] = if merge_tracks {
|
let merge_args: &[&str] = if merge_tracks {
|
||||||
&["-ac", "2", "-filter_complex", "amerge=inputs=2"]
|
&["-ac", "2", "-filter_complex", "amerge=inputs=2"]
|
||||||
} else {
|
} else {
|
||||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -94,6 +94,7 @@ struct Tyrolienne {
|
||||||
step: Step,
|
step: Step,
|
||||||
progress: usize,
|
progress: usize,
|
||||||
total: usize,
|
total: usize,
|
||||||
|
can_merge: bool,
|
||||||
video_path: Option<PathBuf>,
|
video_path: Option<PathBuf>,
|
||||||
out_filename: Option<String>,
|
out_filename: Option<String>,
|
||||||
out_codec: ffmpeg::Codec,
|
out_codec: ffmpeg::Codec,
|
||||||
|
@ -116,7 +117,7 @@ impl Tyrolienne {
|
||||||
config: self.config.clone(),
|
config: self.config.clone(),
|
||||||
out_filename: self.out_filename.clone(),
|
out_filename: self.out_filename.clone(),
|
||||||
out_codec: self.out_codec,
|
out_codec: self.out_codec,
|
||||||
merge_tracks: self.merge_tracks,
|
merge_tracks: self.can_merge && self.merge_tracks,
|
||||||
video_path: self.video_path.clone(),
|
video_path: self.video_path.clone(),
|
||||||
folder: self.folder.clone(),
|
folder: self.folder.clone(),
|
||||||
}
|
}
|
||||||
|
@ -190,7 +191,10 @@ impl AsyncComponent for Tyrolienne {
|
||||||
|
|
||||||
adw::SwitchRow {
|
adw::SwitchRow {
|
||||||
set_title: "Merge audio tracks",
|
set_title: "Merge audio tracks",
|
||||||
set_active: true,
|
#[watch]
|
||||||
|
set_sensitive: model.can_merge,
|
||||||
|
#[watch]
|
||||||
|
set_active: model.can_merge && model.merge_tracks,
|
||||||
connect_active_notify[sender] => move |s| sender.input(Message::SetMergeTracks(s.is_active())),
|
connect_active_notify[sender] => move |s| sender.input(Message::SetMergeTracks(s.is_active())),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -246,6 +250,7 @@ impl AsyncComponent for Tyrolienne {
|
||||||
step: Step::Waiting,
|
step: Step::Waiting,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
total: 1,
|
total: 1,
|
||||||
|
can_merge: false,
|
||||||
video_path: None,
|
video_path: None,
|
||||||
out_filename: None,
|
out_filename: None,
|
||||||
out_codec: ffmpeg::Codec::VP9,
|
out_codec: ffmpeg::Codec::VP9,
|
||||||
|
@ -306,6 +311,8 @@ impl AsyncComponent for Tyrolienne {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
if let Some(file) = file {
|
if let Some(file) = file {
|
||||||
|
let meta = ffmpeg::get_video_meta(file.path()).await;
|
||||||
|
self.can_merge = meta.map(|m| m.audio_streams == 2).unwrap_or(false);
|
||||||
self.video_path = Some(file.path().to_owned());
|
self.video_path = Some(file.path().to_owned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue