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.

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

Благодарю.

Solutions Collecting From Web of "Android MediaCodec: уменьшите размер видео mp4"

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

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

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

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

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