bash script goes off rails when using ffmpeg, I have no clue
I have a series of wav-files and I want to remove all the trailing and preceding silent space. The procedure itself is not the problem, although I may want to revisit that later.
My problem is with the bash script with which I'm doing it. I've written many bash scripts and I think I have covered many of the pitfalls, but here I don't know what's happening. It's a simple loop and the ffmpeg command is somehow influencing the variable in my bash script. I've never seen this before. I the current folder I have a list of wav-files and they consist of 4 numbers and then "dot wav" 0000.wav 0001.wav 0002.wav 0003.wav I collect these wav-files using the command find and put these in a file in a temporary folder. If I cat this file it shows up nice... ./0000.wav ./0001.wav ./0002.wav If I then use it in a "while read SOUND ; do" loop it runs fine too. Only when I use the ffmpeg command in it and use "SOUND" as a parameter, something strange happens. Here's the script and the output. If I comment the remaining "ffmpeg line" it loops nice. I'm hoping someone will give me an "ahaa! moment" cat /usr/local/sbin/remsilence Code:
#!/bin/bash Code:
./0000.wav |
i found that read can read all sorts of things, very unexpected.
i also found that ffmpeg is not so precise with using stdout and stderr etc. shortly, all sorts of weird stuff can happen. also, shouldn't you call cutfile with the file it is going to cut as "$1"? and why don't you just loop over the files directly instead of saving them to a file first? so instead of: Code:
while read SOUND ; do Code:
for SOUND in ????.wav; do |
Hi...
Thanks for thinking with me... The solution is somewhere else, although I haven't yet figured why. BTW.... without reading your answer I tried cutfile "${SOUND}", but that behaved the same The problem is that bash is treating it as numbers. But I still don't understand why it's not doing that immediately wrong. I changed Code:
find -maxdepth 1 -type f -name \*.${EXT} Code:
find `pwd`-maxdepth 1 -type f -name \*.${EXT} EDIT No... it cuts 5 characters away |
Quote:
as it stands, it's wrong - bash treats everything as strings unless you tell it explicitely to use arithmetics. |
Hi.... I already corrected that....
I was just trying to find a reason for this unexpected behaviour.... |
Maybe I should just try another tool for this.
Never had this before. It's just as if I don't know anything about bash anymore... |
cat /usr/local/sbin/remsilence
Code:
#!/bin/bash Code:
/WORKDIR/0000.wav |
Even when I accept that ffmpeg is doing strange things.
Why is it doing this only for the even tries. |
There is two ways to solve this.
Add -nostdin option to your ffmepg commands. From ffmepg's man : Code:
-stdin Code:
ffmpeg -nostdin -loglevel fatal -y -i ${1} -af silenceremove=1:0:-96dB ${TMPDIR}/begincut.${EXT} || return 1 Code:
for SOUND in $(cat ${TMPDIR}/LIST/sounds); do |
you might want to insert set -xv at the beginning of your script to see what's happening. Probably that will give you some additional info.
Replacing that while cycle to for is not really suggested, using while is the preferred solution. Code:
find `pwd` -maxdepth 1 -type f -name \*.${EXT} | grep "${EXT}$" | sort >${TMPDIR}/LIST/sounds Code:
ls -1 *.${EXT} >${TMPDIR}/LIST/sounds |
Thanks all for thinking with me.
lougavulin gave me the key to the solution by telling me I should use the -nostdin with ffmpeg. The script then started to behave like I would expect it to. This is the first time that some binary is messing up my bash-script. Does this happen more? I would think it does. I would really like to hear of some more pitfalls Some things that I did to find some solutions that didn't work I have reverted in this script cat /usr/local/sbin/remsilence Code:
#!/bin/bash |
this is not "some binaries", but there were two apps reading the same stdin stream (fed by <${TMPDIR}/LIST/sounds):
1. obviously the read command 2. now it was the ffmpeg tool. |
After a while you start thinking of bash as a programming language and don't think how they achieve the things you actually want them to do.
At least I did.... |
I now have a way to trim the silence of all wavs in the current folder.
But I'm not satisfied yet. Each ffmpeg action results in a loss. I don't want this. I'm already working with uncompressed WAVs and I see no reason why I should except any loss. That's why I tried to use a different approach. At first I tried "silencedetect", but that gave me unreliable results. Then I thought of a bit "clumsy" way by using the results of the "silenceremove" process and use it to just cut the begin and end of the original WAV-file. That worked. But I still wasn't satisfied. According to the ffmpeg manual there is still some loss unless I use "-c:a copy". So I added that to the command, but then I noticed it sometimes cut into the good part. It seems ffmpeg uses frames when it is used with the "-c:a copy" command. I then thought of shifting the parameters with 15ms so it has a better chance to cut at the right place. Maybe I should ffprobe and extract "pkt_duration_time" and divide that by 2 and use that as offset? Any comments are welcome. cat /usr/local/sbin/remsilence Code:
cat /usr/local/sbin/remsilence |
In the end I just went with the "LESSLOSS" option.
It gives predictable results regarding the places it cuts the file and it's "one-pass" with probably no audible difference. I'm using it for a set of WAVs that are generated by a TTS-engine and used for OpenTX (a radio for Remote Controlled Airplanes). Having a predictable silence is more important and I don't need to check all files to make sure that none are "cut in the flesh". |
All times are GMT -5. The time now is 02:04 PM. |