OpenGL 实现视频编辑中的转场效果

转场介绍

转场效果是什么?

转场效果,简单来说就是两段视频之间的衔接过渡效果。

现在拍摄 vlog 的玩家越来越多,要是视频没有一两个炫酷的转场效果,都不好意思拿出来炫酷了。

image

image

那么如何在视频编辑软件中实现转场效果呢?

这里提供使用 OpenGL 实现视频转场的一个小示例,我们可以通过自定义 GLSL 来实现不同的转场效果。

以在 Android 平台上作为演示,但其实不管是 Android 还是 iOS,实现的原理都是一样的。

首先要有两段视频,视频 A 和视频 B,先播放视频 A 后播放视频 B,中间有一段过程称为 C ,C 就是视频 A、B 做转场动画的时间段。

如下所示:

transition_model.jpg

transition_model.jpg

播放器按照时间顺序,从 A -> C -> B 的播放,这样就有了转场的效果。


视频转场,首先就得有视频,直接从视频 A、B 中解码出当前帧并通过 OpenGL 显示到屏幕上就好了,如果你对这个操作不熟悉的话,可以查看我的公众号【纸上浅谈】历史文章,都有写过相关内容。

这里以图片来替代视频 A、B 中解码出来的帧。

最终效果如下:

transition_sample.gif

实现讲解

模拟视频渲染播放

模拟 fps 为 30 的视频,用 RxJava 每间隔 30 ms 就触发一次 OpenGL 渲染。

Observable
        .interval(30, TimeUnit.MILLISECONDS)
        .subscribeOn(AndroidSchedulers.mainThread())
        .subscribe {
            mGLSurfaceView.requestRender()
        }

另外,如果在视频 A 播放阶段不断地改变图片,也就是更新纹理内容,就相当于在真实的解码视频进行播放了。

当然这些操作只是为了让这个小例子更加贴近真正的视频转场,重要的还是在于如何实现转场的 Shader 效果。

首先转场的时候要有两个纹理作为输入,那么肯定要定义两个 sampler2D 进行采样了。

varying vec2 vTextureCoord;//接收从顶点着色器过来的参数
uniform sampler2D sTexture1;
uniform sampler2D sTexture2;

其中 sTexture1 对应于视频 A 内容,sTexture2 对应于视频 B 内容。

vTextureCoord 对应于顶点着色器传递过来的纹理坐标,视频 A 和 视频 B 都需要用到这个纹理坐标。

这个时候,只要调用 texture2D 方法就能得到视频 A 和 视频 B 的内容了。

// 得到视频 A 的内容
texture2D(sTexture1,vTextureCoord)
// 得到视频 B 的内容
texture2D(sTexture2,vTextureCoord)

要注意的是这里说得到视频 A/B 的内容,是得到纹理坐标对应的图像内容。也就是说如果纹理坐标是 [0,1] 范围内,那么可以得到视频 A/B 的全部图像内容。如果坐标是 [-0.5,0.5] 那么只能采样得到一半内容了。

转场效果实现

混合函数 mix

由于转场效果是需要视频 A 和视频 B 进行叠加混合的,而 GLSL 内嵌了 mix 函数进行调用。

对于 GLSL 中有哪些内嵌的函数可以直接调用的,可以参考写过的文章记录:

OpenGL ES 2.0 着色器语言 GLSL 学习

mix 函数的声明如下:

genType mix(genType x,genType y,float a) // 其中 genType 泛指 GLSL 中的类型定义

它的主要功能是使用因子 a 对 x 与 y 执行线性混合,既返回 x * (1-a) + y * a

现在,通过 texture2D 能得到视频帧内容,通过 mix 能进行视频帧混合叠加,那么就可以得到最后转场视频帧了。

vec4 color = mix(texture2D(sTexture1,vTextureCoord),texture2D(sTexture2,vTextureCoord),a);
top Created with Sketch.