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 .
Inilah bonusnya: Skrip PowerShell ke-3 ini menghasilkan gambar thumbnail mosaik
Anda akan menerima satu gambar per bab video yang semuanya terlihat seperti contoh di bawah ini.
Gagasan utamanya adalah mendapatkan aliran gambar yang berkelanjutan melalui video yang lengkap. Kami melakukan ini dengan opsi pilih ffmpeg .
Pertama, kami mengambil jumlah frame total dengan metode cerdik (misalnya 2000) dan membaginya melalui jumlah thumbnail standar kami (misalnya 5 x 4 = 20). Jadi kami ingin menghasilkan satu gambar setiap 100 frame sejak itu
2000 / 20 = 100
Perintah ffmpeg yang dihasilkan untuk menghasilkan thumbnail bisa terlihat seperti
Dalam kode di atas, Anda melihat 9
-vf
kombinasi berbeda yang terdiri dariselect=not(mod(n\,XXX))
di mana XXX adalah framerate yang dihitungthumbnail
yang memilih frame paling representatif secara otomatisselect='gt(scene\,XXX)
+ di-vsync vfr
mana XXX adalah ambang yang harus Anda mainkanmpdecimate
- Hapus frame duplikat dekat. Bagus terhadap adegan hitamyadif
- Deinterlace gambar input. Tidak tahu mengapa, tetapi itu berhasilVersi 3 adalah pilihan terbaik menurut saya. Semua yang lain dikomentari, tetapi Anda masih bisa mencobanya. Saya dapat menghapus sebagian besar thumbnail yang buram menggunakan
mpdecimate
,yadif
danselect=not(mod(n\,XXX))
. Ya!Untuk video contoh Anda, saya mendapatkan pratinjau ini
klik untuk memperbesar
klik untuk memperbesar
Saya mengunggah semua thumbnail yang dibuat oleh versi-versi itu. Lihatlah mereka untuk perbandingan lengkap.
sumber
select='gt(scene\,0.4)'
untuk bekerja. Dan saya juga tidak bisa mulaifps="fps=1/600"
bekerja. Omong-omong, apakah Anda punya ide tentang superuser.com/questions/725734 ? Terima kasih banyak untuk semua bantuan Anda. Saya sangat senang membantu keluarga saya menemukan banyak kenangan lama.Hargai kedua skrip, cara terbaik untuk membagi video.
Namun, saya memiliki beberapa masalah dengan video yang tidak menunjukkan waktu yang tepat sesudahnya dan saya tidak dapat melompat ke waktu tertentu. Salah satu solusinya adalah dengan demux dan kemudian mux stream menggunakan Mp4Box.
Cara lain yang lebih mudah bagi saya adalah menggunakan mkvmerge untuk membelah. Oleh karena itu, kedua skrip harus diubah. Untuk detect_black.ps1, hanya "* .mkv" yang harus ditambahkan ke opsi filter, tetapi itu tidak harus jika Anda mulai hanya dengan file mp4.
Fungsinya sama, tetapi tidak ada masalah dengan waktu video sejauh ini. Terima kasih atas inspirasinya.
sumber
Saya harap saya salah, tetapi saya tidak berpikir apa yang Anda minta itu mungkin. Mungkin dimungkinkan saat melakukan encoding ulang video, tetapi sebagai "irisan lossless sederhana" saya tidak tahu cara apa pun.
Banyak program pengeditan video akan memiliki fitur analisis otomatis atau sesuatu yang setara yang mungkin dapat membagi video Anda pada bingkai hitam, tetapi ini akan memerlukan pengodean ulang video.
Semoga berhasil!
sumber