这个批处理文件不起作用,我知道 ffmpeg 命令在命令独立时可以工作。
我使用的 WAV 文件与视频的长度完全相同(它是从我试图将其添加回的视频中提取的)。
如果我从 ffmpeg.exe 和批处理文件所在的文件夹中删除 wav 和/或视频文件,NOAUDIO 和 NOVIDEO 标签可以正常工作。
当批处理文件与 wav 音频和 mp4 视频文件一起运行时,它只会闪烁一个命令窗口。我尝试在每个命令后暂停,但仍然没有乐趣。
这里有什么错误吗?
大家干杯...
:: --------------------
::
:: This will put any included WAV file with any included
:: video file, assuming the video file type exists:
::
:: - AVI
:: - MKV
:: - MP4
:: - WEBM
::
:: --------------------
@echo off
title Replace Video Audio with WAV
color 0f
:: --------------------
if not exist *.wav goto NOAUDIO
if not exist *.avi if not exist *.mkv if not exist *.mp4 if not exist *.webm goto NOVIDEO
:: --------------------
if exist *.avi goto AVIFILE
if exist *.mkv goto MKVFILE
if exist *.mp4 goto MP4FILE
if exist *.webm goto WEBMFILE
:: --------------------
For %%a IN ("*.wav") DO Set "FILEWAV=%%~na"
:: --------------------
:AVIFILE
For %%a IN ("*.avi") DO Set "FILEAVI=%%~na"
start /wait ffmpeg.exe -i "%FILEAVI%.avi" -i "%FILEWAV%.wav" -c:v copy -map 0:v:0 -map 1:a:0 "%FILEAVI%-NEW.mp4"
goto FINISHED
:MP4FILE
For %%a IN ("*.mp4") DO Set "FILEMP4=%%~na"
start /wait ffmpeg.exe -i "%FILEMP4%.mp4" -i "%FILEWAV%.wav" -c:v copy -map 0:v:0 -map 1:a:0 "%FILEMP4%-NEW.mp4"
goto FINISHED
:WEBMFILE
For %%a IN ("*.webm") DO Set "FILEWEBM=%%~na"
start /wait ffmpeg.exe -i "%FILEWEBM%.webm" -i "%FILEWAV%.wav" -c:v copy -map 0:v:0 -map 1:a:0 "%FILEWEBM%-NEW.mp4"
goto FINISHED
:MKVFILE
For %%a IN ("*.mkv") DO Set "FILEMKV=%%~na"
start /wait ffmpeg.exe -i "%FILEMKV%.mkv" -i "%FILEWAV%.wav" -c:v copy -map 0:v:0 -map 1:a:0 "%FILEMKV%-NEW.mp4"
goto FINISHED
:: --------------------
:NOAUDIO
cls
echo.
echo.
echo There is no audio to put with the video!
echo.
echo Exiting...
timeout 6 >nul
goto FINISHED
:: --------------------
:NOVIDEO
cls
echo.
echo.
echo There is no video to put audio with!
echo.
echo Exiting...
timeout 6 >nul
goto FINISHED
:: --------------------
:FINISHED
exit
:: --------------------
我刚刚测试了这个,它确实有效,使用与上面批处理文件中完全相同的命令,只是删除了所有标签...
For %%a IN ("*.wav") DO Set FILEWAV=%%~na
:MP4FILE
For %%a IN ("*.mp4") DO Set FILEMP4=%%~na
start /wait ffmpeg.exe -i "%FILEMP4%.mp4" -i "%FILEWAV%.wav" -c:v copy -map 0:v:0 -map 1:a:0 "%FILEMP4%-NEW.mp4"
goto FINISHED
:FINISHED
exit
所以我知道它不起作用的原因与批处理文件的运行顺序有关。这很奇怪,因为我有另一个批处理文件,就像它一样,用于首先提取 WAV,并且它确实有效,其标签设置就像上面的第一个批处理文件一样。令人困惑。
如果我将其减少到这样,它就可以工作......
For %%a IN ("*.wav") DO Set FILEWAV=%%~na
For %%a IN ("*.avi") DO Set FILEAVI=%%~na
start /wait ffmpeg.exe -i "%FILEAVI%.avi" -i "%FILEWAV%.wav" -c:v copy -map 0:v:0 -map 1:a:0 "%FILEAVI%-NEW.mp4"
For %%a IN ("*.mp4") DO Set FILEMP4=%%~na
start /wait ffmpeg.exe -i "%FILEMP4%.mp4" -i "%FILEWAV%.wav" -c:v copy -map 0:v:0 -map 1:a:0 "%FILEMP4%-NEW.mp4"
For %%a IN ("*.webm") DO Set FILEWEBM=%%~na
start /wait ffmpeg.exe -i "%FILEWEBM%.webm" -i "%FILEWAV%.wav" -c:v copy -map 0:v:0 -map 1:a:0 "%FILEWEBM%-NEW.mp4"
For %%a IN ("*.mkv") DO Set FILEMKV=%%~na
start /wait ffmpeg.exe -i "%FILEMKV%.mkv" -i "%FILEWAV%.wav" -c:v copy -map 0:v:0 -map 1:a:0 "%FILEMKV%-NEW.mp4"
exit
主要问题是命令行
For %%a IN ("*.wav") DO Set "FILEWAV=%%~na"
由于命令 goto
在上述四个
if
条件下,因此不会对找到的任何视频文件执行。因此,其中一个
ffmpeg.exe
命令行是使用环境变量 FILEWAV
执行的,很可能根本没有定义,至少不是由批处理文件定义的。
批处理文件可以改进为:
@echo off
:: --------------------
::
:: This will put any included WAV file with any included
:: video file, assuming the video file type exists:
::
:: - AVI
:: - MKV
:: - MP4
:: - WEBM
::
:: --------------------
setlocal EnableExtensions DisableDelayedExpansion
title Replace Video Audio with WAV
color 0f
if not exist %SystemRoot%\System32\where.exe goto CheckAudio
%SystemRoot%\System32\where.exe ffmpeg.exe >nul 2>nul
if not errorlevel 1 goto CheckAudio
echo(
echo(
echo There is ffmpeg.exe not found in current directory or
echo any directory defined in environment variable PATH!
echo(
if exist %SystemRoot%\System32\timeout.exe (echo Exiting...& %SystemRoot%\System32\timeout.exe 6 >nul) else pause
goto FINISHED
if exist *.wav goto ProcessVideo
cls
echo(
echo(
echo There is no audio to put with the video!
echo(
if exist %SystemRoot%\System32\timeout.exe (echo Exiting...& %SystemRoot%\System32\timeout.exe 6 >nul) else pause
goto FINISHED
:ProcessVideo
rem Get file name of (last) WAV file in current directory.
for %%I in (*.wav) do set "AudioFile=%%I"
rem Process all AVI, MKV, MP4 and WBEM video files in current directory.
set "NoVideo=1"
for /F "eol=| delims=" %%# in ('dir *.avi *.mkv *.mp4 *.webm /A-D /B /ON 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /E /L /V /C:"-new.mp4"') do ffmpeg.exe -i "%%#" -i "%AudioFile%" -c:v copy -map 0:v:0 -map 1:a:0 "%%~n#-NEW.mp4" & set "NoVideo="
if not defined NoVideo goto FINISHED
cls
echo(
echo(
echo There is no video to put audio with!
echo(
if exist %SystemRoot%\System32\timeout.exe (echo Exiting...& %SystemRoot%\System32\timeout.exe 6 >nul) else pause
:FINISHED
color
endlocal
命令FOR支持使用多个通配符搜索文件名,就像命令DIR一样。因此,无需为批处理文件支持的每种类型的视频文件格式使用几乎相同的代码。修改结果将处理当前目录中的所有视频文件,而不仅仅是最后一个视频文件,除非视频文件名以
-NEW
结尾,不区分大小写。
字符
a
是循环变量的修饰符。尽管如此,它仍然可以用作循环变量,但最好使用永远不会被解释为修饰符的字符作为循环变量。上面的批处理文件使用一次 I
和一次 #
作为循环变量来演示这一点。
start /wait
根本没有必要。默认情况下,Windows 命令处理器 cmd.exe
等待从批处理文件中启动的任何可执行文件自行终止,否则 timeout.exe
的执行将无法按预期进行。因此,无需使用命令 ffmpeg.exe
及其选项 start
即可运行 /wait
。
批处理文件末尾的命令
exit
始终没有用。对于批处理文件的开发人员来说,它使得“调试批处理文件”变得更加困难,并且它存在于批处理文件末尾且没有任何参数,这对于从命令提示符窗口中执行批处理文件的批处理文件用户来说会适得其反或者对于想要多次从另一个批处理文件调用该批处理文件的用户(例如循环调用)。
最好在批处理文件中指定具有完整限定文件名的 Windows Command,以使批处理文件尽可能独立于 PATH
和
PATHEXT
。然后,Windows 命令处理器不需要搜索可执行文件,即使用户以某种方式损坏了环境变量的值,批处理文件也可以正常工作PATH
。默认情况下,Windows XP 和旧版本的 Windows 上不存在可执行文件 timeout.exe
。因此,
IF条件用于在 Windows Vista 和较新版本的 Windows 上使用
timeout.exe
,或在旧版本的 Windows 上使用 pause
。要了解所使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完整、仔细地阅读每个命令显示的帮助页面。
cls /?
color /?
dir /?
echo /?
endlocal /?
findstr /?
for /?
goto /?
if /?
pause /?
rem /?
set /?
setlocal /?
timeout /?
title /?
where /?
使用命令重定向运算符
的 Microsoft 文档,了解 >nul
、
2>nul
和 |
的说明。重定向运算符 >
和 |
必须在 FOR命令行上使用脱字符号
^
进行转义,以便在 Windows 命令解释器在执行命令 FOR(执行嵌入的 )之前处理此命令行时将其解释为文字字符dir
命令行使用单独的命令进程在后台启动,并且 %ComSpec% /c
中的命令行作为附加参数附加。