2026年10月12日 星期一

以 ffmpeg 做 DJI Neo 空拍機 錄影檔影音合併整理 再以 LosslessCut 做編輯

最近驚訝地發現,之前因為可以自動跟飛攝影,所以買的 DJI Neo Mini Drone ,竟然從拿到試飛熟悉功能,到錄最後一個檔案,總共編號才100,全部都發生在11天之內的其中6天,然後就這樣放了2年多,影片也是最近才複製出來整理,實在是太浪費了。


因為可以手勢及遙控器操作,並不一直連接手機,這些 mp4 影片許多是沒有聲音的,有的那些則是透過手機App遙控,從手機收音即時降噪另外存成同名的 m4a 格式音檔,大多是 34kbps mono 15.63fps 單軌音訊幀率。我以常用的 LosslessCut 試著接起這些零碎影片,因為軟體設計成以清單第一個檔案的格式與軌道數合併,很大機會造成有聲音的影片,聲音軌道被放棄不合併。要逐一檢查這百個檔案實在耗時不合理,只好全部先批次整理過再作後續剪貼接合,這邊的方案是用 LosslessCut 的底層工具 ffmpeg,試錯了幾次成功保留 EXIF 資訊後,最終以下述指令做編輯準備。

前置作業:按 Win+Pause/Break 打開系統資訊,找到進階系統設定,按環境變數,在系統變數中找到Path後按編輯,然後新增,再來貼上 ffmpeg 資料夾的完整路徑。

使用方式:打開存放 DJI Neo 影片(MP4)與音檔(M4A)的資料夾,在視窗空白處,按住鍵盤的 Shift 鍵不放,同時點擊滑鼠右鍵,選擇「在此處開啟 PowerShell 視窗」(或「在此處開啟終端機」)。完整複製下方這一整段指令,貼進視窗中,然後按下 Enter。

======== 以下為 PowerShell 指令 ========
# 1. 建立存放預處理影片的全新資料夾
New-Item -ItemType Directory -Force -Path ".\ready_for_losslesscut" | Out-Null

# 2. 開始批量比對處理(加入 EXIF 複製與檔案時間戳同步)
Get-ChildItem *.mp4 | ForEach-Object {
    $baseName = $_.BaseName
    $m4aFile = ".\$baseName.m4a"
    $outFile = ".\ready_for_losslesscut\$($_.Name)"

    if (Test-Path $m4aFile) {
        # 情境 A:找到同名 m4a,複製原檔所有 EXIF 詮釋資料 (-map_metadata 0)
        ffmpeg -y -i $_.Name -i $m4aFile -c:v copy -c:a copy -map_metadata 0 $outFile 2>$null
    } else {
        # 情境 B:沒有同名 m4a,補上空白音軌並複製原檔所有 EXIF 詮釋資料
        ffmpeg -y -i $_.Name -f lavfi -i anullsrc=channel_layout=mono:sample_rate=16000 -c:v copy -c:a aac -b:a 34k -shortest -map_metadata 0 $outFile 2>$null
    }

    # 3. 如果成功生成新檔案,強行將原始檔案的時間戳(建立、修改、存取時間)複製過去
    if (Test-Path $outFile) {
        $origFile = $_.FullName
        $newFileObj = Get-Item $outFile
       
        $newFileObj.CreationTime = $_.CreationTime
        $newFileObj.LastWriteTime = $_.LastWriteTime
        $newFileObj.LastAccessTime = $_.LastAccessTime
    }
}
Write-Host "處理完成!所有檔案已完整保留原始 EXIF 與時間戳,並生成在 ready_for_losslesscut 資料夾中。" -ForegroundColor Green 
======== 以上為 PowerShell 指令 ========


雖然最近也有使用蘋果電腦,但是不喜歡 MacOS 時不時在磁碟留下隱形垃圾,所以整理照片影片,我還是回歸使用微軟PC。不過為預防萬一,還是叫 Gemini 生成了 Mac 版指令,沒實際搬檔案去試過,但應該差不多是這樣了。

在 Mac 上操作邏輯一樣,但需要將 Windows 的 PowerShell 語法換成 Mac 的 Zsh/Bash 終端機(Terminal)語法。在 Mac 系統中,我們同樣使用 -map_metadata 0 複製內部 EXIF 標籤,並利用 Mac 內建的 touch -r 指令,將原始檔案的外部修改與存取時間「複製」到新檔案上。

touch -r "$f" "$out_file":這是 Mac/Linux 系統的核心指令。它的意思是「以原始檔案 f 為基準(reference),將其建立與修改時間戳同步寫入新檔案(out_file)中」。

前置作業:要在 Mac 上也安裝好 FFmpeg(例如透過 Homebrew),此腳本便能執行。

操作步驟:打開 Mac 的 「終端機 (Terminal)」 應用程式,輸入 cd (注意 cd 後面有一個空格),然後將存放 DJI 影片與 M4A 音檔的資料夾,用滑鼠直接拖曳進終端機視窗中,再按下 Enter 切換路徑。最後完整複製下方整段指令,貼進終端機中,並按下 Enter 執行。

======== 以下為 Bash 指令 ========
# 1. 建立存放預處理影片的全新資料夾
mkdir -p ./ready_for_losslesscut

# 2. 開始批量比對處理(Zsh/Bash 語法)
for f in *.mp4; do
    # 取得不含副檔名的主檔名
    base="${f%.*}"
    m4a_file="./${base}.m4a"
    out_file="./ready_for_losslesscut/${f}"

    if [ -f "$m4a_file" ]; then
        # 情境 A:找到同名 m4a,直接進行無損影音封裝,並複製內部 EXIF (-map_metadata 0)
        ffmpeg -y -i "$f" -i "$m4a_file" -c:v copy -c:a copy -map_metadata 0 "$out_file" 2>/dev/null
    else
        # 情境 B:沒有同名 m4a,無損補上 34k Mono 空白音軌,並複製內部 EXIF
        ffmpeg -y -i "$f" -f lavfi -i anullsrc=channel_layout=mono:sample_rate=16000 -c:v copy -c:a aac -b:a 34k -shortest -map_metadata 0 "$out_file" 2>/dev/null
    fi

    # 3. 如果成功生成新檔案,使用 Mac 內建的 touch 指令,將原檔(f)的時間戳完美複製給新檔(out_file)
    if [ -f "$out_file" ]; then
        touch -r "$f" "$out_file"
    fi
done

echo "處理完成!所有檔案已完整保留原始 EXIF 與時間戳,並生成在 ready_for_losslesscut 資料夾中。"
======== 以上為 Bash 指令 ========

沒有留言:

張貼留言