尝试通过拖放到批处理文件来生成用于 ffmpeg 连接的列表文件

尝试通过拖放到批处理文件来生成用于 ffmpeg 连接的列表文件

是的,这个问题真的很简单,整个过程只有 3 个步骤:

1.通过拖放文件获取字母数字列表。

2.编辑文件列表以匹配以下语法/布局:

file 'filename1.mkv'
file 'filename2.mkv'
file 'filename3.mkv'

3.使用列表文件连接文件。

我无法弄清楚如何生成拖放到批处理文件中的文件列表。

我正在谷歌搜索,但也许我的搜索词使用了太多常用词,无论如何我还没有找到任何有用的东西。按字母顺序对列表进行排序可能也很困难,除非有人有更好的主意,否则我可能需要使用第三方工具。

编辑:有人发布了这个答案,但删除了他们的评论。这是一个很好的解决方案。此代码使用绝对路径,因此放置的文件可能来自任何地方。脚本输出到批处理文件所在的位置。路径和文件名中可以​​使用空格。

@echo off setlocal enabledelayedexpansion
echo. > "%~dp0Concat1.txt"
for %%A in (%*) do ( echo file '%%~A'>> "%~dp0Concat1.txt" )
sort < "%~dp0Concat1.txt" > "%~dp0Concat2.txt"
ffmpeg -f concat -safe 0 -i "%~dp0Concat2.txt" -c copy "%~dp0Output.mkv"
del /Q "%~dp0Concat1.txt" "%~dp0Concat2.txt"
pause

实际上,它不能正确地按字母顺序排列,但我认为其他人正在解决这个问题。考虑到我遇到的问题,这似乎更像是一个后续问题。我注意到由于与时间戳相关的错误,许多 DVD 文件无法正确组合。我找到了一种纠正这些错误的方法,但我需要先将它们复制到另一个文件,然后连接这些新文件。我的想法是,如果我能以某种方式省略创建的列表文件中的路径,而是在文件名前添加类似 %~dp0Output/ 的内容,表示可以使用 bat 文件目录中的 mkdir 创建的新输出文件夹。要连接的新文件和最终文件可以放在输出文件夹中,如果文件具有相同的名称并且省略了完整路径,则列表文件仍然有效,但会指向新文件,而不是旧文件。

好的,代码的第一部分已经准备好了:

@echo off setlocal enabledelayedexpansion
echo. > "%~dp0Concat1.txt"
for %%A in (%*) do ( echo file '%%~nxA'>> "%~dp0Concat1.txt" )

更新:这个新代码已接近完成,我只需对 Concat2.txt 执行字母数字排序并告诉脚本替换更多扩展类型。它应该能够连接视频和/或音频并将其输出到 Output.mkv 而无需重新编码。谢谢大家,你们都为这个难题提供了宝贵的线索。我的下一篇文章希望用完成的脚本来回答这个问题。

注意:我在这里找到了 vbscript 部分:https://stackoverflow.com/questions/60034/how-can-you-find-and-replace-text-in-a-file-using-the-windows-command-line-envir

mkdir "%~dp0Temp"

Echo Const ForReading = 1 > "%~dp0Temp\Replace.vbs"
Echo Const ForWriting = 2 >> "%~dp0Temp\Replace.vbs"
Echo strFileName = Wscript.Arguments(0) >> "%~dp0Temp\Replace.vbs"
Echo strOldText = Wscript.Arguments(1) >> "%~dp0Temp\Replace.vbs"
Echo strNewText = Wscript.Arguments(2) >> "%~dp0Temp\Replace.vbs"
Echo Set objFSO = CreateObject("Scripting.FileSystemObject") >> "%~dp0Temp\Replace.vbs"
Echo Set objFile = objFSO.OpenTextFile(strFileName, ForReading) >> "%~dp0Temp\Replace.vbs"
Echo strText = objFile.ReadAll >> "%~dp0Temp\Replace.vbs"
Echo objFile.Close >> "%~dp0Temp\Replace.vbs"
Echo strNewText = Replace(strText, strOldText, strNewText) >> "%~dp0Temp\Replace.vbs"
Echo Set objFile = objFSO.OpenTextFile(strFileName, ForWriting) >> "%~dp0Temp\Replace.vbs"
Echo objFile.Write strNewText  'WriteLine adds extra CR/LF >> "%~dp0Temp\Replace.vbs"
Echo objFile.Close >> "%~dp0Temp\Replace.vbs"
cscript //nologo "%~dp0Temp\Replace.vbs"

@echo off setlocal enabledelayedexpansion
echo. > "%~dp0Temp\Concat1.txt"
for %%i in (%*) do if not exist "%~dp0Temp\%%~ni.mkv" (
   ffmpeg -fflags +genpts -y -i "%%~i" -c copy -reset_timestamps 1 -video_track_timescale 90000 "%~dp0Temp\%%~ni.mkv"
)
for %%A in (%*) do ( echo file '%~dp0Temp\%%~nxA'>> "%~dp0Temp\Concat1.txt" )
sort < "%~dp0Temp\Concat1.txt" > "%~dp0Temp\Concat2.txt"

cscript "%~dp0Temp\Replace.vbs" "%~dp0Temp\Concat2.txt" ".VOB'" ".mkv'"

ffmpeg -fflags +genpts -f concat -safe 0 -i "%~dp0Temp\Concat2.txt" -c copy -reset_timestamps 1 -video_track_timescale 90000 "%~dp0Output.mkv"
del /Q "%~dp0Temp"
pause

答案1

如果文件名中没有空格,则不需要撇号(如果运行 Windows,我不建议在连接时使用带空格的名称)。文件列表还将与文件在其目录中出现的顺序相匹配。

您可以按如下所示合并两个代码,或将其分成两个单独的脚本。

(for %%i in (*.mkv) do @echo file %%i) > List.txt

ffmpeg -f concat -i List.txt -c copy output.mkv

如果需要,您可以del List.txt在末尾添加以丢弃创建的列表文件。

如果从与要连接的文件相同的目录运行,上述操作将会起作用。

相关内容