I have a folder consisting of many subfolders, each with other subfolders and therein wav files.
I want to convert all of the files like this:
ffmpeg -i BmBmGG-BmBmBmBm.wav -acodec pcm_s16le -ar 44100 BmBmGG-BmBmBmBm.wav
BUT, I want the directory structures and names preserved. Either overwritten or in a parallel directory.
The above command words fine when the output file has a different name, however, with the same name I get an error:
Multiple frames in a packet from stream 0
[pcm_s24le @ 0x1538ac0] Invalid PCM packet, data has size 4 but at least a size of 6 was expected
Error while decoding stream #0:0: Invalid data found when processing input
I first tried bulk converting like this:
ffmpeg -i */*/*.wav -acodec pcm_s16le -ar 44100 */*/*.wav
Unfortunately, this gives the same problem. How can I store them in a parallel directory? Say new///*.wav?
This did the trick:
for f in $(find ./ -name '*.wav'); do
ffmpeg -i $f -acodec pcm_s16le -ar 44100 ${f%.wav}z.wav;
rm $f;
mv ${f%.wav}z.wav $f;
done
Alternatively:
shopt -s globstar nullglob
for f in *.wav **/*.wav
do
ffmpeg -i "$f" -acodec pcm_s16le -ar 44100 "${f%.wav}.new.wav"
mv -f "${f%.wav}.new.wav" "$f"
done
This uses pure-Bash constructs instead of the nasty find
. If your file names (or directory names) contain spaces or special characters, these won't be expanded.
A brief explanation:
shopt -s globstar
enables the double-star operator, so that **/*.wav
will search for wav files in all subdirectories;
- if there are no files with the wav extension,
shopt -s nullglob
makes the two globs expand to zero arguments (note: if this code is part of a larger script, remember to disable nullglob once you are out of the loop, to prevent unwanted behavior);
- all variables are surrounded by double quotes, again to prevent expansion;
mv -f
is used instead of the rm + mv trick.