之前写了一篇
主要是研究ffmpeg在Android端的应用,那既然有了ffmpeg为什么还要去用其他的技术去做音视频合成呢,有两点:性能差,效果不够
1.性能差:
ffmpeg输入为一次性输入,然后逐帧渲染,再加上filtrer过滤器,添加各种效果,使得每次渲染都会去做大量操作,导致OOM,还有就是ffmpeg使用CPU进行软解码,OpenGl使用GPU硬解码
2.效果不够:
这里的效果主要是转场效果,视频之间的转场,ffmpeg没有转场的功能命令,所以需要自己用骚操作实现,但这样会导致大量的性能损耗,这一点之前的文章说过
使用OpenGl合成视频转场后的性能对比
对比数据表格之前记录了但找不到了,
图片处理速度明显提升,基本是毫秒级别
视频处理速度提升大概200%。
可以看出很明显的OpenGL对于性能的提升,2.0版本是进行了优化并且没有丰富的转场效果前提下才达到这个性能,3.0使用OpenGL做出了比较多的转场效果,可参考gl-transitions.com/
中间也遇到了比较多的问题,写出来记录一下:
1.OpenGL渲染要每一帧的图像资源,视频需要逐帧去获取图像,比较耗时
办法:合成开始前先用Android原生解码器把视频每一帧缓存下来,用的时候直接拿
2。OpenGL是图像处理库,不支持音频处理
办法:合成的时候把视频轨道和音频轨道分开用两个线程来处理,视频使用ffmpeg+OpenGl,音频使用ffmpeg+Android原生,最后用编码器把音轨混合进视频中导出一个完整视频
转场效果的实现:
思路还是跟之前一样,在第一个视频的末尾转场处同时去获取第二个视频的开头的textureId,同步渲染
public void exec() { //第二个视频的纹理图像Id
int texture2 = mContext.getToTextureId(mProgress , (int) mTransitionDuration);
if (texture2 != -1) {
mContext.attachOffScreenTexture(mContext.getOutputTextureId());
if (mDrawer == null) {
getDrawer();
}
mDrawer.setProgress(mProgress);//当前转场进度
mDrawer.setRatio(mContext.getRenderWidth() * 1.0f / mContext.getRenderHeight());
mDrawer.setToRatio(mContext.getNextAspectRatio());
setDrawerParams();
mDrawer.draw(mContext.getFromTextureId(),//当前视频的纹理图像Id
texture2,
mContext.getRenderLeft(),