Мое требование состоит в том, чтобы кадрировать точно (несколько кадров вверх / вниз) обрезать на лету mp4 (h264 + aac) видеопоток https с помощью ffmpeg на мобильном телефоне как можно быстрее - это означает, что я буду торговать при необходимости плохим сжатием (больший выходной файл) большая скорость резания. В настоящее время я режу видео с помощью этой команды:
ffmpeg -ss [start_time] -i https://domain/in.mp4 -t 00:00:10.000 -c:a copy -c:v copy out.mp4
Этот подход (копирование битового потока) очень быстрый (менее чем за секунду в хорошей сети при 10-секундной вырезке видео), но не точно вырезает видео. Видео вырезано по ключевым кадрам, что неточно.
Поэтому моя идея состоит в том, чтобы компенсировать эту неточность (расстояние от ключевого кадра), просматривая видео перед его воспроизведением:
delta = start_time - first_key_frame_timestamp_before_start_time
Чтобы вычислить дельту, мне нужен очень быстрый способ получить time_stamp первого ключевого кадра перед началом времени. Я видел пост, в котором объясняется, как получить временную метку первого ключевого кадра до start_time, но этот подход непрактичен для длинных (2 часа +) видео, потому что потребуется много времени, чтобы эта операция достигла, скажем, середины видео. Мне нужно что-то вроде этого:
ffmpeg -ss 01:30:06.000 -i https://domain/in.mp4 -t 2 -show_frames > frame_meta.txt
Я также попытался выполнить точную обрезку путем перекодирования видео (видео продолжительностью 2 часа, видео длиной 10 секунд в середине видео) с помощью этой команды:
ffmpeg -ss [start_time] -i https://domain/in.mp4 -t 10 out.mp4
но для того, чтобы завершить работу на мобильном устройстве, требуется много времени (~ 16 секунд) по сравнению с менее чем второй командой копирования битового потока. Спасибо за любую полезную подсказку или решение.
РЕДАКТИРОВАТЬ 1:
Мне удалось вычислить дельту и получить временную метку первого ключевого кадра до start_time с помощью внутренних классов ExoPlayer(мультимедийный проигрыватель Android), и этот подход очень быстр: от 500 мс (очень короткие видеоролики) до 1500 мс (для очень длинных видео). По сути, этот подход основан на синтаксическом анализе meta_headers (атома moov) удаленного потока mp4, чтобы найти адекватную метку времени ключевого кадра перед вырезом start_time. Теперь возникает новая проблема, когда видео обрезается с помощью:
ffmpeg -ss [start_time] -i https://domain/in.mp4 -t 00:00:10.000 -c:a copy -c:v copy out.mp4
Атом edit-list добавляется в мета-заголовок, как понятно из этого и этого поста, в котором игроку следует начать игру с дельта-смещением по времени, чтобы компенсировать неточное вырезание видео, которое выполняется с помощью команды копирования ffmpeg bitStream. Но плееры, которые я использую на Android, не поддерживают воспроизведение списка редактирования, потому что они просто начинают нормально воспроизводиться с начала видео или останавливаются на каком-то кадре на несколько секунд, пока воспроизводится звук, а затем продолжают нормально воспроизводиться.
Когда я пытаюсь найти ранее рассчитанную дельту и затем начать воспроизведение на обрезанном видео, я не позиционируюсь на правильном кадре (например, рассчитанная дельта = 1 381 мс, но реальная / рабочая дельта = 444 мс), и мой план компенсации неточной обрезки не работает:(. Если вы спрашиваете себя, правильно ли я вычислил дельту, я проверил ее с помощью IsoViewer (синтаксический анализатор контейнеров mp4) и вручную, просматривая кадры с помощью Avidemux и просматривая пару значений time_stamp / frame_type ...