fix: bound ffmpeg encoding processes

This commit is contained in:
2026-09-24 18:46:09 +08:00
parent 1f9da14772
commit 704b14f05a
2 changed files with 43 additions and 11 deletions
+22 -7
View File
@@ -263,7 +263,7 @@ async fn resolve_bsky_video(
let list_str = list_path.to_string_lossy().into_owned(); let list_str = list_path.to_string_lossy().into_owned();
let output_str = output.to_string_lossy().into_owned(); let output_str = output.to_string_lossy().into_owned();
let status = tokio::task::spawn_blocking(move || { let status = tokio::task::spawn_blocking(move || {
std::process::Command::new("ffmpeg") let mut child = std::process::Command::new("ffmpeg")
.args([ .args([
"-y", "-y",
"-f", "-f",
@@ -280,15 +280,30 @@ async fn resolve_bsky_video(
]) ])
.stdout(std::process::Stdio::null()) .stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null()) .stderr(std::process::Stdio::null())
.status() .spawn()
.map_err(|e| format!("ffmpeg spawn failed: {e}"))?;
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(300);
loop {
match child
.try_wait()
.map_err(|e| format!("ffmpeg wait failed: {e}"))?
{
Some(status) => break Ok(status),
None if std::time::Instant::now() >= deadline => {
let _ = child.kill();
let _ = child.wait();
break Err("ffmpeg exceeded 300s".to_string());
}
None => std::thread::sleep(std::time::Duration::from_millis(50)),
}
}
}) })
.await .await
.map_err(|e| format!("bsky remux worker panicked: {e}"))?; .map_err(|e| format!("bsky remux worker panicked: {e}"))??;
match status { if !status.success() {
Ok(s) if s.success() => Ok(Some((output, out_dir))), return Err(format!("ffmpeg exited with {status}"));
Ok(s) => Err(format!("ffmpeg exited with {s}")),
Err(e) => Err(format!("ffmpeg spawn failed: {e}")),
} }
Ok(Some((output, out_dir)))
} }
/// Fetches a post thread by handle or DID (`at://` URIs work for both). /// Fetches a post thread by handle or DID (`at://` URIs work for both).
+19 -2
View File
@@ -333,7 +333,7 @@ impl PixivAPI {
let framerate = 1000.0 / median as f64; let framerate = 1000.0 / median as f64;
let output = out_dir.path().join("ugoira.mp4"); let output = out_dir.path().join("ugoira.mp4");
let status = std::process::Command::new("ffmpeg") let mut child = std::process::Command::new("ffmpeg")
.args([ .args([
"-y", "-y",
"-framerate", "-framerate",
@@ -357,11 +357,28 @@ impl PixivAPI {
]) ])
.stdout(std::process::Stdio::null()) .stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null()) .stderr(std::process::Stdio::null())
.status() .spawn()
.map_err(|e| format!("ffmpeg spawn failed: {e}"))?; .map_err(|e| format!("ffmpeg spawn failed: {e}"))?;
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(300);
loop {
match child
.try_wait()
.map_err(|e| format!("ffmpeg wait failed: {e}"))?
{
Some(status) => {
if !status.success() { if !status.success() {
return Err(format!("ffmpeg exited with {status}")); return Err(format!("ffmpeg exited with {status}"));
} }
break;
}
None if std::time::Instant::now() >= deadline => {
let _ = child.kill();
let _ = child.wait();
return Err("ffmpeg exceeded 300s".to_string());
}
None => std::thread::sleep(std::time::Duration::from_millis(50)),
}
}
Ok((output.to_string_lossy().into_owned(), out_dir)) Ok((output.to_string_lossy().into_owned(), out_dir))
}) })
.await .await