Вот два сценария PowerShell для разделения длинных видео на более мелкие главы черными сценами.
Сохраните их как Detect_black.ps1 и Cut_black.ps1. Загрузите ffmpeg для Windows и сообщите сценарию путь к файлу ffmpeg.exe и папке с видео в разделе параметров.
Оба сценария не затрагивают существующие видеофайлы, они остаются нетронутыми.
Тем не менее, вы получите несколько новых файлов в том же месте, где находятся ваши входные видео
- Файл журнала для каждого видео с выводом на консоль для обеих используемых команд ffmpeg
- Файл CSV для каждого видео со всеми временными метками черных сцен для ручной тонкой настройки
- Пара новых видео в зависимости от того, сколько черных сцен было обнаружено ранее
Первый скрипт для запуска: 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
}
Как это работает
Первый скрипт перебирает все видеофайлы, которые соответствуют указанному расширению и не соответствуют шаблону *_???.*
, так как были названы новые главы видео, <filename>_###.<ext>
и мы хотим исключить их.
Он ищет все черные сцены и записывает метку времени начала и длительность черной сцены в новый файл CSV с именем <video_name>_cutpoints.txt
Он также рассчитывает вырезать точки , как показано на рисунке: cutpoint = black_start + black_duration / 2
. Позже, видео становится сегментированным в эти временные метки.
Файл cutpoints.txt для вашего примера видео будет отображать:
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
После запуска вы можете при желании манипулировать точками среза вручную. Если вы снова запустите скрипт, весь старый контент будет перезаписан. Будьте осторожны при ручном редактировании и сохраняйте свою работу в другом месте.
Для примера видео команда ffmpeg для обнаружения черных сцен
$ffmpeg -i "Tape_10_3b.mp4" -vf blackdetect=d=4:pic_th=0.98:pix_th=0.15 -an -f null
В разделе опций скрипта есть 3 важных номера, которые можно редактировать.
d=4
означает, что обнаруживаются только черные сцены длительностью более 4 секунд
pic_th=0.98
пороговое значение для того, чтобы считать изображение «черным» (в процентах)
pix=0.15
устанавливает порог для рассмотрения пикселя как «черного» (по яркости). Поскольку у вас есть старые видео VHS, в ваших видео нет полностью черных сцен. Значение по умолчанию 10 не будет работать, и мне пришлось немного увеличить порог
Если что-то пойдет не так, проверьте соответствующий вызванный файл журнала <video_name>__ffmpeg.log
. Если следующие строки отсутствуют, увеличивайте числа, упомянутые выше, пока не обнаружите все черные сцены:
[blackdetect @ 0286ec80]
black_start:236.908 black_end:242.247 black_duration:5.33877
Второй скрипт для запуска: 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
}
Как это работает
Второй скрипт перебирает все видеофайлы так же, как первый скрипт. Он читает только вырезанные временные метки из соответствующего cutpoints.txt
видео.
Затем он собирает подходящее имя файла для файлов главы и говорит ffmpeg сегментировать видео. В настоящее время видео нарезано без перекодирования (сверхбыстрое и без потерь). Из-за этого может быть неточность 1-2 с с временными метками точки вырезания, потому что ffmpeg может вырезать только в key_frames. Так как мы просто копируем и не перекодируем, мы не можем вставить key_frames самостоятельно.
Команда для примера видео будет
$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"
Если что-то пойдет не так, взгляните на соответствующий файл ffmpeg.log
Ссылки
Делать
Спросите у OP, лучше ли формат CSV, чем текстовый файл, как файл с точками обрезки, чтобы вы могли редактировать их в Excel немного проще
»
Реализовать способ форматирования временных меток как [чч]: [мм]: [сс], [миллисекунды], а не только как секунды
». Реализовано
Реализуйте команду ffmpeg для создания png-файлов мозаики для каждой главы
»Реализовано
Уточните, если этого -c copy
достаточно для сценария ОП или нам нужно полностью перекодировать.
Похоже, Райан уже на нем .