How to read from a child process stdout pipe without blocking?

⚓ Rust    📅 2025-09-04    👤 surdeus    👁️ 3      

surdeus

Windows 11:

let mut ffmpeg = Command::new(r".\ffmpeg")
            .args([
                "-f",
                "gdigrab",
                "-framerate",
                "1",
                "-i",
                "desktop",
                "-c:v",
                "libx264",
                "-crf",
                "32",
                "-pix_fmt",
                "yuv420p",
                &output_path.to_str().unwrap(),
                "abc.mp4",
                "-f",
                "rawvideo",
                "-",
            ])
            .stdin(Stdio::null())
            .stdout(Stdio::piped())
            .stderr(Stdio::inherit())
            .spawn()
            .unwrap();
[vost#1:0/rawvideo @ 000002353b621880] Error submitting a packet to the muxer: Invalid argument.50    
    Last message repeated 1 times
[out#1/rawvideo @ 000002353b620ec0] Error muxing a packet
[out#1/rawvideo @ 000002353b620ec0] Task finished with error code: -22 (Invalid argument)
[out#1/rawvideo @ 000002353b620ec0] Terminating thread with return code -22 (Invalid argument)
[out#0/mp4 @ 000002353b616900] video:327KiB audio:0KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: 0.254129%
[out#1/rawvideo @ 000002353b620ec0] Error writing trailer: Invalid argument
[out#1/rawvideo @ 000002353b620ec0] Error closing file: Invalid argument

This program encounters an error, but it works fine when I replace stdio::piped() with a file handle. I suspect the pipe gets full and blocks, causing issues with ffmpeg.

I already tried to use BufReader and mpsc, but still failed.

let ffmpeg_stdout = ffmpeg.stdout.take().unwarp();
let mut buf_reader = BufReader::new(ffmpeg_stdout);
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
    let mut buffer = vec![0u8; 8192];
    loop {
        match buf_reader.read(&mut buffer) {
            Ok(0) => break,
            Ok(bytes_read) => {
                if tx.send(buffer[..bytes_read].to_vec()).is_err() {
                    break;
                }
            }
            Err(_) => break,
        }
    }

I also tried to use duct crate

let mut cmd = cmd(r"ffmpeg", ffmpeg_args).reader().unwrap();
loop {
    let mut buf = [0u8; 8196];
    cmd.read_exact(&mut buf);
}

The process's memory usage keeps increasing, which suggests that the contents of the pipe are not being cleared/taken.

I have no idea. Please tell me how to solve this, thanks.

2 posts - 2 participants

Read full topic

🏷️ Rust_feed