Merging videos with mencoder

      Comments Off on Merging videos with mencoder

In this article, I present an easy way to merge all video files in a directory using the Open Source tool mencoder (part of mplayer, the video player) using a batch file, suitable for Windows XP and later. The method below supports merging AVI, MPG, MP4, WMV and RM files.

Mencoder supports an option called Stream Copying, using which you can concatenate video and audio streams.

Note: All input video files need to have the same dimensions, frame rate and codec type! This is a limitation imposed by mencoder (and quite reasonable too, because we copy all content. Otherwise, you’d need to convert some or all videos).

Usually, split videos come with filenames like video-01.wmv, video-02.wmv, etc. To process these, a for loop is ideal, looping through a sorted list of file names.
As mencoder needs to be instructed which format it should use (for the video container), we need to use the extension of the input files.
Of course, the script can be modified to use mencoder’s format conversion functions, but I wanted a simple merge, which most video converters do not offer. Once the file is merged, you can use a tool like handbrake to convert the format.

Here is the code in its entirety, below I have provided details on each section of the script:

setlocal enableextensions enabledelayedexpansion
set MENC=c:mplayermencoder.exe -oac copy -ovc copy
set FSEL=%1
if not defined FSEL set FSEL=*.wmv
set EXT=
set FL=
set OF=
for /f "tokens=*" %%I in ('dir /b /on %FSEL%') do set FL=!FL! "%%~nxI"&if not defined OF (set OF=%%~nI&set EXT=%%~xI)
if not defined FL exit /b
set OF=%OF%_merged%EXT%
if exist "%OF%" exit /b
if /i "%EXT%" equ ".avi" %MENC% -o "%OF%" %FL%
if /i "%EXT%" equ ".mpg" %MENC% -of mpeg -o "%OF%" %FL%
if /i "%EXT%" equ ".mp4" %MENC% -of lavf -lavfopts format=mp4 -o "%OF%" %FL%
if /i "%EXT%" equ ".wmv" %MENC% -of lavf -lavfopts format=asf -o "%OF%" %FL%
if /i "%EXT%" equ ".rm" %MENC% -of lavf -lavfopts format=rm -o "%OF%" %FL%
exit /b

Detailed explanation.

First, enable command line extensions and delayed variable expansion. This allows me to use extended options of the batch language in the cmd window (like if defined), as well as to modify a variable in a loop (without using a subroutine):

setlocal enableextensions enabledelayedexpansion

Set the location of the mencoder executable, as well as the copy arguments for the video and audio stream. Adapt this to the location of your copy of mencoder.

set MENC=c:mplayermencoder.exe -oac copy -ovc copy

Initialize the file name related variables:

  • FSEL is the mask for the files to process
  • EXT is the video file extension (extracted from the first video file)
  • FL is the input File List
  • OF is the Output File.

If you call the batch file  with a parameter, that value will be used for FSEL. If the parameter is not provided, FSEL is set to *.wmv to represent the input file selection you want to process.

set FSEL=%1
if not defined FSEL set FSEL=*.wmv
set EXT=
set FL=
set OF=

Construct the input file list by looping through the FSEL files, in order of file name (The FOR command does not automatically sort a file list by name, so we use a DIR/on to order by name).
Here, the delayed variable expansion is used (!FL!), so we can update the value of FL in the loop with each file name encountered in the DIR command. (Check the output of the command for /? for details on that problem).
When processing the first file, the output file name is not defined yet, so that is used to set an output file name (without extension), and the extension of the file is stored.

Note: I have a rule about using quotes and variables: Use quotes only on the place that you need to use them (like when passing them to a command). That makes merging text much easier. As for the FL variable, this needs to contain quotes around the individual file names, so I need to set this up here…

After the loop, FL is checked. If it is empty (no matches for the file selection), the script quits.

for /f "tokens=*" %%I in ('dir /b /on %FSEL%') do set FL=!FL! "%%~nxI"&if not defined OF (set OF=%%~nI&set EXT=%%~xI)
if not defined FL exit /b

Next, construct the output file name by adding the text “_merged” and the extension:

set OF=%OF%_merged%EXT%

Check if the output file already exists. If so, quit the script, so it never overwrites an existing file:

if exist "%OF%" exit /b

Here is where the merge is done based on the extension type:

if /i "%EXT%" equ ".avi" %MENC% -o "%OF%" %FL%
if /i "%EXT%" equ ".mpg" %MENC% -of mpeg -o "%OF%" %FL%
if /i "%EXT%" equ ".mp4" %MENC% -of lavf -lavfopts format=mp4 -o "%OF%" %FL% 
if /i "%EXT%" equ ".wmv" %MENC% -of lavf -lavfopts format=asf -o "%OF%" %FL%
if /i "%EXT%" equ ".rm"  %MENC% -of lavf -lavfopts format=rm  -o "%OF%" %FL%

Finally, cleanly exit the script:

exit /b