Parallel processing with Pipe command - windows

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.

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"

Windows CMD Batch Script FFmpeg

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"
)

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.

How to execute ffmpeg from with Batch For Loop

FOR %%A IN (%*) DO ffmpeg -y -i %%A -c:v prores_ks -profile:v 3 -c:a pcm_s16le "%%~dpA%%~nA.mov"
This batch file is intended to take multiple files which are dragged and dropped onto it, and transcode them with ffmpeg. The command results in a whole bunch of prinouts that are similar to the command, but it does not execute. I have also tried using start cmd.exe /c, but that causes numerous windows to open which necessitates a computer reboot.
Edit: squashman has made it clear that this solution would not work anyway (Thanks!). However, I have edited the script to act on only a single file at once and it still does not execute as intended and causes a looping printout.
ffmpeg -y -i %%1 -c:v prores_ks -profile:v 3 -c:a pcm_s16le "%%~dp1%%~n1.mov"
How can I modify this script to execute ffmpeg properly?
Edit 2: Resolved by dragging and dropping a folder onto the batch script.
cd /d %1
md output
FOR /F %%A IN ('dir /B %1') do ffmpeg -y -i %%A -c:v prores_ks -profile:v 3 -c:a pcm_s16le "output/%%~nA.mov"
pause
Expect all .mov files reside in current directory. if not, prepend path into both of "*.mov" and "%%~A.mov".
FOR /F "tokens=1,2 delims=." %%A IN ('dir /B *.mov') do ffmpeg -y -i %%A -c:v prores_ks -profile:v 3 -c:a pcm_s16le "%%~A.mov"
another way is to use PPX http://www.pirosa.co.uk/demo/wxargs/wxargs.html and speed-up whole process by utilizing all CPU cores
dir /b *.%required_file_extension% |ppx2 -P 4 -L 1 ffmpeg -y -i %%A -c:v prores_ks -profile:v 3 -c:a pcm_s16le "{}.mov"
Worth also considering using a build system like SCons.
I've coded up something similar here to transcode a directory's worth of video files all at once from the command-line:
https://github.com/nuket/Shrinkr#shrinkr-batch-transcode-scons-edition
Benefit of a build system is it tracks which source files have changed, so you can interrupt and re-run the batch transcode and it won't repeat already-completed work.

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.

Resources