批次檔以遞歸方式混合不同資料夾中的 .mp4 和 .srt

批次檔以遞歸方式混合不同資料夾中的 .mp4 和 .srt

種子下載中有一種新趨勢,即以 x265 .mp4 形式發布電視和電影,並在單獨的資料夾中包含 .srt 子文件,遵循以下資料夾結構:

Season1\title1.mp4
Season1\title2.mp4
Season1\title3.mp4
Season1\Subs\title1\subfile1.srt
Season1\Subs\title1\[subfile2.srt]
Season1\Subs\title1\[subfile3.srt]
Season1\Subs\title2\subfile1.srt
Season1\Subs\title2\[subfile2.srt]
Season1\Subs\title2\[subfile3.srt]
Season1\Subs\title3\subfile1.srt
Season1\Subs\title3\[subfile2.srt]
Season1\Subs\title3\[subfile3.srt]

我的目標是將每個 .mp4 混合到其 subs 資料夾中的第一個 .srt 。我可以使用 MKVToolNix GUI 一次執行一個操作,但我一直在尋找一種更簡單/更快的方法來使用批次檔(或 PowerShell 腳本)執行此操作。以下兩個解決方案很接近:

批量合併/複用 MP4 和 SRT 檔案到 MKV

大量合併/重複使用 .srt 與 .mkv 文件

不過,只有當 .mp4 和 .srt 位於同一資料夾中且標題適當時,它們才有效。我的問題,也是許多其他人也必須處理的問題,是在新的發布標準下:

  • .mp4 和 .srt 位於不同的資料夾。
  • 每個 .mp4 可能有一個或多個 .srt 檔案。如果是這種情況,可以安全地假設我想要第一個 .srt 文件,該文件通常是預設的英文字幕。
  • .srt 文件不遵循第一個文件的標題始終相同的命名約定。換句話說,批次檔必須使用第一個 .srt,無論其名稱為何。

這部2018年的劇本來自蘇傑·帕德克,是一個好的開始。

for %%f in (*.mkv) do (
    echo %%~nf
    'C:\Program Files\MKVToolNix\mkvmerge.exe' -o "%%~nf_New.mkv" "%%~nf.mkv" --language 0:eng "%%~nf.srt"
    move /Y "%%~nf_New.mkv"  "%%~nf.mkv"

只要所有檔案(.mp4 和 .srt)位於同一資料夾中且標題正確,它就會遞歸地工作。不過,我正在尋找的是一個不涉及重命名或移動文件的批次檔。它將使用 mkvmerge.exe 將每個 .mp4 混合到其子資料夾中的第一個 .srt,並將每個新的 .mkv 儲存到與 .mp4 相同的資料夾中。

(可選)因為我可以弄清楚,Mkvmerge.exe 應該將 .srt 設為英語語言強制使用 DefaultTrack 標誌

它適用於一個季節中的所有 .mp4 檔案。除非你感覺很勤奮,否則不需要每個季節都工作。然後,我將從每個季節的 .mp4 檔案所在的相同資料夾中運行每個季節的批次檔。

抱歉這麼長的解釋,但這確實超出了我的能力範圍,我需要你的幫助。我很感激任何建議。

答案1

@echo off 

setlocal && cd /d "%~dp0"
set "_mkv=C:\Program Files\MKVToolNix\mkvmerge.exe"
set "_flag_0=--default-language en --language 0:en"
set "_flag_1=--priority higher --flush-on-close --disable-track-statistics-tags -o"

for /f usebackq^delims^= %%G in (`dir /a:d /b ^|findstr Season.*[0-9] ^|find/v /i "\subs\"
   `)do if exist "%%G\*.mp4" for /f usebackq^delims^= %%i in (`2^>nul where "%%~G:*.mp4"
        `)do call %:^) "%%~G" "%%~ni" "%%~i" "%_mkv%" "%_flag_0%" "%_flag_1%" "*.srt"

%:^)
if "%~1" == "" (endlocal & goto :eof)else for /f ^usebackq^delims^= %%# in (`2^>nul ^
     where "%~1\Subs\%~2:%~7"`)do "%~4" %~6 "%~dpn3.mkv" "%~3" %~5 "%%~f#" & exit /b
     

1.將此bat儲存在base / root(SeasonX\資料夾上方1級:

2.使用for /f循環獲取每個資料夾的完整路徑SeasonX\

3.如果該資料夾中有一個any/more.mp4,那麼這次也要取得它們的路徑

4.儲存您需要的 mkv/flags以及 mkv 可執行檔的完整路徑,並在函數內使用 ( :label)

5.當找到第一個 subtitle\file.srt 時,呼叫一個已經包含要在其中使用的參數的函數來處理 mp4,並立即退出該函數。


觀察:1。Findstr過濾子資料夾並允許其在與您的資料夾名稱佈局相符的所有子資料夾上運行,在一些選項下方可檢查哪一個最適合您的場景

dir /a:d /b | findstr /ei Season.[0-9]       |find/v /i "\subs\"
dir /a:d /b | findstr /ei Season.*[0-9]      |find/v /i "\subs\"
dir /a:d /b | findstr /ei Season[0-9][0-9]   |find/v /i "\subs\"
dir /a:d /b | findstr /ei Season.[0-9][0-9]  |find/v /i "\subs\"
dir /a:d /b | findstr /ei Season.*[0-9][0-9] |find/v /i "\subs\"

觀測值:2。在bat中呼叫函數時,有必要傳遞變數/字串(在參數中),以便可以使用它們:

::  call :label/function and passing all arguments
:: 
::  call %:^) "%%~G" "%%~ni" "%%~i" "%_mkv%" "%_flag_0%" "%_flag_1%" "* .srt"
::  call %:ˆ) "Season1" "title1" "C:\Users\Answer42\Videos\SU-2022\Season1\title1.mp4" "C:\Program Files\MKVToolNix\mkvmerge.exe" "--default-language en --language 0:en" "--priority higher --flush-on-close --disable-track-statistics-tags -o" "*.srt"
:: 
:: ------------------------------------------------------------------------------- ::
::
:: %1  ==      "%%~G" == folder where .mp4 files are
:: %2  ==     "%%~ni" == the name without extension for the current mp4
:: %3  ==      "%%~i" == the full path to the current mp4 file
:: %4  ==    "%_mkv%" == the full path to the mkvmerge executable
:: %5  == "%_flag_0%" == mkv flag for process the first subtitle :: input in loop
:: %6  == "%_flag_1%" == mkv flag to process and output file
:: %7  ==     "*.srt" == subtitle extension
:: 
:: ------------------------------------------------------------------------------- ::

觀測值:3。循環內的命令for /f(函數/標籤內)以及使用參數在 for 迴圈中獲得的結果:

for /f ... (`where "%~1\Subs\%~2:%~7"`)do...
for /f ... (`where "C:\Users\Answer42\Videos\SU-2022\Season1\Subs\title1:*.str`)do...

...)do "%~4" %~6 "%~dpn3.mkv" "%~3" %~5 "%%~f#"
...)do "C:\Program Files\MKVToolNix\mkvmerge.exe" --priority higher --flush-on-close --disable-track-statistics-tags -o "C:\Users\Answer42\Videos\SU-2022\Season1\title1.mkv" "C:\Users\Answer42\Videos\SU-2022\Season1\title1.mp4" --default-language en --language 0:en "C:\Users\Answer42\Videos\SU-2022\Season1\Subs\title1\subfile1.srt"


我的目標是將每個 .mp4 混合到其 subs 資料夾中的第一個 .srt ...

使用此程式碼最棘手的部分是調整返回正確字幕的命令...

  • 請理解,我們不知道如何使輸出符合目標,我們甚至沒有看到文件、文件名、創建/更改日期甚至其內容。

  • 因此,很難定義什麼使您有資格成為第一個(或 english.str),因此您將進入此部分進行調整(如有必要),將函數中的當前命令替換為以下可能的命令之一:

%:^)
if "%~1" == "" (endlocal & goto :eof)else for /f ^usebackq^delims^= %%# in (`2^&>nul ^
     where "%~1\Subs\%~2:%~7"`)do "%~4" %~6 "%~dpn3.mkv" "%~3" %~5 "%%~f#" & exit /b

:: Possible adjustments/replacement/in command:
     where "%~1\Subs\%~2:%~7"`)do...

     where "%~1\Subs\%~2:%~7"^|sort`)do...
     where "%~1\Subs\%~2:%~7"^|sort /r`)do...

     dir /b /a:-d /on /s "%~1\Subs\%~2\%~7"`)do...
     dir /b /a:-d /o-n /s "%~1\Subs\%~2\%~7"`)do...

     dir /b /a:-d /od /tc /s "%~1\Subs\%~2\%~7"`)do...
     dir /b /a:-d /o-d /tc /s "%~1\Subs\%~2\%~7"`)do...

     dir /b /a:-d /on /s "%~1\Subs\%~2\%~7" ˆ|sort /r`)do...
     dir /b /a:-d /o-n /s "%~1\Subs\%~2\%~7" ˆ|sort /r`)do...

     dir /b /a:-d /od /tc /s "%~1\Subs\%~2\%~7" ^|sort`)do...
     dir /b /a:-d /o-d /tc /s "%~1\Subs\%~2\%~7" ^|sort /r`)do...

相關內容