Подтвердить что ты не робот

Android MediaCodec: уменьшите размер видео mp4

Я ищу способ "сжать" видео mp4. Для этого я хочу уменьшить разрешение видео и/или уменьшить FPS.

После долгих исследований я думаю, что способ сделать это - использовать MediaCodec и связанные с ним API следующим образом:

- > MediaExtractor для извлечения закодированных медиаданных из файла mp4. - > MediaCodec (декодер): декодировать каждый кадр для последующей обработки. - > MediaCodec (Encoder): На данный момент я предполагаю, что там, где мы должны установить параметры MediaFormat, такие как разрешение видео, что должно помочь нам уменьшить конечный размер файла mp4. - > MediaMuxer для генерации файла mp4 (MinSDK 18, это может быть проблемой, но на данный момент... ok).

Я не хочу использовать SurfaceView/TextureView. Что касается звука, я не хочу обрабатывать его для снижения качества.

Я рассматривал все примеры здесь: http://bigflake.com/mediacodec/

Я также видел модули исходного кода CTS.

И я смотрел несколько таких проектов: https://github.com/vecio/MediaCodecDemo/blob/master/src/io/vec/demo/mediacodec/DecodeActivity.java

И, конечно же, я прочитал десятки сообщений о stackoverflow.

Проблема в том, что я еще не нашел кода, который хорошо работает для этой породы. Я попытался взять различные фрагменты кода и объединить их в проект, но на самом деле не работает.

Спасибо.

4b9b3361

Ответ 1

Ближайшая вещь к тому, что вы хотите, вероятно, DecodeEditEncodeTest на большой ленте. Вам не нужны SurfaceView или TextureView, так как вы не пытаетесь отобразить видео, но вам нужно будет использовать SurfaceTexture.

Тест-код генерирует видео, затем декодирует/редактирует/кодирует, затем проверяет кодированный вывод. Вам нужна часть декодирования-редактирования-кодирования. При создании кодера дайте ему любой размер, который вы хотите. Созданная им поверхность ввода будет соответствовать размерам. Масштабирование выполняется графическим процессором, поскольку он отображает текстуру GL (от SurfaceTexture) на входную поверхность энкодера. Вам нужно будет решить, обеспечивает ли линейная фильтрация GLES необходимый уровень качества.

(Вы можете увидеть что-то подобное в ExtractMpegFramesTest, которое масштабирует все до 640x480, когда оно выполняет извлечение. В этом случае оно преобразует кадры в PNG, а не подавать их в кодировщик, поэтому он не подходит для вашей ситуации.)

Отбрасывание кадров теоретически просто: просто не отправляйте его в кодировщик. На практике это немного сложнее, если вход имеет нерегулярно разнесенные кадры. Если вход "frame1 frame2... pause... frame4 frame5", и вы отбрасываете frame2, вы в конечном итоге будете приостановлены на frame1, что может показаться странным. Вы можете использовать метки времени представления, чтобы определить время.

Поверхностный ввод и MediaMuxer (необходимый для сохранения H.264 как .mp4) требуют API 18+. Для более старых версий Android вы, вероятно, захотите использовать стороннюю библиотеку, например ffmpeg.