Обнаружение сцены и concat делают мое видео длиннее (FFMPEG) - PullRequest
1 голос
/ 29 марта 2019

Я кодирую видео по сценам.На данный момент я получил два решения для этого.Первый использует приложение Python , которое дает мне список кадров, которые представляют сцены.Вот так:

285
378
553
1145
...

Первая сцена начинается с кадра с 1 по 285, вторая с 285 до 378 и так далее.Итак, я сделал скрипт bash, который кодирует все эти сцены.По сути, он берет текущий и предыдущий кадры, затем конвертирует их во время и, наконец, запускает команду ffmpeg:

begin=$(awk 'BEGIN{ print "'$previous'"/"'24'" }') 
end=$(awk 'BEGIN{ print "'$current'"/"'24'" }') 
time=$(awk 'BEGIN{ print "'$end'"-"'$begin'" }') 

ffmpeg -i $video -r 24 -c:v libx265  -f mp4 -c:a aac -strict experimental -b:v 1.5M -ss $begin -t $time "output$count.mp4" -nostdin

Это прекрасно работает.Второй метод использует сам ffmpeg.Я запускаю эти команды и выдает список раз .Вот так:

15.75
23.0417
56.0833
71.2917
...

Снова я создал скрипт bash, который кодирует все это время.В этом случае мне не нужно конвертировать во времена, потому что то, что я получил, - это времена:

time=$(awk 'BEGIN{ print "'$current'"-"'$previous'" }') 
ffmpeg -i $video -r 24 -c:v libx265  -f mp4 -c:a aac -strict experimental -b:v 1.5M -ss $previous -t $time "output$count.mp4" -nostdin

После всего этого объясненного возникает проблема.Как только все сцены закодированы, мне нужно их объединить, и для этого я создаю список с именами видео, а затем запускаю команду ffmpeg.

list.txt

file 'output1.mp4'
file 'output2.mp4'
file 'output3.mp4'
file 'output4.mp4'

команда:

ffmpeg -f concat -i list.txt -c copy big_buck_bunny.mp4

Проблема заключается в том, что «конкататное» видео длиннее исходного на 2,11 секунды.Оригинальный длится 596,45 секунд, а закодированный длится 598,56.Я добавил все продолжительность видео и я получил 598,56.Итак, я думаю, что проблема в процессе кодирования.Оба видео имеют одинаковый номер кадра.Моя цель - получить метрики о процессе кодирования. Когда я запускаю VQMT, чтобы получить PSNR и SSIM, я получаю странные результаты, я думаю, что для этой проблемы.

Кстати, я использую видео big_buck_bunny.

Ответы [ 2 ]

1 голос
/ 10 апреля 2019

Вероятная разница связана с кодеком copy. В последнем случае вы указываете ffmpeg скопировать сегменты, но он не может сделать это в зависимости от вашего времени ввода. Сначала он должен найти предыдущие I-кадры (кадр, который может быть декодирован без какой-либо ссылки на какой-либо предыдущий кадр) и начинается отсюда.

Чтобы получить то, что вам нужно, вам нужно либо перекодировать видео (как вы делали в 2 предыдущих примерах), либо изменить время, чтобы остановиться на I кадрах.

Чтобы подтвердить, что я правильно понял вашу проблему:

  1. У вас есть исходное видео (оно кодируется с переменной частотой кадров, близкой к 18fps)
  2. Вы хотите разделить исходное видео с помощью ffmpeg, увеличив частоту кадров до 24 кадров в секунду.
  3. Затем вы хотите объединить каждый сегмент.

Я думаю, что проблема в основном в том, что у вас есть некоторое расхождение во времени (если я разделю индекс кадра на время, которое вы дали, я получу от 16 до 18 кадров в секунду). Когда вы конвертируете их на шаге 2, время вывода видео будет 24 кадра в секунду. ffmpeg не выполняет повторную выборку по оси времени, поэтому, если вы установите скорость видео, видео будет ускоряться или замедляться. Существует также проблема согласованности для потока: Как правило, видеопоток должен начинаться с I-кадра, поэтому при разделении FFMPEG должен найти предыдущий I-кадр (при использовании кодека copy, и это изменяет длительность сегмента).

Когда вы объединяете, у вас также может возникнуть проблема согласованности (то есть, если объединяемый сегмент действительно заканчивается I-кадром, а следующий начинается с I-кадра, возможно, FFMPEG удалит один, хотя я не помню, какое сейчас поведение сейчас)

Итак, чтобы решить вашу проблему, на вашем месте я бы избежал шага 2 (в любом случае это плохо для качества). То есть я бы использовал ffmpeg для разделения интересующих сегментов на основе номера кадра (это единственное значение, которое не приблизительное в вашей схеме) в png или ppm кадрах (или в трубу, если вы не позаботьтесь о сохранении их), а затем объедините все кадры, кодируя их на последнем шаге с ожидаемой скоростью, установленной на totalVideoTime / totalFrameCount.

Вы получите финальное видео меньшего и более высокого качества.

Если по какой-то причине вы не можете сделать то, что я сказал, по крайней мере для ввода concat, вам следует использовать формат ffconcat:

ffconcat version 1.0
file segment1
duration 12.2
file segment2
duration 10.3

Это даст вам ожидаемую продолжительность, обрезая каждый сегмент, если он длиннее

Для выбора по номеру кадра (вместо времени, поскольку время трудно получить право на видео с переменной частотой кадров), вы должны использовать фильтр select, например:

-vf select=“between(n\,start_frame_num\,end_frame_num),setpts=STARTPTS"

0 голосов
/ 10 апреля 2019

Я предлагаю проверить частоту кадров на входе и выходе и убедиться, что они совпадают. Это может быть источником несоответствия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...