Berikut adalah dua skrip PowerShell untuk membagi video panjang menjadi beberapa bab kecil dengan adegan hitam.
Simpan sebagai Detect_black.ps1 dan Cut_black.ps1. Unduh ffmpeg untuk Windows dan beri tahu skrip path ke ffmpeg.exe dan folder video Anda di bawah bagian opsi.
Kedua skrip tidak akan menyentuh file video yang ada, mereka tetap tidak tersentuh.
Namun, Anda akan mendapatkan beberapa file baru di tempat yang sama dengan video input Anda
- File log per video dengan output konsol untuk kedua perintah ffmpeg yang digunakan
- File CSV per video dengan semua cap waktu adegan hitam untuk fine tuning manual
- Beberapa video baru tergantung pada berapa banyak adegan hitam yang terdeteksi sebelumnya
Skrip pertama yang dijalankan: Detect_black.ps1
### Options __________________________________________________________________________________________________________
$ffmpeg = ".\ffmpeg.exe" # Set path to your ffmpeg.exe; Build Version: git-45581ed (2014-02-16)
$folder = ".\Videos\*" # Set path to your video folder; '\*' must be appended
$filter = @("*.mov","*.mp4") # Set which file extensions should be processed
$dur = 4 # Set the minimum detected black duration (in seconds)
$pic = 0.98 # Set the threshold for considering a picture as "black" (in percent)
$pix = 0.15 # Set the threshold for considering a pixel "black" (in luminance)
### Main Program ______________________________________________________________________________________________________
foreach ($video in dir $folder -include $filter -exclude "*_???.*" -r){
### Set path to logfile
$logfile = "$($video.FullName)_ffmpeg.log"
### analyse each video with ffmpeg and search for black scenes
& $ffmpeg -i $video -vf blackdetect=d=`"$dur`":pic_th=`"$pic`":pix_th=`"$pix`" -an -f null - 2> $logfile
### Use regex to extract timings from logfile
$report = @()
Select-String 'black_start:.*black_end:' $logfile | % {
$black = "" | Select start, end, cut
# extract start time of black scene
$start_s = $_.line -match '(?<=black_start:)\S*(?= black_end:)' | % {$matches[0]}
$start_ts = [timespan]::fromseconds($start_s)
$black.start = "{0:HH:mm:ss.fff}" -f ([datetime]$start_ts.Ticks)
# extract duration of black scene
$end_s = $_.line -match '(?<=black_end:)\S*(?= black_duration:)' | % {$matches[0]}
$end_ts = [timespan]::fromseconds($end_s)
$black.end = "{0:HH:mm:ss.fff}" -f ([datetime]$end_ts.Ticks)
# calculate cut point: black start time + black duration / 2
$cut_s = ([double]$start_s + [double]$end_s) / 2
$cut_ts = [timespan]::fromseconds($cut_s)
$black.cut = "{0:HH:mm:ss.fff}" -f ([datetime]$cut_ts.Ticks)
$report += $black
}
### Write start time, duration and the cut point for each black scene to a seperate CSV
$report | Export-Csv -path "$($video.FullName)_cutpoints.csv" –NoTypeInformation
}
bagaimana cara kerjanya
Skrip pertama beralih melalui semua file video yang cocok dengan ekstensi yang ditentukan dan tidak cocok dengan pola *_???.*
, karena bab video baru dinamai <filename>_###.<ext>
dan kami ingin mengecualikannya.
Itu mencari semua adegan hitam dan menulis timestamp mulai dan durasi adegan hitam ke file CSV baru bernama <video_name>_cutpoints.txt
Hal ini juga menghitung poin dipotong seperti yang ditunjukkan: cutpoint = black_start + black_duration / 2
. Nantinya, video akan tersegmentasi pada stempel waktu ini.
File cutpoints.txt untuk video contoh Anda akan menunjukkan:
start end cut
00:03:56.908 00:04:02.247 00:03:59.578
00:08:02.525 00:08:10.233 00:08:06.379
Setelah berlari, Anda dapat memanipulasi titik potong secara manual jika diinginkan. Jika Anda menjalankan skrip lagi, semua konten lama ditimpa. Hati-hati saat mengedit secara manual dan menyimpan pekerjaan Anda di tempat lain.
Untuk video contoh, perintah ffmpeg untuk mendeteksi adegan hitam adalah
$ffmpeg -i "Tape_10_3b.mp4" -vf blackdetect=d=4:pic_th=0.98:pix_th=0.15 -an -f null
Ada 3 angka penting yang dapat diedit di bagian opsi skrip
d=4
berarti hanya adegan hitam yang lebih panjang dari 4 detik yang terdeteksi
pic_th=0.98
adalah ambang batas untuk menganggap gambar sebagai "hitam" (dalam persen)
pix=0.15
menetapkan ambang untuk mempertimbangkan piksel sebagai "hitam" (dalam pencahayaan). Karena Anda memiliki video VHS lama, Anda tidak memiliki adegan yang sepenuhnya hitam di video Anda. Nilai default 10 tidak akan berfungsi dan saya harus meningkatkan ambang sedikit
Jika ada yang salah, periksa logfile terkait yang disebut <video_name>__ffmpeg.log
. Jika baris berikut tidak ada, tambah angka yang disebutkan di atas hingga Anda mendeteksi semua adegan hitam:
[blackdetect @ 0286ec80]
black_start:236.908 black_end:242.247 black_duration:5.33877
Skrip kedua untuk dijalankan: cut_black.ps1
### Options __________________________________________________________________________________________________________
$ffmpeg = ".\ffmpeg.exe" # Set path to your ffmpeg.exe; Build Version: git-45581ed (2014-02-16)
$folder = ".\Videos\*" # Set path to your video folder; '\*' must be appended
$filter = @("*.mov","*.mp4") # Set which file extensions should be processed
### Main Program ______________________________________________________________________________________________________
foreach ($video in dir $folder -include $filter -exclude "*_???.*" -r){
### Set path to logfile
$logfile = "$($video.FullName)_ffmpeg.log"
### Read in all cutpoints from *_cutpoints.csv; concat to string e.g "00:03:23.014,00:06:32.289,..."
$cuts = ( Import-Csv "$($video.FullName)_cutpoints.csv" | % {$_.cut} ) -join ","
### put together the correct new name, "%03d" is a generic number placeholder for ffmpeg
$output = $video.directory.Fullname + "\" + $video.basename + "_%03d" + $video.extension
### use ffmpeg to split current video in parts according to their cut points
& $ffmpeg -i $video -f segment -segment_times $cuts -c copy -map 0 $output 2> $logfile
}
bagaimana cara kerjanya
Skrip kedua akan mengulangi semua file video dengan cara yang sama dengan skrip pertama. Bunyinya di hanya dipotong cap waktu dari yang sesuai cutpoints.txt
dari video.
Selanjutnya, ia mengumpulkan nama file yang cocok untuk file bab dan memberitahu ffmpeg untuk membagi video. Saat ini video diiris tanpa re-encoding (supercepat dan tanpa kehilangan). Karena ini, mungkin ada 1-2s ketidaktepatan dengan stempel waktu titik potong karena ffmpeg hanya dapat memotong di key_frames. Karena kita hanya menyalin dan tidak menyandikan ulang, kita tidak bisa menyisipkan key_frames sendiri.
Perintah untuk video contoh adalah
$ffmpeg -i "Tape_10_3b.mp4" -f segment -segment_times "00:03:59.578,00:08:06.379" -c copy -map 0 "Tape_10_3b_(%03d).mp4"
Jika ada yang salah, lihat di ffmpeg.log yang sesuai
Referensi
Melakukan
Tanyakan OP apakah format CSV lebih baik daripada file teks sebagai file cut point, sehingga Anda dapat mengeditnya dengan Excel sedikit lebih mudah
»Diimplementasikan
Menerapkan cara untuk memformat stempel waktu sebagai [jj]: [mm]: [dd], [milidetik] daripada hanya beberapa detik
»Diimplementasikan
Menerapkan perintah ffmpeg untuk membuat file arsitektur png untuk setiap bab
»Diimplementasikan
Rumuskan apakah -c copy
cukup untuk skenario OP atau kita perlu menyandikan ulang sepenuhnya.
Sepertinya Ryan sudah di atasnya .