有没有一种方法可以使用ffmpeg按章批量拆分文件,然后在Windows中使用mkvmerge重新组装?

问题描述

因此,我最初制作了一个批处理脚本,能够相对精确地将视频修剪成章节,而不必通过关键帧运行,但是代码看起来很恐怖,我无法使其遍历所有mp4文件,也无法获取mkvmerge分割文件后追加文件。代码在下面,但请谨慎,这是我的第一次尝试。

@echo off
setlocal enableDelayedExpansion

REM CODE BELOW CREATES JSON FILES FOR ALL MP4 FILES WITHIN THE SAME DIRECTORY
ffprobe -v quiet -print_format json -show_chapters -loglevel error "01x01.mp4" > "01x01.json"

REM CODE BELOW SETS VARIABLES FROM EACH SPECIFIC JSON
FOR /F "delims=" %%i in ('jq .chapters[2].start ^< 01x01.json') DO SET /A start1=%%i
FOR /F "delims=" %%j in ('jq .chapters[2].end ^< 01x01.json') DO SET /A end1=%%j

FOR /F "delims=" %%k in ('jq .chapters[4].start ^< 01x01.json') DO SET /A start2=%%k
FOR /F "delims=" %%l in ('jq .chapters[4].end ^< 01x01.json') DO SET /A end2=%%l

FOR /F "delims=" %%m in ('jq .chapters[6].start ^< 01x01.json') DO SET /A start3=%%m
FOR /F "delims=" %%n in ('jq .chapters[6].end ^< 01x01.json') DO SET /A end3=%%n

FOR /F "delims=" %%o in ('jq .chapters[8].start ^< 01x01.json') DO SET /A start4=%%o
FOR /F "delims=" %%p in ('jq .chapters[8].end ^< 01x01.json') DO SET /A end4=%%p

REM SETS THE DURATION OF EACH FILE TO USE PRECISION TIMING FOR START AND STOP TIMES
CALL vbs (%end1%-%start1%)/1000
SET duration1=%val%
CALL vbs (%end2%-%start2%)/1000
SET duration2=%val%
CALL vbs (%end3%-%start3%)/1000
SET duration3=%val%
CALL vbs (%end4%-%start4%)/1000
SET duration4=%val%

REM SETS THE START TIME IN SECONDS VS MILLISECONDS
CALL vbs (%start1%)/1000
SET start1=%val%
CALL vbs (%start2%)/1000
SET start2=%val%
CALL vbs (%start3%)/1000
SET start3=%val%
CALL vbs (%start4%)/1000
SET start4=%val%

REM TRIM AND SPLIT ORIGINAL FILE INTO SEPERATE SECTIONS BASED ON CHAPTER MARKERS
ffmpeg -ss %START1% -i 01x01.mp4 -ss 0 -c copy -to %DURATION1% -avoid_negative_ts make_zero 01x01-1.mp4
ffmpeg -ss %START2% -i 01x01.mp4 -ss 0 -c copy -to %DURATION2% -avoid_negative_ts make_zero 01x01-2.mp4
ffmpeg -ss %START3% -i 01x01.mp4 -ss 0 -c copy -to %DURATION3% -avoid_negative_ts make_zero 01x01-3.mp4
ffmpeg -ss %START4% -i 01x01.mp4 -ss 0 -c copy -to %DURATION4% -avoid_negative_ts make_zero 01x01-4.mp4

REM DELETES UNNEEDED JSON AFTER USE
del /s *.json

REM APPEND ALL MP4 FILES INTO COHESIVE MKV
for /d /r %%D in (*) do (
    pushd %%D
    set files=
    for %%F in (*.mp4) do set files=!files! + ^( "%%F" ^)
    if not "!files!"=="" %mkvmerge% -o "01x01-FINAL.mkv" !files:~2!
    popd
)

REM DELETE UNNEEDED MP4 ORIGINALS AND SPLIT FILES
del /s *.mp4

我知道它很长,每次尝试使用变量或循环遍历所有文件时,它都无法读取json文件。我整天待在这里,可以按原样使用脚本,但是每次迭代都必须创建一个文件。

我也希望能够只将标有“视频”的章节拉出来,但我还没有完全弄清这一点。

如果有帮助,我将为算术部分以及示例json添加vbs批处理文件。

@echo off
>"%temp%\VBS.vbs" echo Set fso = CreateObject("Scripting.FileSystemObject") : Wscript.echo (%*)
for /f "delims=" %%a in ('cscript /nologo "%temp%\VBS.vbs"') do set "val=%%a"
del "%temp%\VBS.vbs"
{
    "chapters": [
        {
            "id": 0,"time_base": "1/1000","start": 0,"start_time": "0.000000","end": 5590,"end_time": "5.590000","tags": {
                "title": "Video"
            }
        },{
            "id": 1,"start": 5590,"start_time": "5.590000","end": 13994,"end_time": "13.994000","tags": {
                "title": "Advertisement"
            }
        },{
            "id": 2,"start": 13994,"start_time": "13.994000","end": 163964,"end_time": "163.964000",{
            "id": 3,"start": 163964,"start_time": "163.964000","end": 195940,"end_time": "195.940000",{
            "id": 4,"start": 195940,"start_time": "195.940000","end": 547849,"end_time": "547.849000",{
            "id": 5,"start": 547849,"start_time": "547.849000","end": 595850,"end_time": "595.850000",{
            "id": 6,"start": 595850,"start_time": "595.850000","end": 1413588,"end_time": "1413.588000",{
            "id": 7,"start": 1413588,"start_time": "1413.588000","end": 1477569,"end_time": "1477.569000",{
            "id": 8,"start": 1477569,"start_time": "1477.569000","end": 1529696,"end_time": "1529.696000","tags": {
                "title": "Video"
            }
        }
    ]
}

我也尝试使用start_time,所以我不必进行额外的计算,但是jq也不喜欢。

当我在其中放置mkvmerge时,它甚至都没有尝试运行,而且一旦它全部变成一个文件,我仍然需要将其结尾减少7秒,将其前面减少12秒。

任何帮助将不胜感激,我知道这很多,但是我似乎已经遇到了障碍,或者只是睡眠不足。

更新

这很棒,我只需要弄清楚如何使用带空格的文件就可以了。我想我可以先运行下一批,然后用下划线替换所有空格。那可能会起作用,但是如果可以的话,我不想更改文件名。

@echo off

for %%i in (*.mp4) do (
FOR /F "delims=" %%A IN ('ffprobe -v quiet -print_format json -show_chapters -loglevel error "%%i" ^| xidel - -se "$json/(chapters)()[id!=0 and tags/title='Video']/concat('ffmpeg -ss ',start div 1000,' -i %%i -to ',((end - start) div 1000),' -c copy -avoid_negative_ts make_zero %%~ni-',position(),'.mp4')"') DO %%A
FOR /F "delims=" %%A IN ('xidel -s --xquery "concat('mkvmerge -o &quot;%%~ni-FINAL.mkv&quot; &quot;',join(file:list(.,false(),'%%~ni-*.mp4'),'&quot; + &quot;'),'&quot;')"') DO %%A
)

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)