-   Linux - Software (
-   -   ffmpeg: batch process all files in folder to single channel (

Steve W 06-17-2016 06:55 AM

ffmpeg: batch process all files in folder to single channel

I sometimes wish to convert mp3 files to single channel only. I would normally do this in the shell by typing:


ffmpeg -v 5 -y -i "my_stereo_file.mp3" -acodec libmp3lame -ac 1 -ab 128k "my_stereo_file 1chan.mp3"
... the "ac 1" switch of course making the mp3 single channel, and I add "1 chan" to the filename to create an output file.

If I have a number of these to do, it would be good to automate the process. I have scripts that, for example, convert all m4a files in a directory to mp3:


for x in *.m4a; do ffmpeg -ab 140k -i "$x" "`basename "$x" .m4a`.mp3"; done
However I cannot figure out how to automatically add the "1 chan" bit to the filename. The m4a conversion script does not need to change the core filename, since it changes the extension to mp3 anyway.

Could anyone suggest the script line I would need to convert all mp3 files in that folder to mp3 with single channel, plus adding "1 chan" to each output filename as it does so?

(I think it has something to do with the Basename function, but having fiddled with this, I keep getting an "unexpected EOF error" when running, which I suspect is due to mismatched quotes, but I cannot figure out which types of quotes go where.)

Thank you for any advice you can give.


malekmustaq 06-17-2016 07:50 AM

You can place applicable descriptive chars or texts somewhere in end of this line --> "`basename "$x" .m4a`.mp3" before or after that bold file suffix. Just try to play it. You will find interesting tricks in computing.

Hope that helps.


teckk 06-17-2016 09:08 AM


for i in *.m4a; do
    ffmpeg -i $i -ac 1 -vn -c:a libmp3lame -b:a 140k "${i%.*}"_1chan.mp3

for i in *.mp3; do
    ffmpeg -i $i -ac 1 -vn -c:a libmp3lame -b:a 128k "${i%.*}"_1chan.mp3

You can test that first with:

for i in *.m4a; do
    echo "${i%.*}_1chan.m4a"
    sleep 1

Steve W 06-18-2016 05:33 AM

Thank you for your solution. I had to put double quotes around the $i, or it couldn't handle filenames of more than one word.

I also got an error saying "Unrecognized option 'c:a'", but I suspect this was due to my ffmpeg version not being the latest. It tells me that I should use "avconv" now, so I replaced "ffmpeg" with "avconv" in your line, and it then worked perfectly!

So my final function is:


for i in *.mp3; do
    avconv -i "$i" -ac 1 -vn -c:a libmp3lame -b:a 128k "${i%.*}"_1chan.mp3

Thank you once again. Didn't need "basename" after all!

I struggle to understand Regular Expressions. Could you please tell me what the percent sign does in the output part of the command ("${i%.*}")? I see that .* means wildcard, but having Googled this, I can find no reference to a percent sign doing anything in this situation. Although I realise symbol in Regular Expressions have multiple uses!


teckk 06-18-2016 09:34 AM

A few examples:


#Get file basename
echo ${i%.*}


#Get file extension
echo ${i#*.}


#Remove _ in filename
echo ${i//_/}


#Get filename before _
echo ${i%_*}


#Get filename after _
echo ${i#*_}

i="my file.txt"

#Replace space with _
${i// /_}


#Remove space in filename
echo ${i// /}

Steve W 06-19-2016 12:14 PM

Ah, so the percent sign in this context means "get the string before the next character". I see. I was mistaking ".*" for the wildcard, but it's the character indicator.

I just tried

echo ${i%l*}
and it produced "my_fi".

Thanks for the information! We live and learn a little each day...


All times are GMT -5. The time now is 06:25 AM.