How can I Pipe the output of FFMPEG 2 Levels of Piping in a bash script

I have been trying to pipe 2 levels deep.

I can pipe successfully:

  1. ffmpeg | grep
  2. ffmpeg | sed

I can not pipe

  1. ffmpeg | grep | sed
  2. ffmpeg | sed | grep

I don't understand, does ffmpeg limit to only one pipe in the chain?

This code has NO OUTPUT with 2 pipes and no errors:

ffmpeg -i "https://17563.live.streamtheworld.com/WETAFM.mp3?nocache=Ag6q8pw2" -af silencedetect=n=-10dB:d=0.5 -f null - 2>&1 | grep silence_duration | sed "s/.*silence_duration: \(.*\).*/\1/"

Expected Output:

2.06442
0.719252
0.594036
0.562698
0.500295

This code has the correct output with 1 pipe:

ffmpeg -i "https://17563.live.streamtheworld.com/WETAFM.mp3?nocache=Ag6q8pw2" -af silencedetect=n=-10dB:d=0.5 -f null - 2>&1 | grep silence_duration

Output:

[silencedetect @ 0000018027f9bd00] silence_end: 2.06442 | silence_duration: 2.06442
[silencedetect @ 0000018027f9bd00] silence_end: 3.45971 | silence_duration: 0.719252
[silencedetect @ 0000018027f9bd00] silence_end: 7.04399 | silence_duration: 0.594036
[silencedetect @ 0000018027f9bd00] silence_end: 7.81501 | silence_duration: 0.562698
[silencedetect @ 0000018027f9bd00] silence_end: 9.05535 | silence_duration: 0.500295

This code has the correct output with 1 pipe:

ffmpeg -i "https://17563.live.streamtheworld.com/WETAFM.mp3?nocache=Ag6q8pw2" -af silencedetect=n=-10dB:d=0.5 -f null - 2>&1 | sed "s/.*silence_duration: \(.*\).*/\1/"

Output:

[silencedetect @ 000001a48277b980] silence_start: 0
2.06442
[silencedetect @ 000001a48277b980] silence_start: 2.74045
0.719252
[silencedetect @ 000001a48277b980] silence_start: 6.44995
0.594036
[silencedetect @ 000001a48277b980] silence_start: 7.25231
0.562698
[silencedetect @ 000001a48277b980] silence_start: 8.55506
0.500295

Solution 1:

Why is grep | sed not doing anything?

It is, but you didn't wait for it. If you press q then ffmpeg will close the stream the silence_duration values will be displayed.

If you want it to print the values immediately one method is to use awk instead.

How to isolate the silence_duration values?

If the ultimate goal is to isolate the silence_duration values use awk:

ffmpeg -i "https://17563.live.streamtheworld.com/WETAFM.mp3?nocache=Ag6q8pw2" -af silencedetect=n=-10dB:d=0.5 -f null - 2>&1 |  awk -F ': ' '/silence_duration/ {print $3}'

Result:

2.06442
0.719252
0.594036
0.562698
0.663968
1.24109

However, I prefer to use the (a)metadata filter with filters that support metadata keys. It is more complicated, but the output is cleaner and easier to parse. You can easily either pipe the info (file=-) or output directly to a file (file=silence.log):

ffmpeg -loglevel error -i "https://17563.live.streamtheworld.com/WETAFM.mp3?nocache=Ag6q8pw2" -af silencedetect=n=-10dB:d=0.5,ametadata=mode=print:key=lavfi.silence_duration:file=- -f null - | awk -F = '/silence_duration/ {print $2}'