通过GO循环将FOR循环传递到新命令提示符的问题

时间:2019-06-15 01:00:21

标签: batch-file

这是我的第一篇文章,因此,如果我不能很好地解释它,我对此表示歉意。请让我知道我是否应该重新措辞或澄清一些事情!我的标题也不是很好,所以请告诉我是否应该更改它。

为了帮助自己进一步解释这种情况,我想澄清一下这是什么目的。作为我的兴趣爱好之一,我帮助制作图像档案。问题之一是它支持的唯一视频格式是webm。有时会导致不知道如何转换的用户将视频转换为劣质视频,然后需要稍后对其进行修复。

因此,我一直在处理大量批处理文件,这些文件可以通过最大限度地减少所需的用户输入来加快并可能降低不良转换视频的数量。您可以在这里查看以下内容: https://www.nicklo6649.com/Public%20files/index.php?dir=Batchfiles/

其中一位工作人员提到他们希望如何同时启动多个转换并让其转换整个文件夹,因为他们的CPU足够强大。那就是我现在正在努力的几天。

我当前对脚本的问题是,我似乎无法以任何方式可靠地将FOR循环传递给新命令提示符,该提示在GOTO循环中启动。

我不介意重写当前脚本,只要它仍能够使用FOR循环及其指定的值启动ffmpeg的多个实例。

该解决方案最好以批处理或PowerShell脚本的形式出现,尽管任何其他语言也可以,只要它可以与批处理文件一起使用即可。

我尝试了以下操作:

使用FOR循环开始cmd在GOTO循环中,使用:

start cmd.exe <FOR loop>

在GOTO循环之前将FOR循环保存在文本文件中,在GOTO循环中启动一个名为command2.bat的新批处理文件,然后将FOR循环保存到文本文件中并将其保存到变量中,然后调用变量:

Echo "<FOR loop>"> command.txt

command2.bat script:

setlocal EnableDelayedExpansion
set /p command=<command.txt
set command="%command%"
%command%
endlocal
pause

将FOR循环保存在GOTO循环之前的另一个批处理文件中,然后使用GOTO循环启动该批处理文件:

Echo "<FOR loop>"> command.bat

这是脚本本身。

:next1
rem used to specify the input folder which the FOR loop should look in
set /p input=Input:

rem used to specify the output folder which the FOR loop should look in
set /p output=output:

rem used to specify how many time the GOTO loop should loop and start a new command prompt
set /p amount=:

if "%amount%"=="0" echo fatal error, please retry && goto :next1 

rem this creates a folder for the temporary files ffmpeg needs to store while doing the first pass in two-pass
mkdir "temp files"

@echo on

setlocal EnableDelayedExpansion

set loop=0
:loop
echo.
start cmd.exe for %%f in ("%input%\*.*") do ffmpeg -n -i "%%f" -c:v vp9 -c:a libopus -crf 20 -b:v 192 -pix_fmt yuv420p -pass 1 -f webm "temp files\!random!" && ffmpeg -n -i "%%f" -c:v vp9 -c:a libopus -crf 20 -b:v 192 -an -pix_fmt yuv420p -pass 2 %output%\%%~nf.webm
echo.
set /a loop=%loop%+1 
if "%loop%"=="%amount%" goto :next
if "%loop%"==11 goto :next
goto loop

:next
endlocal
del /q /f ffmpeg2pass*
del /q /f "temp files\*.*"

:end
choice /c EC /n /m "(E)xit or (C)ontinue"
if errorlevel 1 set exit=Quit
if errorlevel 2 set exit=Continue
if "%exit%"=="Quit" goto :exit
if "%exit%"=="Continue" goto :skip
:exit
exit

预期的输出是该脚本开始x个新的命令提示符,每个命令提示符使用脚本中定义的相同FOR循环,并使用指定的输入,输出和将来的选择,例如编解码器。

2 个答案:

答案 0 :(得分:2)

@echo off
setlocal
set "tempdir=temp files"

:next1
rem Specify the input folder which the FOR loop should look in.
set /p "inputdir=InputDir: "
set "inputdir=%inputdir:"=%"

rem Specify the output folder which the FOR loop should look in.
set /p "outputdir=OutputDir: "
set "outputdir=%outputdir:"=%"

rem Specify how many time the GOTO loop should loop and start a new command prompt.
set "amount=0"
set /p "amount=Amount: "

rem Check if integer, else amount will be 0.
set /a "amount+=0"

rem Check if integer is 0.
if "%amount%" == "0" echo Please retry& goto :next1

rem Create a folder for the temporary files ffmpeg needs to store while doing the first pass in two-pass.
if not exist "%tempdir%" md "%tempdir%"

for %%A in ("%inputdir%\*.*") do call :encode "%%~A"
exit /b 0


:encode
setlocal
set "count=0"
set "imagename=ffmpeg.exe"

rem Run tasklist.
if %amount% gtr 1 (
    for /f %%A in ('tasklist /nh /fi "IMAGENAME eq %imagename%"') do (
        if /i "%%~A" == "%imagename%" set /a "count+=1"
    )
)

rem Check count of processes.
if %count% geq %amount% (
    >nul ping -n 10 localhost
    endlocal
    goto :encode
)

rem Set wait for 1 instance only.
set "wait="
if %amount% equ 1 set "wait=/w"

rem Encode with ffmpeg.
start "%ComSpec%" %wait%^
 cmd /c^
 ffmpeg -y -hide_banner -i "%~1" -c:v vp9 -crf 20 -b:v 192k -an -pix_fmt yuv420p -pass 1 -passlogfile "%tempdir%\%~n1" -f webm nul ^&^&^
 ffmpeg -y -hide_banner -i "%~1" -c:v vp9 -crf 20 -b:v 192k -c:a libvorbis -b:a 64k -pix_fmt yuv420p -pass 2 -passlogfile "%tempdir%\%~n1" "%outputdir%\%~n1.webm" ^&^&^
 del "%tempdir%\%~n1-0.log"
exit /b 0

此代码使用tasklist来计数 ffmpeg.exe个实例。如果数量更大 或等于输入的数量,脚本将 等待10秒钟,然后重试 tasklist。这允许计数 ffmpeg.exe个实例最多 输入的金额。

ffmpeg代码差异

  • 音频编码设置为-c:a libvorbis -b:a 64k
  • 第一遍的输出保存到nul
  • 插入-hide_banner以减少控制台输出。
  • -b:v 192更改为-b:v 192k,因此比特率单位 指定类型。似乎比特率较低,也许应该 是-b:v 192K
  • 插入了-passlogfile参数,因此日志文件具有 可以识别的已知且可能唯一的名称。
  • 第一次通过日志文件将在末尾删除 第二遍。

答案 1 :(得分:1)

我希望这会有所帮助。它可能必须进行一些修改。根据主要帖子中的修改,我更改了-y的开关-n

@echo off

setlocal EnableDelayedExpansion

:Pre_Main
::How many instances should be initiated. Limit hardcoded to 11.
::Input dir , Output dir.
set /p input=Input:
set /p output=Output:
set /p amount=Amount:

REM If not defined %amount% (
    REM echo Please specify a number of instances greater than 0
    REM goto :Pre_Main
REM )

if %amount% LEQ 0 (
    echo Please specify a number of instances greater than 0
    goto :Pre_Main
)

cd input

if exist ffmpeg_temp_files (
    rd /s /q ffmpeg_temp_files
) ELSE (
    md ffmpeg_temp_files
)

set "n_loop=1"

::
::End-Pre_Main
::

:loop
for %%f in (*) do (
    @echo on
    echo inside the loop... File: %%f n_loop: !n_loop!
    start "!n_loop!...%%f" ffmpeg.exe -n -i "%%f" -c:v vp9 -c:a libopus -crf 20 -b:v 192 -pix_fmt yuv420p -pass 1 -f webm "temp files\%%~nf_!time!_!n_loop!" && ffmpeg.exe -n -i "%%f" -c:v vp9 -c:a libopus -crf 20 -b:v 192 -an -pix_fmt yuv420p -pass 2 %output%\%%~nf.webm
    @echo off

    if !n_loop! GEQ !amount! goto :Pos_Main
    if !n_loop! EQU 12       goto :Pos_Main
    set /a n_loop=!n_loop!+1
)

:Pos_Main

endlocal

if exist ffmpeg_temp_files rd /s /q ffmpeg_temp_files
del /q /f ffmpeg2pass*

cd ..

choice /c EC /n /m "(E)xit or (C)ontinue"
if %errorlevel% EQU 1 goto :exit 
if %errorlevel% EQU 2 goto :Pre_Main

::
::End-Pos_Main
::

:exit
exit /b