Windows: Recursively convert FLAC to MP3 w/ ffmpeg

I have ffmpeg installed and use batch files to convert MP4 h.264 to MKV x.265 successfully, but I have a problem with converting FLAC files to 320 kbps MP3 w/ no metadata needed. Although many posts explain how to do this in Linux, their scripts don't solve this problem when run in the command prompt of Windows.

The command line script I have created to convert to MP3 has this line:

for %%A in (*.flac) do ffmpeg -i "%%~nA.flac" -c:v copy -b:a 320k "%%~nA.mp3"

Not being adept at Powershell, I am looking for a command line solution. I don't care if metadata survives or not.

How may I modify that to convert all FLAC files in the current directory and all sub directories beneath it (as shown in the first link above for Linux)?


Solution 1:

The following .bat file should do it:

for /R %%A in (*.flac) do ffmpeg -i "%%A" -c:v copy -b:a 320k "%%~dpnA.mp3"

You may test it first with this script:

for /R %%A in (*.flac) do echo ffmpeg -i "%%A" -c:v copy -b:a 320k "%%~dpnA.mp3"

Explanation for the above substitutions (they are combined in the script above):

  • %~dA - expands %A to a drive letter only
  • %~pA - expands %A to a path only
  • %~nA - expands %A to a file name only

Solution 2:

@echo off 

cd /d "%~dp0" & setlocal 
set "_flag1=-c:v copy -b:a 320k"
set "_flag2=-hide_banner -v error -stats"
set "_ffmpeg="C:\Program Files\FFmpeg\Bin\FFmpeg.exe" -i"

for /r %%i in (*.Flac)do %_ffmpeg% "%%~i" %_flag1% "%%~dpni.mp3" %_flag2%
%__AppDir__%timeout.exe /t 5 /nobreak |echo=Is Done! & endlocal & goto :eof

  • The same without defining/using variables:
@echo off & setlocal & cd /d "%~dp0"

for /r %%i in (*.Flac)do "C:\Program Files\FFmpeg\Bin\FFmpeg.exe" -i ^
  "%%~i" -c:v copy -b:a 320k "%%~dpni.mp3" -hide_banner -v error -stats
  
%__AppDir__%timeout.exe /t 5 /nobreak |echo=Is Done! & endlocal & goto :eof

Do you really need to use .Flac twice?
And you gonna always save all converted files in the same folder (work directory)?

for %%A in (.flac) do ffmpeg -i "%%~nA.flac" -c:v copy -b:a 320k "%%~nA.mp3"
for /R %% A in (.flac) from ffmpeg -i "%%~pI%%~nA.flac" -b:a 320k "%%~nA.mp3" fails with the same error as noted before...

1. Remove n and .flac

for %%A in (*.flac) do ffmpeg -i "%%~nA.flac" -c:v copy -b:a 320k "%%~nA.mp3"
  • Obs.: 1 The For loop variable "%%~A" provide to you the full path to the input file, you don't need to crop name and/or add explicitly:
"%~Drive\\Path\\Name.Flac"
"%%~dpn.Flac"
"%%~N.Flac"

rem :: use
ffmpeg -i  "%%#~A" ...

2. Use For /R:

For /R %%i in (*.flac)do ...

3. Consider define/adding a drive:\folder\ to save the target encoded file, not just a name, if not to save it in the same work directory your bat are in.

 ... (...)do.... ffmpeg ... "%%~dpni.mp3"
  • Obs.: 2 To save your .mp3 in the current/work directory, youc can use:
 ... (...)do.... ffmpeg ... "%%~ni.mp3"
 ... (...)do.... ffmpeg ... ".\%%~ni.mp3"
 ... (...)do.... ffmpeg ... "%CD%\%%~ni.mp3"
  • Obs.:: 3 All metadata survives!!

One suggest using For /F + where /R

@echo off

setlocal & cd /d "%~dp0"    

for /f delims^= %%i in ('
2^>nul %__AppDir__%where.exe /r . *.flac
')do "C:\Program Files\FFmpeg\Bin\FFmpeg.exe" -i "%%~i" -c:v ^
     copy -b:a 320k "%%~dpni.mp3" -hide_banner -v error -stats

%__AppDir__%timeout.exe 5 /nobreak |echo=Is Done! & endlocal & goto :eof
  • Obs.:: 4 For break line using ^, do not use any spaces/character after the caret:

enter image description here


Additional resources:

  • Set /?
  • For /?
  • For /F
  • For /R
  • Where /?
  • Timeout /?
  • Redirection
    • |, <, >, 2>, etc.
  • Conditional Execution
    • || and &&
  • Local Environment | Function | Also Refer: Goto :EOF
    • Setlocal & Endlocal
  • Split long commands in multiple lines through Windows batch file
  • How does the Windows Command Interpreter [cmd.exe] Parse Scripts