最近驚訝地發現,之前因為可以自動跟飛攝影,所以買的 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 的 「終端機 (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 資料夾中。"
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 指令 ========
沒有留言:
張貼留言