Android開發:OpenGL 實現視頻編輯中的轉場效果

作者:glumes

轉場介紹

轉場效果是什麼?

轉場效果,簡單來說就是兩段視頻之間的銜接過渡效果。

現在拍攝 vlog 的玩家越來越多,要是視頻沒有一兩個炫酷的轉場效果,都不好意思拿出來炫酷了。

Android開發:OpenGL 實現視頻編輯中的轉場效果

那麼如何在視頻編輯軟件中實現轉場效果呢?

這裏提供使用 OpenGL 實現視頻轉場的一個小示例,我們可以通過自定義 GLSL 來實現不同的轉場效果。

以在 Android 平臺上作爲演示,但其實不管是 Android 還是 iOS,實現的原理都是一樣的。

首先要有兩段視頻,視頻 A 和視頻 B,先播放視頻 A 後播放視頻 B,中間有一段過程稱爲 C ,C 就是視頻 A、B 做轉場動畫的時間段。

如下所示:

Android開發:OpenGL 實現視頻編輯中的轉場效果

播放器按照時間順序,從 A -> C -> B 的播放,這樣就有了轉場的效果。


視頻轉場,首先就得有視頻,直接從視頻 A、B 中解碼出當前幀並通過 OpenGL 顯示到屏幕上就好了,如果你對這個操作不熟悉的話,可以查看我的公衆號【紙上淺談】歷史文章,都有寫過相關內容。

這裏以圖片來替代視頻 A、B 中解碼出來的幀。

最終效果如下:

Android開發:OpenGL 實現視頻編輯中的轉場效果

實現講解

###模擬視頻渲染播放

模擬 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 學習https://glumes.com/post/opengl/opengl-glsl-2-mark

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);
渲染進度控制

似乎到這裏就可以大功告成了,實際上纔剛剛完成了一半~~~

要知道轉場效果是隨着時間來播放的,就上面的例子中,轉場時間內,一開始都是視頻 A 的內容,然後視頻 A 逐漸減少,視頻 B 逐漸增多,到最後全是視頻 B 內容,在我們的 Shader 中也要體現這個時間變化的概念。

在 Shader 中定義 progress 變量,代表轉場的播放進度,進度爲 0 ~ 1.0 之間。

uniform float progress;

同時在每一次渲染時更新 progress 變量的值。

GLES20.glUniform1f(muProgressHandle, mProgress);

當 progress 爲 0 時代表轉場剛剛開始,當 progress 爲 1 時代表轉場已經結束了。

if (mProgress >= 1.0f) {
 mProgress = 0.0f;
} else {
 mProgress += 0.01;
}

這裏 progress 每次遞增 0.01,完成一次轉場就需要 100 次渲染,每次渲染間隔 30ms,那麼一次轉場動畫就是 3000ms 了,當然這個可以自己調節的。

畫面繪製

再回到 mix 函數的參數 a ,這個參數起到了隨時間調節轉場混合程度的作用。當 a = 0 時,全是視頻 A 的內容, 當 a = 1 時,全是視頻 B 的內容。

Android開發:OpenGL 實現視頻編輯中的轉場效果

如上圖所示,在轉場動畫的某一幀,左側是視頻 A 的內容,因爲此時 a = 0,右側是視頻 B 的內容,此時 a = 1 。

可以看到在一次渲染繪製內 a 既要能等於 0 ,還要能等於 1 ,這個是怎麼實現的呢?

事實上我們說的一次渲染繪製,通常指 OpenGL draw 方法的一次調用,但是在這一次調用裏,還是有很多步驟要執行的。

OpenGL 渲染管線會先執行頂點着色器,然後光柵化,再接着就是片段着色器,片段着色器會根據紋理座標採樣紋理貼圖上的像素內容進行着色,因此片段着色器在管線中會多次執行,針對每個像素都要進行着色。

Android開發:OpenGL 實現視頻編輯中的轉場效果

上面圖像的小方塊就好比一個像素,每個像素都要執行一個片段着色器。

首先,肯定所有的像素都要進行着色的。左側方塊採樣視頻 A 的紋理進行着色,右側方塊採樣視頻 B 的紋理進行着色。

回到如下代碼:

mix(texture2D(sTexture1,vTextureCoord),texture2D(sTexture2,vTextureCoord),a);

只要保證繪製左側時 a = 0,繪製右側時 a = 1 就行了。這裏可以通過移動紋理座標來控制 a 的值。

vec2 p = vTextureCoord + progress * sign(direction);
float a = step(0.0,p.y) * step(p.y,1.0) * step(0.0,p.x) * step(p.x,1.0);

OpenGL 中定義紋理座標範圍是 [0 ~ 1] ,可以將範圍右移 0.5 ,從而變成 [0.5 ~ 1.5] ,此時紋理座標一半位於規定範圍內,一半超出界外了。

這樣就可以通過對當前像素小方格對應的紋理座標的 x,y 值運用 step 函數進行判斷是否在界內,就可以決定是採樣視頻 A 還是視頻 B 的圖像了。

當每次刷新 progress 時,就向右移一小段距離,視頻 A 隨着右移而變少,視頻 B 變多,這樣就是實現了轉場效果。


聯想和總結

不知道這個簡單的例子有沒有讓你想到些什麼?

對的,沒錯,就是升職加薪,走向巔峯必備的 PPT 技能,這種視頻轉場的實現效果就和我們在編輯 PPT 動畫時添加的一樣。

Android開發:OpenGL 實現視頻編輯中的轉場效果

而且這還是比較簡單的,想要做一些花裏胡哨的轉場特效,缺少靈感就可以參考 PPT 裏面的動畫了。

另外,我們還可以對轉場效果做一些總結分類,比如示例中用的是圖片,可以理解成視頻 A 的最後一幀顯示與視頻 B 的第一幀顯示做轉場效果,這種轉場效果實際使用的人比較少,大多數是視頻 A 的最後一幀與視頻 B 的前一段時間的視頻做轉場效果。

因此也可以對轉場效果做個分類:

  • 視頻 A 最後一幀與視頻 B 第一幀做轉場動畫
  • 視頻 A 最後一幀與視頻 B 前一段時間視頻做轉場動畫
  • 視頻 A 最後一段時間視頻 與視頻 B 第一幀做轉場動畫
  • 視頻 A 最後一段時間視頻 與視頻 B 前一段時間視頻做轉場動畫

這四個分類的實現原理其實都差不多,如果是一段視頻的話,那麼就在視頻播放時更新對應紋理。

以上就在關於使用 OpenGL 在視頻編輯中實現轉場效果的講解,通過這篇文章希望大家可以掌握轉場的基本實現原理。

Android學習PDF+架構視頻+面試文檔+源碼筆記


感謝大家能耐着性子看完

在這裏小編也分享一份自己收錄整理的Android學習PDF+架構視頻+面試文檔+源碼筆記,還有高級架構技術進階腦圖、Android開發面試專題資料,高級進階架構資料幫助大家學習提升進階,也節省大家在網上搜索資料的時間來學習,也可以分享給身邊好友一起學習

如果你有需要的話,可以點贊+評論關注我,然後加我VX:15388039515 我發給你
(或關注微信公衆號“Android開發之家”回覆【資料】免費領取)
Android開發:OpenGL 實現視頻編輯中的轉場效果

Android開發:OpenGL 實現視頻編輯中的轉場效果

Android開發:OpenGL 實現視頻編輯中的轉場效果

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章