Files

跨子目錄中的 .avi 文件的 ffmpeg

  • August 23, 2021

情況:

  • 執行 macOS 10.13.6 並使用 bash 5.0.17(1)
  • 許多包含多個文件的子目錄。
  • 需要過濾掉具有特定副檔名 (.avi) 的子目錄中的文件。
  • 需要處理所有 .avi 文件並使用 .mp4 重新混合到 .mp4 ffmpegffmpeg使用以下語法進行重新混合:ffmpeg -i in.avi -c copy out.mp4
  • 輸出格式:在與源 .avi 文件相同的文件夾中,並使用相同的文件名(除了 .avi 副檔名)

範例文件結構:

$ find . -maxdepth 2
.
./abc
./abc/abc.avi
./xyz
./xyz/xyz.avi.mp4
./123
./123/123.avi

在這種情況下,我想過濾掉文件./abc/abc.aviand ./123/123.avi,我可以使用正則表達式 and 來做到這一點find

$ find -E . -iregex ".*\.avi"
./abc/abc.avi
./123/123.avi

所需的 remuxed.mp4輸出文件名將是:

./abc/abc.mp4
./123/123.mp4

我怎樣才能:

  1. 使用腳本,用一個命令將所有這些.avi文件重新組合到.mp4容器中?我不確定如何將 的輸出通過管道find傳輸到 的輸入ffmpeg,同時指定所需的輸出文件名。
  2. 刪除原始.avi文件,但前提是 remux 成功?

感謝Cbhihe的回答,因為它讓我走上了正確的道路。由於基線在 mac 上的工作方式以及文件名中空格的處理,我需要更改一些內容。

macOSfind使用了一些特殊的語法。您可以使用以下單線:

find -E . -type f -iregex ".*\.avi" -execdir bash -c 'in=$1; out=${in%.*}.mp4; (ffmpeg -y -i "$in" -c copy "$out") 2>/dev/null && \rm "$in"' shellproc {} \;

  • find -E . -type f -iregex ".*\.avi"搜尋文件:

    • .表示搜尋目前目錄,
    • -E表示允許使用正則表達式的擴展查找,
    • -iregex ".*\.avi"搜尋此路徑中的所有 `.aviz 文件,包括子目錄。
  • -execdir bash -c '<COMMAND>' shellproc {} \;使用 bash shell 對每個搜尋結果執行命令,從與搜尋結果相同的目錄執行。文件名作為參數 $1 傳遞。

  • in=$1; out=${in%.*}.mp4; (ffmpeg -y -i "$in" -c copy "$out") 2>/dev/null && \rm "$in"定義輸入和輸出文件名,執行 ffmpeg 進行重新混合併抑制詳細的 ffmpeg 輸出,並且僅在重新混合成功完成時刪除輸入文件。

在 Linux 系統上,find語法略有不同:

find . -type f -regex ".*\.avi" -execdir bash -c 'in=$1; out=${in%.*}.mp4; (ffmpeg -y -i "$in" -c copy "$out") 2>/dev/null && \rm "$in"' shellproc {} \;

我不是 Arch Linux 的使用者,ffmpeg我正在從bashArch Linux 上的環境中編寫此答案,但您的兩個要求可以在 FreeBSD 和 MacOS-X 上得到滿足,例如:

$ from=avi; to=mp4; 
$ find -E . -type f -iregex ".*\.avi" -execdir \
 sh -c 'file=$(basename $3); (ffmpeg -i $file.$1 -c copy $file.$2) 2>/dev/null && \rm $3' shellproc "$from" "$to" {} \;

在上面的一個班輪中:

  • -type f-iregex .... stat它應該可以通過只使用“正常文件”類型的文件來節省您的時間。
  • $1代表$from
  • $2代表$to
  • $3代表{},即你的find命令的結果
  • shellprocin...shellproc "$from" "$to" {} \;只是一個任意標籤,用於標識使用以下命令執行的 shell 程序:sh -c 'file=$(basename $3); (ffmpeg -i $file.$1 -c copy $file.$2) 2>/dev/null && \rm $3'. 該標籤將作為所述外殼輸出的任何錯誤消息的前綴。這就是它的功能。

有幾種可能的方式來做你想做的事。我建議您看一下 Kusalananda 的答案,以了解(更多)關於find ... -exec...’s 語法的資訊。

引用自:https://unix.stackexchange.com/questions/584460