FFmpeg: разделение видео на сегменты очень маленького размера (например, 5 КБ)

#ffmpeg

#ffmpeg

Вопрос:

Я пытаюсь разделить видеофайл на сегменты размером менее 10 КБ (в идеале 5 КБ) с помощью FFmpeg.

Я использую вот это видео: https://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4 . Он уже имеет низкое разрешение.

Я попытался указать очень маленькое значение segment_time, равное 00:00:0.04:

 ffmpeg -i BigBuckBunny_320x180.mp4 -c copy -map 0 -f segment -segment_time 00:00:0.04 BigBuckBunny_320x180_d.mp4
  

Я попытался указать sequential -segment_frames, например, 1,2,3,4,5,6,7 … и т.д.:

 ffmpeg -i BigBuckBunny_320x180.mp4 -c copy -map 0 -f segment -segment_frames 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 -segment_list out.csv BigBuckBunny_320x180_d.mp4
  

Я также пытался принудительно использовать ключевые кадры:

 ffmpeg -i BigBuckBunny_320x180.mp4 -force_key_frames "expr:gte(t,n_forced*0.04)" -c copy -map 0 -f segment -segment_frames 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 BigBuckBunny_320x180_d.mp4
  

Все это приводит к получению сегментов длиной 0,5 с с различными размерами файлов, в среднем около 50 КБ.

 username@My-Air:~/dev/video$ less out.csv 
BigBuckBunny_320x180_000.mp4,0.000000,0.500000
BigBuckBunny_320x180_001.mp4,0.500000,1.000000
BigBuckBunny_320x180_002.mp4,1.000000,1.500000
BigBuckBunny_320x180_003.mp4,1.500000,2.000000
BigBuckBunny_320x180_004.mp4,2.000000,2.500000
BigBuckBunny_320x180_005.mp4,2.500000,3.000000
...

username@My-Air:~/dev/video/bunny_0.5s_splits$ ls -l
total 134552
-rw-r--r--  1 username  staff    16K 25 Mar 23:40 BigBuckBunny_320x180_000.mp4
-rw-r--r--  1 username  staff    26K 25 Mar 23:40 BigBuckBunny_320x180_001.mp4
-rw-r--r--  1 username  staff    36K 25 Mar 23:40 BigBuckBunny_320x180_002.mp4
-rw-r--r--  1 username  staff    44K 25 Mar 23:40 BigBuckBunny_320x180_003.mp4
-rw-r--r--  1 username  staff    40K 25 Mar 23:40 BigBuckBunny_320x180_004.mp4
-rw-r--r--  1 username  staff    38K 25 Mar 23:40 BigBuckBunny_320x180_005.mp4
-rw-r--r--  1 username  staff    43K 25 Mar 23:40 BigBuckBunny_320x180_006.mp4
-rw-r--r--  1 username  staff    44K 25 Mar 23:40 BigBuckBunny_320x180_007.mp4
-rw-r--r--  1 username  staff    50K 25 Mar 23:40 BigBuckBunny_320x180_008.mp4
-rw-r--r--  1 username  staff    49K 25 Mar 23:40 BigBuckBunny_320x180_009.mp4
-rw-r--r--  1 username  staff    50K 25 Mar 23:40 BigBuckBunny_320x180_010.mp4
-rw-r--r--  1 username  staff    51K 25 Mar 23:40 BigBuckBunny_320x180_011.mp4
-rw-r--r--  1 username  staff    51K 25 Mar 23:40 BigBuckBunny_320x180_012.mp4
-rw-r--r--  1 username  staff    57K 25 Mar 23:40 BigBuckBunny_320x180_013.mp4
-rw-r--r--  1 username  staff    53K 25 Mar 23:40 BigBuckBunny_320x180_014.mp4
-rw-r--r--  1 username  staff    57K 25 Mar 23:40 BigBuckBunny_320x180_015.mp4
-rw-r--r--  1 username  staff    57K 25 Mar 23:40 BigBuckBunny_320x180_016.mp4
-rw-r--r--  1 username  staff    61K 25 Mar 23:40 BigBuckBunny_320x180_017.mp4
...
  

Странно, что временные метки находятся ровно в 0 секундах и 0,5 секунды. Является ли это ограничением FFmpeg? Я не смог найти никакой документации, подтверждающей это.

Есть ли какой-либо способ уменьшить размер этих файлов до 5 КБ? Возможно ли это с помощью FFmpeg? Если нет, есть ли другой инструмент, который я мог бы использовать? Я посмотрел на GStreamer, но не смог понять, возможно ли это, и это кажется очень сложным.

Любая помощь приветствуется. Спасибо.

Комментарии:

1. Один кадр размером 320×180 равен 172 КБ без сжатия. Что заставляет вас думать, что 5 КБ достижимо?

2. Спасибо за ответ. Я сжал файл (с 62 МБ до 22 МБ), используя сжатие ffmpeg по умолчанию. Но теперь, когда я пытаюсь разделить сжатый файл на сегменты (используя 00: 00: 01 в качестве -segment_time ), кажется, что он разбивается на случайные интервалы. 10 секунд, 1 секунда, 3 секунды, 7 секунд, 10 секунд и т.д. Я получаю одни и те же сегменты, когда пытаюсь разделить каждый кадр (используя -segment-frames:1,2,3,4,5... ). В чем причина этого? Даже после прочтения документации я все еще немного смущен тем, как FFmpeg решает эти разделения!

3. Я бы предположил, что это из-за ключевых кадров, но я недостаточно осведомлен о процессе, чтобы быть уверенным.

4. Я заставил каждый кадр быть ключевым, и тогда мне удалось разделить видео, но сработало только первое разделение. Остальные фрагменты представляли собой просто черное видео без звука. Я могу разделить каждый второй кадр с помощью Movavi (в результате получаются сегменты достаточно маленького размера), но мне приходится делать это вручную, что невозможно для длинного видео. Я хотел бы знать, какое программное обеспечение он использует под обложками, так что, возможно, это можно сделать с помощью скрипта или команды?

5. Я не понимаю, почему цель недостижима, поскольку она была достигнута. Это качество видео здесь не проблема. Мне нужны были небольшие фрагменты для потоковой передачи видео по будущей сети 5G, которая находится на стадии тестирования и не может обрабатывать данные > 10 КБ. Я знаю, что это не обычный вариант использования, но приведенные ниже команды, которые показывают, как сжимать, устанавливать ключевые кадры и разбивать видео на сегменты, могут быть кому-то полезны. Очевидно, что им не нужно придерживаться тех же крайних ограничений, как вы выразились.

Ответ №1:

Хорошо, я наконец получил то, что хотел. Теперь у меня есть видеосегменты размером менее 10 КБ, в среднем около 5 КБ. Я использовал следующие команды:

  1. Сжат исходный видеофайл с использованием стандартного сжатия ffmpeg:
 ffmpeg BigBuckBunny_320x180.mp4 BigBuckBunny_320x180_compressed.mp4
  
  1. Установите интервал ключевых кадров равным 1, чтобы каждый кадр стал ключевым:
 ffmpeg -i BigBuckBunny_320x180_compressed.mp4 -vcodec libx264 -x264-params keyint=1:scenecut=0 -acodec copy BigBuckBunny_320x180_compressed_frames.mp4
  
  1. Разделите результирующий файл на сегменты длиной 0,04, что примерно равно длине одного кадра:
 ffmpeg -i BigBuckBunny_320x180_compressed_frames.mp4 -c copy -map 0 -segment_time 00:00:0.04 -f segment -reset_timestamps 1 BigBuckBunny_320x180_compre
ssed_framesd.mp4
  

Я решил предыдущую проблему, из-за которой только первый сегмент воспроизводился должным образом, используя: -reset_timestamps 1 .