Home > Back-end >  Execute bash command after a specified string is contained in output
Execute bash command after a specified string is contained in output

Time:05-28

I'm trying to run this command:

~ $ sudo ffmpeg -stream_loop -1 -re -i funnyVideo.mp4 -map 0:v -f v4l2 /dev/video2

which every second outputs the frame number it's displaying:

... other ...
frame=    1 fps=0.0 q=-0.0 size=N/A time=00:00:00.03 bitrate=N/A speed=0.0665x

then the last line is replaced with the new displayed frame number.

frame=   23 fps= 23 q=-0.0 size=N/A time=00:00:00.76 bitrate=N/A dup=15 drop=0

and so on. I'm trying to wait for the string "frame= 205", execute another script and let the process continue:

while IFS= read -r line; do
    if [[ "$line" =~ "frame=   205" ]]; then
          echo "Frame 205 has been reached"
          break;
    fi
done < <(sudo ffmpeg -stream_loop -1 -re -i funnyVideo.mp4 -map 0:v -f v4l2 /dev/video2)

I have no idea what's going on here. Why isn't it echoing Frame 205 has been reached even if I can see the line containing text frame= 205 after a while?

CodePudding user response:

The fact that you can see it is the problem. You never output the lines you read, so how are they showing up? It's because they're not captured.

To capture such lines, redirect stderr to stdout with <(sudo ffmpeg ... 2>&1)

You will then find that ffmpeg doesn't output \ns between these updates, which is how it's making the line update in place. You can use IFS= read -d $'\r' -r line to read carriage returns separators instead.

PS: The frame numbers are based on a timer and therefore not deterministic. Sometimes it'll give you frame= 205 and sometimes frame= 209.

  • Related