Author Topic: mkv to mp4 .bat  (Read 598 times)

dosdan

  • Full Member
  • ***
  • Posts: 157
Re: mkv to mp4 .bat
« Reply #15 on: August 26, 2019, 12:37:41 AM »
Using ADM for the batching of simple Copy |  Copy stuff like this is really kludgy.  It's more straight-forward to do it in FFMPEG. This is a very powerful program that can handle multiple input and output files. However, here we'll be using single input and output files.  Assuming you either have ffmpeg.exe in the current directory or in your Environmental PATH list of directories, and using your supplied MKV file:

ffmpeg -i 01.mkv -hide_banner -c copy -y test.mp4

Note: when operating at the CMD prompt in Windows, you can type one or more starting letters of a filename and then press the Tab key one or more times to find matches. This saves time typing filenames. You can also use the Up Arrow key to recycle through previous command limes, which you can reuse directly, or edit first.

Here, "-i" is followed by the input filename.
"-hide_banner" hides a lot of FFMEG compilation info that can otherwise make the output display very wordy.
"-y" is useful when repeating this or similar commands where the output file already exists and being asked "Do you want to overwrite it?"
"-c copy" is to copy (i.e. not re-encode) the major video & audio stream.
"test.mp4"  specifies both the output filename and the output container format (MP4).

Result:
Code: [Select]
Input #0, matroska,webm, from '01.mkv':
  Metadata:
    ENCODER         : Lavf57.84.100
  Duration: 00:00:26.75, start: 0.000000, bitrate: 19553 kb/s
    Stream #0:0: Video: h264 (High), yuv420p(tv, bt470bg/bt709/bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 60 fps, 60 tbr, 1k tbn, 120 tbc (default)
    Metadata:
      DURATION        : 00:00:26.750000000
    Stream #0:1: Audio: aac (LC), 44100 Hz, stereo, fltp (default)
    Metadata:
      title           : Track1
      DURATION        : 00:00:26.703000000
    Stream #0:2: Audio: aac (LC), 44100 Hz, stereo, fltp (default)
    Metadata:
      title           : Track2
      DURATION        : 00:00:26.703000000
    Stream #0:3: Audio: aac (LC), 44100 Hz, stereo, fltp (default)
    Metadata:
      title           : Track3
      DURATION        : 00:00:26.680000000
Output #0, mp4, to 'test.mp4':
  Metadata:
    encoder         : Lavf58.30.100
    Stream #0:0: Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt470bg/bt709/bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 60 fps, 60 tbr, 16k tbn, 1k tbc (default)
    Metadata:
      DURATION        : 00:00:26.750000000
    Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp (default)
    Metadata:
      title           : Track1
      DURATION        : 00:00:26.703000000
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (copy)
Press [q] to stop, [?] for help
frame= 1603 fps=0.0 q=-1.0 Lsize=   63332kB time=00:00:26.70 bitrate=19429.3kbits/s speed= 207x
video:62759kB audio:525kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.077037%

FFMPEG has found 4 streams in the input container (MKV). Like many programs, it counts from zero. So the 4 streams are:
0:0 Video (h264)
0:1 Audio (AAC)
0:2 Audio (AAC)
0:3 Audio (AAC)

Here the "0:1"  means the 2nd stream in the 1st (zeroth) input file.

Note that in the output file there are only 2 streams:
Code: [Select]
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (copy)

This is because FFMPEG has automatically selected the audio & video streams which it thinks are the most significant. The logic it uses is:
In the absence of any map options for a particular output file, ffmpeg inspects the output format to check which type of streams can be included in it, viz. video, audio and/or subtitles. For each acceptable stream type, ffmpeg will pick one stream, when available, from among all the inputs.

It will select that stream based upon the following criteria:

  • for video, it is the stream with the highest resolution,
  • for audio, it is the stream with the most channels,
  • for subtitles, it is the first subtitle stream found but there’s a caveat. The output format’s default subtitle encoder can be either text-based or image-based, and only a subtitle stream of the same type will be chosen.
In the case where several streams of the same type rate equally, the stream with the lowest index is chosen.

But we want all the steams in the output file. The "-map 0" option will do that:

ffmpeg -i 01.mkv -map 0 -hide_banner -c copy -y test.mp4
Code: [Select]
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (copy)
  Stream #0:2 -> #0:2 (copy)
  Stream #0:3 -> #0:3 (copy)

In this example of 1 video & 3 audio streams this is equivalent to specifying any of the following:
-map 0:v -map 0:a
-map 0:v -map 0:a:0 -map 0:a:1 -map 0:a:2
-map 0:v:0 -map 0:a:0 -map 0:a:1 -map 0:a:2


And, since we have only 1 input file, we can drop the "0:" when mapping e.g.
-map v:0 -map a:0 -map a:1 -map a:2

The order that the maps are specified is significant. We could swap the last two audio streams using:
ffmpeg -i 01.mkv -hide_banner -map v -map a:0  -map a:2  -map a:1   -c copy -y -hide_banner test.mkv
or:
ffmpeg -i 01.mkv -hide_banner -map :0 -map :1  -map :3  -map :2   -c copy -y -hide_banner test.mkv
Code: [Select]
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (copy)
  Stream #0:3 -> #0:2 (copy)
  Stream #0:2 -> #0:3 (copy)

Or we could drop tracks and swap their order using:
ffmpeg -i 01.mkv -hide_banner -map :0 -map :3  -map :2 -c copy -y -hide_banner test.mkv
Code: [Select]
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:3 -> #0:1 (copy)
  Stream #0:2 -> #0:2 (copy)

A batch file to use FFMEG will be presented in my next msg.

Dan.

 



« Last Edit: August 26, 2019, 12:53:58 AM by dosdan »

dosdan

  • Full Member
  • ***
  • Posts: 157
Re: mkv to mp4 .bat
« Reply #16 on: August 26, 2019, 02:00:21 AM »
Convert_MKV_to_MP4 (folder).bat
Code: [Select]
@echo off
setlocal EnableDelayedExpansion
cls

if exist conversion_error.txt del /q conversion_error.txt

:FILES_LOOP
for %%F  in ("%~1\*.mkv") do (
    echo Converting    "%%~F"    to    "%%~dpFconverted\%%~nF.mp4"
if not exist "%%~dpFconverted\" md "%%~dpFconverted\"
ffmpeg.exe -i "%%~fF" -c copy -y -hide_banner -loglevel error -map 0 "%%~dpFconverted\%%~nF.mp4"
if errorlevel 1 echo error occurred: "%%~F"  >> conversion_error.txt
rem Next line shows the MP4 after it has been created, so with multiple MP4s it acts as a sort of progress indicator.
if exist "%%~dpFconverted\%%~nF.mp4" dir "%%~dpFconverted\%%~nF.mp4" | find "/"
rem Remove REM from the start of the next line if you wish to delete the original file if no error occurred in the conversion.
echo "%%~fF"
rem del "%%~fF"
echo.
shift
)
if not "%1"=="" goto FILES_LOOP
goto FINISHED

:FINISHED
@echo off
if exist conversion_error.txt start /i conversion_error.txt
echo.
echo.
pause


Place a shortcut to this batchfile on your Windows desktop and then drag&drop a folder (not selected files within a folder) onto this icon. All the MKVs within the folder will be converted to MP4s.

Test setup:  a directory called "C:\Filename_test\MKV Test" (note the space in the directory name". This directory contains 3 MKVs:
* 01.mkv (actually a bogus media file. This is a renamed text file to evaluate the error-handling when the batchfile encounters a corrupted (simulated) media file.)
* 0 2.mkv  (a media file with a space in its name).
* 03.mkv  (media file without a space in its name)

Result:


The batchfile is designed to continue operating if it encounters errors while processing a folder with thousands of MKV files. Because you may miss this error(s) due to scrolling off the screen, it also pops up a window (conversion_error.txt in the associated program, typically Notepad) at the end, if any errors occurred.

Dan.
« Last Edit: August 26, 2019, 02:14:15 AM by dosdan »