2

У меня много видеофайлов (flv/mp4), которые меняют разрешение среднего потока (720p/1080p/640).

Я хотел бы использовать что-то вроде ffmpeg для автоматического определения изменения разрешения и разделения видео на отдельные сцены, сохраняя качество кодирования: сегмент без перекодирования (Video1-scene1.flv, Video1-scene2.flv и т.д.),

Я нашел различные методы разделения на тишину, смену сцены, на черные сцены, но не так просто, как изменение ширины разрешения.

Эти файлы часто приводят к сбою видеоредакторов / триммеров, и ручная идентификация и удаление сцен с низким разрешением занимает очень много времени, если я просто конвертирую все видео в 1080p.

Алгоритм, вероятно, так же прост, как сравнение текущего кадра с предыдущим, и, если они имеют разное разрешение, разделите видео и начните новый сегмент.

Может кто-нибудь помочь, пожалуйста?

ПРИМЕР ФАЙЛА (temporarily available): Example.flv

Ниже приведены несколько связанных ответов:

Вырезать часть из видеофайла из начальной позиции в конечную позицию с помощью FFmpeg

https://stackoverflow.com/questions/36074224/how-to-split-video-or-audio-by-silent-parts

Автоматически разбивать большие видеофайлы .mov на меньшие файлы с черными рамками (смена сцены)?

Разделите видео с помощью FFMPEG с помощью функции обнаружения сцены

Дополнительные ресурсы:
Используя решение лорда Некберда, я присоединяю (к сожалению, очень ручной) процесс, который я в конечном итоге заставил работать на Windows10. Возможно, это может породить другие идеи вокруг ffmpeg.
(Я разместил отдельный вопрос для тех, кто достаточно ГУРУ, чтобы: автоматизировать этот процесс ...)

перетащите видео в пакетный файл, который содержит:

ffprobe -v ошибка -show_entries frame = pkt_pts_time, width, height -select_streams v -of csv = p = 0% 1> allkeyframes.txt

(образец allkeyframes.txt ...)

13.652000,640,480
13.755000,640,480
13.597000,480,360
13.652000,480,360

вставьте этот текст в POWERSHELL:

$o=""
$n=0
foreach($line in (Get-Content allkeyframes.txt)){
  $nline = $line.Split(",")
  $nline2=($nline[1]+$nline[2])
  if ($nline2 -ne $preventry) {
    $n0=$nline[0]
    $o="$o,$n0"
    $n=$n0
}
  $preventry = $nline2
}
if ($o.length -gt 1){
echo $o.Remove(0,1) > resolutionchanges.txt
} else {
Write-Host "No resolution changes found" -ForegroundColor Red
}

(Resolutionchanges.txt:)

13.597000,25.618000,33.628000,45.598000

введите следующее в командном окне, после вставки содержимого resolutionchanges.txt и изменения «input.flv» на имя видео (Win10 отклонил мои попытки пакетирования этого):

ffmpeg -i input.flv -map 0 -c copy -segment_times 13.597000,25.618000,33.628000,45.598000 -reset_timestamps 1 -f сегмент output_% 03d.flv

1 ответ1

0

Решение Lazyman состоит в том, чтобы использовать фильтр масштаба, чтобы согласовать каждый ввод с желаемой шириной x высотой.

Для предложенного вами решения вы можете использовать ffprobe чтобы определить, когда происходят изменения размера.

ffprobe -v error -show_entries frame=pkt_pts_time,width,height -select_streams v -of csv=p=0 input.flv

Пример выходной выдержки при изменении ширины и высоты (key_frame, pkt_pts_time, width, height):

0,89.081000,480,640
0,89.281000,480,640
0,89.481000,480,640
1,89.568000,640,480
0,89.592000,640,480
0,89.632000,640,480
1,97.749000,480,640

Изменения размера, скорее всего, будут происходить в ключевых кадрах, где вы можете делать сокращения, если требуется потоковое копирование. Если вы просто хотите, чтобы ключевые кадры добавили -skip_frame nokey .

Затем используйте сегментный мультиплексор:

ffmpeg -i input.flv -map 0 -c copy -segment_times 89.568,97.749 -reset_timestamps 1 -f segment output_%03d.flv

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .