Windows CMD Batch Script FFmpeg - windows

I have created a batch file (.bat) that uses FFmpeg to transcode various videos (with *.mov or *.mp4 file name extension) from an input folder to an output folder (with extension *.mkv) as batch process (Windows 10 environment).
File names (without extension) from the input folder should be copied to the newly created output file names (that have the new file extension *.mkv).
#echo off
set CMD=ffmpeg -c:v ffv1 -level 3 -g 1 -coder 1 -context 1 -pix_fmt + -slices 24 -slicecrc 1 -report -c:a pcm_s24le
FOR /R input_folder %%G IN (*.mov,*.mp4) DO (
echo %%G
call set outputfile=%%~nG%.mkv
call set inputfile=%%~nG%%~xG
echo %CMD% -y output_folder/%outputfile% -i %inputfile%
)
But this script does not work as expected, i.e. nothing happens.
Do you perhaps have an idea how to fix this?
Thanks in advance!

Here's an example showing my suggestions from the comments, with the addition of the file deletion as requested in the comments too. This assumes that ffmpeg returns an errorlevel of 0 upon success, (you don't want to delete them if the processing failed), and that there is an existing directory named output_folder, in the current working directory.
#Echo Off
SetLocal EnableExtensions
Set "CMD=ffmpeg.exe -c:v ffv1 -level 3 -g 1 -coder 1 -context 1 -pix_fmt +"
Set "CMD=%CMD% -slices 24 -slicecrc 1 -report -c:a pcm_s24le"
For /R "input_folder" %%G In (*.mov *.mp4) Do (
Echo %%G
%CMD% -y "output_folder\%%~nG.mkv" -i "%%G"
If Not ErrorLevel 1 Del /A /F "%%G"
)

Related

How to set file name after merging video files (batch script, FFMPEG)

I use this bat script for converting .mp4(x264) files to .mp4(x265)
for %% in ("*.mp4") do ffmpeg -i "%%a" -c:v hevc "%dp0NewFolder\%%~na[HEVC].mp4"
So I'm trying to make another bat script for merging video files(concat).
for %%i in (*.mp4) do echo file '%%i'>> vlist.txt
ffmpeg -f concat -safe 0 -i vlist.txt -c copy %~dp0NewFolder\%%~na.mp4
Files to merge would be like
Vid_1.mp4,
Vid_2.mp4,
Vid_#.mp4
...
I want to keep the part before "_" in the new file name
What should I use instead of %%~na? To make it just Vid.mp4
Currently it creates %~na.mp4
From what I got you don't need a big scheme to create a output filename since we are talking about 1 filename only, or did I get something wrong?
for /f "delims=_" %%a in ('dir /b /a-d *.mp4') do set "NewVideoName=%%a"& goto :Next
:Next
ffmpeg -f concat -safe 0 -i vlist.txt -c copy "NewFolder\%NewVideoName%.mp4"

FFmpeg Batch loop through files in two different folders at the same time

I have files in two folders like this
Video
record01.mkv
record02.mkv
Audio
audio1.avi
audio2.avi
Merged
I would like to run a loop to combine the files in the folders with one-to-one correspondence based on alphabetical order (es. first file in "Video" folder combines with first file in "Audio" folder and so on)
The command I need to use is simple:
ffmpeg -i "record01.mkv" -i "audio1.avi" -map 0 -map 1 -map -1:v -c copy ".\Merged\record01.mkv"
I tried with the following command but it didn't work (as I expected since files in the two different folders have different names)
FOR /R %%i IN (*.mp4) DO ffmpeg -i ".\Video\%%i" -i ".\Audio\%%i" -map 0 -map 1 -map -1:v -c copy ".\Merged\%%~dni.mkv"
Thank you!
There is a trick to read two files in parallel (or one file and one command output): use a for loop for one input-stream and redirection plus set /p for the other (this one has to be a file):
#echo off
setlocal enabledelayedexpansion
dir /b /s /on audio\*.avi > audioFiles
< audioFiles (for /f %%a in ('dir /on /b /s video\*.mkv') do (
set /p "audio="
echo %%a, !audio!
))
I trust you are able to implement the ffmpeg command yourself.

Parallel processing with Pipe command

I'd like to parallel process the command that downloads a live stream.
So if it has 4 parts and the PARTS variable contains the number 4, it should open 4 new cmd windows and process the individual part.
After reading a lot about parallel processing I came to the following solution:
set /p URL=Enter video URL:
set /p NAME=Enter video name:
set /p PARTS=Enter Number of Parts:
for /l %%x in (1, 1, %PARTS%) do (
start cmd /C "C:\Program Files (x86)\Streamlink\bin\streamlink.exe" -O "%URL%/%%x" best | ffmpeg -y -i pipe:0 -c:v copy -c:a copy -absf aac_adtstoasc "%NAME%p%%x.mp4"
)
There seems to be an issue with the | command though since this script would open windows that close right after start and the output of the piped command ffmpeg -y -i pipe:0 -c:v copy -c:a copy -absf aac_adtstoasc "%NAME%p%%x.mp4 would show in the initial cmd window that executed the script.
How can I change it so the whole command gets executed in the new window?
To not let the pipe process the output of the start command, you need to escape it:
start "" cmd /C "C:\Program Files (x86)\Streamlink\bin\streamlink.exe" -O "%URL%/%%x" best ^| ffmpeg -y -i pipe:0 -c:v copy -c:a copy -absf aac_adtstoasc "%NAME%p%%x.mp4"
Since quotation is not modified this way, the used path and all variable parts still appear quoted to the calling cmd instance too, so no more additional escaping is required, unless these strings may contain quotation marks on their own, in which case I strongly recommend delayed expansion:
setlocal EnableDelayedExpansion
rem // some other code...
set /P URL="Enter video URL: "
set /P NAME="Enter video name: "
rem // some other code...
start "" cmd /C "C:\Program Files (x86)\Streamlink\bin\streamlink.exe" -O "!URL!/%%x" best ^| ffmpeg -y -i pipe:0 -c:v copy -c:a copy -absf aac_adtstoasc "!NAME!p%%x.mp4"
rem // some other code...
endlocal
The "" behind the start command should be stated to provide a window title; otherwise an error could occur as the first quoted item was taken as the title rather than as part of the command line.
The above line still could cause problems, since the cmd instance executing the actual commands receives the already expanded values rather than the variable. So you might even need to do this:
rem // Supposing delayed expansion is disabled in the hosting `cmd` instance:
start "" cmd /C /V "C:\Program Files (x86)\Streamlink\bin\streamlink.exe" -O "!URL!/%%x" best ^| ffmpeg -y -i pipe:0 -c:v copy -c:a copy -absf aac_adtstoasc "!NAME!p%%x.mp4"
setlocal EnableDelayedExpansion
rem // Supposing delayed expansion is enabled in the hosting `cmd` instance:
start "" cmd /C /V "C:\Program Files (x86)\Streamlink\bin\streamlink.exe" -O "^!URL^!/%%x" best ^| ffmpeg -y -i pipe:0 -c:v copy -c:a copy -absf aac_adtstoasc "^!NAME^!p%%x.mp4"
endlocal
Note that the pipe | creates two more cmd instances one for either side, implicitly.

FFMPEG - Automatic Stream Copy Then Encode On Fail

I've embarked on a mission to get rid of all of my MKV files since the MP4 container works better for me. So to that end, I did some research and wrote a small script that searches my data files for MKVs and stream copies them to MP4. The script works most of the time, but I get the occasional file that fails and since the script deletes the originals, I lose the file completely.
I'd like to modify the script in two ways:
(1) Before deleting the original file, check that the converted file is greater than zero.
(2) If the converted file is zero (failed) then run an FFMPEG command to re-encode the original file using default values utilizing Intel Quick Sync hardware encoding, then delete the original as usual and go on to the next file in the list.
Here's what I have so far...
#ECHO OFF
cls
echo This script automatically converts MKV video files to MP4.
echo.
echo Changing directory to data drive (Z:).
echo.
Z:
echo Retrieving list of MKV files...
echo.
dir /b /s *.mkv > MKV-Files.txt
echo MKV list compiled.
echo.
echo Converting files to MP4...
echo.
FOR /F "delims=;" %%F in (MKV-Files.txt) DO (
echo Converting "%%F"
echo.
C:\FFMPEG\bin\ffmpeg.exe -y -i "%%F" -movflags faststart -codec copy "%%~dF% %~pF%%~nF.mp4"
echo.
echo Conversion successful.
echo.
echo Deleting "%%F"
echo.
del "%%F" /F
)
echo Job completed.
echo.
echo Exiting...
Thanks in advance for your ideas.
You can try this substitution:
ffmpeg.exe -y -i "%%F" -abort_on empty_output -movflags faststart -codec copy "%%~dF% %~pF%%~nF.mp4" || ffmpeg.exe -y -i "%%F" -movflags faststart -c:v h264_qsv -c:a copy "%%~dF% %~pF%%~nF.mp4"
You may want to disable subtitle or data tracks as MP4 has limited support for them. Add -dn and -sn for that.

Windows Batch - Change the beginning of a path but keep the rest

I'm running FFMPEG for video encoding.
I have a batch file which will encode files you drop on it, keeping the file's original name and copy the encoded files to a specific directory.
I would like that script to "know" the original's file path and copy the encoded file to a path relative to it, meaning:
original file dropped on batch file is in C:\some\folder\show\season\episode\file.mov
encoded file should be encoded to D:\different\directory\show\season\episode\file.mp4
The part of the path up until \show is fixed.
This is what I have so far:
#echo on
set count=0
for %%a in (%*) do (<br>
if exist %%a (
md \\specific\path\"%%~na"
%MYFILES%\ffmpeg.exe -i "%%~a" -vcodec libx264 -preset medium -vprofile baseline -level 3.0 -b 500k -vf scale=640:-1 -acodec aac -strict -2 -ac 2 -ab 64k -ar 48000 "%%~na_500.mp4"
copy "%%~na_500.mp4" "\\specific\path\"%%~na"\%%~na_500.mp4"
copy "%%~na_500.mp4" "\\specific\path\"%%~na"\%%~na_500.mp4"
del "%%~na_500.mp4"
set /a count+=1
) else (
echo Skipping non-existent %%~a
Thank you,
Oren
#ECHO OFF
SETLOCAL
SET "MYFILES=MY_files"
SET "fixed_path=u:\destdir"
FOR %%a IN ("%*") DO IF EXIST "%%a" (
FOR /f "tokens=3*delims=\" %%b IN ("%%~dpa") DO (
ECHO(MD "%fixed_path%\%%c"
ECHO(%MYFILES%\ffmpeg.exe -i "%%~a" -vcodec libx264 -preset medium -vprofile baseline -level 3.0 -b 500k -vf scale=640:-1 -acodec aac -strict -2 -ac 2 -ab 64k -ar 48000 "%%~na_500.mp4"
ECHO(copy "%%~na_500.mp4" "%fixed_path%\%%c%%~na_500.mp4"
ECHO(del "%%~na_500.mp4"
)
) ELSE (ECHO(%%~a does NOT EXIST
)
GOTO :EOF
The required MD commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(MD to MD to actually create the directories. Append 2>nul to suppress error messages (eg. when the directory already exists)
Similarly, the DEL and COPY commands are merely echoed.
I set myfiles to a constant - no doubt yours will be different and I set fixed _path to a constant for convenience of editing.
No idea whether the ffmpeg command is correct - just edited yours, and I'm puzzled by your use of two apparently identical copy commands in succession, but maybe my eyes are playing tricks...

Resources