我正在寻找一种“压缩”mp4视频的方法。为实现这一目标,我希望降低视频分辨率和/或降低FPS。
经过长时间的研究,我认为这样做的方法是使用MediaCodec和相关的API,如下所示:
- > MediaExtractor从mp4文件中提取编码的媒体数据。 - > MediaCodec(解码器):解码每个帧以供以后处理。 - > MediaCodec(编码器):此时,我想我们应该在哪里建立MediaFormat参数,例如视频分辨率,这应该有助于我们减少mp4文件的最终大小。 - > MediaMuxer用于生成mp4文件(MinSDK 18,这可能有问题,但现在......好吧)。
我不想使用SurfaceView / TextureView。 关于音频,我不想处理它以降低质量。
我一直在看这里的所有例子: http://bigflake.com/mediacodec/
我也看过CTS源代码模块。
我一直在研究以下几个项目: https://github.com/vecio/MediaCodecDemo/blob/master/src/io/vec/demo/mediacodec/DecodeActivity.java
当然,我已经在stackoverflow上阅读了几十篇帖子。
问题是我还没有找到任何适用于此porpuse的代码示例。我尝试将各种代码片段放在一起放在一个项目中,但实际上并不起作用。
感谢。
答案 0 :(得分:4)
最接近你想要的东西可能是bigflake上的DecodeEditEncodeTest。您不需要SurfaceView
或TextureView
,因为您没有尝试显示视频,但您需要使用SurfaceTexture
。
测试代码生成视频,然后解码/编辑/编码,然后测试编码输出。你想要解码编辑编码部分。创建编码器时,请给它任意大小。它创建的输入表面将调整大小以匹配。缩放由GPU执行,因为它将GL纹理(从SurfaceTexture
)渲染到编码器的输入表面上。您必须决定GLES线性过滤是否提供您所需的质量水平。
(您可以在ExtractMpegFramesTest中看到类似的东西,它在进行提取时将所有内容扩展到640x480。在这种情况下,它将帧转换为PNG而不是将它们送入编码器,因此它不适用于你的情况。)
理论上,删除帧很简单:只是不要将它提交给编码器。实际上,如果输入具有不规则间隔的帧,则会更难。如果输入是“frame1 frame2 ... pause ... frame4 frame5”,并且你丢弃了frame2,你最终会在frame1上暂停,这可能看起来很奇怪。您可以使用演示时间戳来计算时间。
表面输入和MediaMuxer
(将H.264保存为.mp4所需)需要API 18+。对于旧版Android,您可能希望使用第三方库,例如ffmpeg。