fix: conditionally disable audio track merging

This commit is contained in:
uku 2025-05-19 19:24:11 +02:00
parent 0475c52529
commit dd2616f0e5
Signed by: uku
SSH key fingerprint: SHA256:4P0aN6M8ajKukNi6aPOaX0LacanGYtlfjmN+m/sHY/o
2 changed files with 30 additions and 13 deletions

View file

@ -23,9 +23,10 @@ struct FfprobeOut {
}
#[derive(serde::Deserialize)]
struct StreamInfo {
width: usize,
height: usize,
#[serde(tag = "codec_type", rename_all = "lowercase")]
enum StreamInfo {
Video { width: usize, height: usize },
Audio,
}
#[derive(serde::Deserialize)]
@ -37,6 +38,7 @@ struct FormatInfo {
pub struct VideoMeta {
pub width: usize,
pub height: usize,
pub audio_streams: usize,
pub duration_us: usize,
}
@ -62,10 +64,8 @@ pub async fn get_video_meta(path: &Path) -> Result<VideoMeta> {
.args([
"-v",
"error",
"-select_streams",
"v:0",
"-show_entries",
"stream=width,height : format=duration",
"stream=width,height,codec_type : format=duration",
"-of",
"json",
])
@ -77,17 +77,28 @@ pub async fn get_video_meta(path: &Path) -> Result<VideoMeta> {
let str = String::from_utf8(output.stdout)?;
let output: FfprobeOut = serde_json::from_str(&str)?;
let stream = output
let (width, height) = output
.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")?;
let audio_streams = output
.streams
.iter()
.filter(|s| matches!(s, StreamInfo::Audio))
.count();
let duration_sec = output.format.duration.parse::<f64>()?;
let duration_us = (duration_sec * 1_000_000.0).ceil() as usize;
Ok(VideoMeta {
width: stream.width,
height: stream.height,
width,
height,
audio_streams,
duration_us,
})
}
@ -115,7 +126,6 @@ pub async fn convert_video(
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 {
&["-ac", "2", "-filter_complex", "amerge=inputs=2"]
} else {

View file

@ -94,6 +94,7 @@ struct Tyrolienne {
step: Step,
progress: usize,
total: usize,
can_merge: bool,
video_path: Option<PathBuf>,
out_filename: Option<String>,
out_codec: ffmpeg::Codec,
@ -116,7 +117,7 @@ impl Tyrolienne {
config: self.config.clone(),
out_filename: self.out_filename.clone(),
out_codec: self.out_codec,
merge_tracks: self.merge_tracks,
merge_tracks: self.can_merge && self.merge_tracks,
video_path: self.video_path.clone(),
folder: self.folder.clone(),
}
@ -190,7 +191,10 @@ impl AsyncComponent for Tyrolienne {
adw::SwitchRow {
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())),
},
@ -246,6 +250,7 @@ impl AsyncComponent for Tyrolienne {
step: Step::Waiting,
progress: 0,
total: 1,
can_merge: false,
video_path: None,
out_filename: None,
out_codec: ffmpeg::Codec::VP9,
@ -306,6 +311,8 @@ impl AsyncComponent for Tyrolienne {
.await;
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());
}
}