3

So, I'm trying to refactor some old code that should remove video streams, compress the audio stream and repack the mp4, which should be a video file with only an audio stream. I later intend to replicate it to work with .wmv.

According to the author, it works like this:

  1. Use mediainfo.exe to get AudioStreamID (1 or 2)

    mediaindo --inform=Audio;%ID% "filename.mp4"
    
  2. Use mp4box.exe and ID from above to extract audio track. Eg. with ID=1:

    mp4box -raw 1 "filename.mp4" -out "filename.aac"
    
  3. Compress audio track with ffmpeg.exe and fdkaac.exe

    ffmpeg -i "filename.aac" -f caf - | fdkaac -b16 -I -p29 - -o "filename.m4a"
    
  4. Remove old audio and video tracks and add a new compressed audio track

    mp4box -rem 1 -rem 2 -add "filename.m4a" "filename.mp4"
    

Then someone else put it into batch:

@echo off
echo CBFT MP4 to SDVL converter
chcp 65001>nul
echo %~n1
setlocal
set mp4box=P:\progz\multimedia\gpac\mp4box.e xe -quiet
set ffmpeg=P:\progz\multimedia\ffmpeg\bin\ff mpeg.exe -hide_banner -v 0
set fdkaac=P:\progz\multimedia\fdkaac\fdkaac .exe
set mediainfo=P:\progz\multimedia\MediaInfo\ MediaInfo.exe
for /R %1 %%f in (*.mp4) do (
echo.
echo %%~nxf
if exist "%%~dpnf.aac" del "%%~dpnf.aac">nul
if exist "%%~dpnf.m4a" del "%%~dpnf.m4a">nul
for /f "tokens=1,2* delims=:" %%a in (
'%mediainfo% --inform^=Audio^;%%ID%%:%%Duration/String3%% "%%f"') do (
echo %%c
%mp4box% -raw %%a "%%f" -out "%%~dpnf.aac" )
%ffmpeg% -i "%%~dpnf.aac" -f caf - | %fdkaac% -b16 -I -p29 - -o "%%~dpnf.m4a"
%mp4box% -flat -rem 1 -rem 2 -add "%%~dpnf.m4a":name= "%%f"
if exist "%%~dpnf.aac" del "%%~dpnf.aac">nul
if exist "%%~dpnf.m4a" del "%%~dpnf.m4a">nul
)
endlocal

And it seemed to work by then, with mp4. Now it breaks in the ffmpeg part, here is my attempt to rebuild it until now:

echo CBFT MP4 to SDVL converter
chcp 65001>nul
echo %~n1
for /R %1 %%f in (*.mp4) do (

echo STARTING
echo %%~nxf
if exist "%%~dpnf.aac" del "%%~dpnf.aac"
if exist "%%~dpnf.m4a" del "%%~dpnf.m4a"

echo start ABOVE
echo mediainfo BELOW
pause

for /f "tokens=1,2* delims=:" %%a in (
'mediainfo --inform^=Audio^;%%ID%%:%%Duration/String3%% "%%f"') do (
echo %%c
mp4box -raw %%a "%%f" -out "%%~dpnf.aac" )

echo mp4box ABOVE
echo ffmpeg BELOW
pause

## This line should compress the audio stream ##

echo ffmpeg ABOVE
echo mp4box BELOW
pause

mp4box -flat -rem 1 -rem 2 -add "%%~dpnf.m4a":name= "%%f"
if exist "%%~dpnf.aac" del "%%~dpnf.aac"
if exist "%%~dpnf.m4a" del "%%~dpnf.m4a"
)
endlocal

Note that it's missing the stream compression section and that I removed fdkaac completely. I'm also guessing that the whole process could be done by a single ffmpeg command (plus the looping part), which would be specially useful when I try to get it to work with the .wmv files.

Could you give some directions on what I should do? That single ffmpeg command, if it is possible, or help me with multiple of them so I make them all work together?

To clarify: my goal is to reproduce steps 1 through 4 with ffmpeg. I believe there are capabilities to filter out streams and probably they're way more economic than this old code. How should I use ffmpeg for this?

0

2 Answers 2

4

I know have a final, working version, even though it could use some improvement on the -f section:

The whole thing (after checking that ffmpeg is available)

:: Actual converting ::

for /r "%~1" %%V in (*.mp4, *.wmv, *.mkv, *.avi, *.webm, *.mov, *.m4v) do (
    for /f "tokens=* delims=." %%A in ("%%~xV") do set ext=%%A
    if !ext!==mkv set ext=matroska
    if !ext!==webm set ext=matroska
    if !ext!==wmv set ext=asf
    ffmpeg -err_detect ignore_err -fflags +igndts -i "%%~fV" -f !ext! -codec:a copy -map 0 -map -0:v -map -0:s -b:a 32k "%%~pnxV.tmpsdvl"
)

:: Moving and Renaming ::

robocopy "%~f1" "SDVL\%~n1" *.tmpsdvl /s /mov
for /r "SDVL\%~n1" %%B in (*.TMPSDVL) do ren %%~fB %%~nB

Breaking it down

The FFmpeg string

ffmpeg -err_detect ignore_err -fflags +igndts -i "%%~fV" -f !ext! -codec:a copy -map 0 -map -0:v -map -0:s -b:a 32k "%%~pnxV.tmpsdvl"

What it does

  • -err_detect ignore_err and -fflags +igndts are some measures taken to power through some common errors;
  • -i "%%~fV" is the full qualified path to my input, since I'm running a for loop;
  • -f !ext! ensures the output uses the format from the previously specified variable. This approach will be clarified below;
  • -codec:a copy tells fmmpeg to use the same encoder for the audio stream;
  • -map 0 selects all streams from the file;
  • -map -0:v then deselects all video streams;
  • -map -0:s deselects every subtitle stream;
  • -b:a 32k sets the audio quality to 32kbps CBR;
  • "%%~pnxV.tmpsdvl" generates the output in the same directory as the input, but with the extension .tmpsdvl added.

The loop

for /r "%~1" %%V in (*.mp4, *.wmv, *.mkv, *.avi, *.webm, *.mov, *.m4v) do (
    for /f "tokens=* delims=." %%A in ("%%~xV") do set ext=%%A
    if !ext!==mkv set ext=matroska
    if !ext!==webm set ext=matroska
    if !ext!==wmv set ext=asf

What it does

This for loop goes through every filetype specified in the parenthesis () in the input folder (which is the first passed argument, "%~1") and uses each match as %%V. Before actually running ffmpeg, we need to define a variable, !ext!, as simply passing an extension to ffmpeg -f won't necessarily work. We also need to trim the leading . in %%xV. This is the only point I believe needs improvement, as I manually had to e.g. convert mkv to matroska in this section.

The moving and renaming

robocopy "%~f1" "SDVL\%~n1" *.tmpsdvl /s /mov
for /r "SDVL\%~n1" %%B in (*.TMPSDVL) do ren %%~fB %%~nB

What it does

This is a bit trivial, but for the sake of thoroughness, this scoops every .tmpsdvl file from the folder this command was applied to and moves it to a separate folder, preserving the original structure. It then ingenuously renames every file to a version without an extension, and since we had file.ext.tmpsdvl, we easily get file.ext

Notes

  • The chosen quality was 32kbps because .wmv files will need at least a 24kbps audio stream;
  • There's still room for improvement in the section where it was necessary to specify ffmpeg -f. Perhaps by using ffprobe.

References

1

ffmpeg -v error -stats -i input.mp4 -vn -sn -dn -acodec libmp3lame -ab 192k -ar 41000 output.mp3

or

-acodec aac -ab 265k out.m4a

or -acodec copy for no compression

1
  • 1
    Ha, I actually found about -acodec copy somewhere else and came up with a similar solution :) Jun 30, 2020 at 0:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .