Вот два сценария 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
достаточно для сценария ОП или нам нужно полностью перекодировать.
Похоже, Райан уже на нем .
Вот бонус: этот третий скрипт PowerShell создает миниатюрное изображение мозаики
Вы получите одно изображение на каждую главу видео, которое выглядит как пример ниже.
Основная идея состоит в том, чтобы получить непрерывный поток изображений по всему видео. Мы делаем это с помощью опции выбора ffmpeg .
Сначала мы извлекаем общее количество кадров с помощью оригинального метода (например, 2000) и делим его на число миниатюр по умолчанию (например, 5 x 4 = 20). Поэтому мы хотим генерировать одно изображение каждые 100 кадров, так как
2000 / 20 = 100
Результирующая команда ffmpeg для создания миниатюры может выглядеть так
В приведенном выше коде вы видите 9 различных
-vf
комбинаций, состоящих изselect=not(mod(n\,XXX))
где XXX - расчетная частота кадровthumbnail
который выбирает наиболее представительные кадры автоматическиselect='gt(scene\,XXX)
+-vsync vfr
где XXX - это порог, с которым вы должны игратьmpdecimate
- Удалить почти дублированные кадры. Хорошо против черных сценyadif
- Деинтерлейсировать входное изображение. Не знаю почему, но это работаетВерсия 3 - лучший выбор на мой взгляд. Все остальные закомментированы, но вы все еще можете попробовать их. Я был в состоянии удалить большую часть размытых миниатюр с помощью
mpdecimate
,yadif
иselect=not(mod(n\,XXX))
. Да!Для вашего примера видео я получаю эти превью
нажмите, чтобы увеличить
нажмите, чтобы увеличить
Я загрузил все эскизы, созданные этими версиями. Посмотрите на них для полного сравнения.
источник
select='gt(scene\,0.4)'
до работы. И я тоже не смог добратьсяfps="fps=1/600"
до работы. Кстати, у вас есть идеи о superuser.com/questions/725734 ? Большое спасибо за вашу помощь. Я очень рад помочь моей семье обнаружить тонны старых воспоминаний.Оцените оба сценария, отличный способ разделить видео.
Тем не менее, у меня были некоторые проблемы с видео, которые не показывают правильное время после этого, и я не мог перейти к определенному времени. Одним из решений было демультиплексирование, а затем мультиплексирование потоков с помощью Mp4Box.
Другой, более простой способ для меня - использовать mkvmerge для разбиения. Поэтому оба сценария должны были быть изменены. Для Detect_black.ps1 к опции фильтра нужно было добавить только «* .mkv», но это не обязательно, если вы начинаете только с файлами mp4.
Функция та же, но проблем с видео пока нет. Спасибо за вдохновение.
источник
Я надеюсь, что ошибаюсь, но я не думаю, что ваш вопрос возможен. Это может быть возможно при перекодировании видео, но как «простой фрагмент без потерь» я не знаю ни одного способа.
Многие программы редактирования видео будут иметь функцию автоматического анализа или что-то подобное, что может разделить ваши видео на черные рамки, но это потребует перекодирования видео.
Удачи!
источник