<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android 短視頻 SDK 轉(zhuǎn)場特效的音視頻同步分析

          共 3350字,需瀏覽 7分鐘

           ·

          2022-05-22 09:02

          在短視頻的應用場景中,經(jīng)常存在用戶拍攝的兩個或者多個視頻生成一個視頻的需求,為了達到兩個視頻平滑過渡,就需要在兩個視頻中間添加轉(zhuǎn)場效果。

          由于導入視頻的幀率、碼率等參數(shù)都不一致,如何保證在添加完轉(zhuǎn)場效果后音視頻同步?

          本文主要介紹轉(zhuǎn)場效果的實現(xiàn)及如何保證最終合成視頻的音視頻同步,同時簡單介紹一下轉(zhuǎn)場濾鏡。

          作者:金山視頻云 

          鏈接:https://www.jianshu.com/p/5eef175a8cb8

          一. 轉(zhuǎn)場功能介紹

          市面上的轉(zhuǎn)場基本分為三類:

          1. 片頭片尾轉(zhuǎn)場:即只作用在一個視頻上。

          此種和普通的時間濾鏡添加區(qū)別不大,并不復雜,本文不再贅述

          1. 非重疊轉(zhuǎn)場:轉(zhuǎn)場接替作用在第一個視頻的最后和第二個視頻的開始,兩個視頻是順次拼接。

          比如持續(xù)1s的blur轉(zhuǎn)場,blur濾鏡 在第一個視頻的最后0.5s開始,直到結(jié)束,作用是由清晰變模糊;在第二個視頻的開始作用,持續(xù)0.5s,作用是由模糊變清晰。

          1. 重疊轉(zhuǎn)場:轉(zhuǎn)場疊加作用在第一個視頻的最后和第二個視頻的開始,兩個視頻有一個轉(zhuǎn)場時間的重疊區(qū)。

          比如持續(xù)1s的 淡入淡出轉(zhuǎn)場,淡入淡出濾鏡接收兩個視頻輸入源,并且從第一個視頻的最后1s開始作用,即在第一個視頻的最后1s需要同時啟動第二個視頻的解碼,并將解碼后的數(shù)據(jù)輸入到濾鏡中,在轉(zhuǎn)場的持續(xù)時間內(nèi)是同時疊加了兩個視頻數(shù)據(jù)。

          二. 轉(zhuǎn)場方案介紹

          轉(zhuǎn)場是在時間上對多個視頻做轉(zhuǎn)碼和拼接。

          我們采取的方案如如下圖所示,依次對待拼接文件做解碼,輸出音頻采樣和視頻像素數(shù)據(jù)到編碼器,經(jīng)過muxer最終將不同幀率、碼率的視頻生成統(tǒng)一格式的文件。

          上圖中AVMediaCapture為demuxer和decoder的封裝。

          如第一章節(jié)的介紹轉(zhuǎn)場同一時間最多作用在兩個視頻上,因此只需要創(chuàng)建兩個AVMediaCapture的實例,第一個視頻解碼結(jié)束后,第三個視頻可以使用第一個視頻創(chuàng)建的AVMediaCapture,依次類推,避免反復創(chuàng)建造成資源浪費。

          如下圖所示:

          而對于AVMediaCapture中的解碼器(硬解為例),也不需要反復創(chuàng)建,我們來看官網(wǎng)上關于MediaCodec的生命周期:

          如上圖所示,當一個文件解碼完成以后,通過reset接口使解碼器處于Uninitialized狀態(tài),當對第二個文件進行解碼時,只需要重新configure,start即可。

          三. 轉(zhuǎn)場中的音視頻pts 計算

          3.1 非重疊轉(zhuǎn)場

          在兩個視頻之間添加持續(xù)時間 trans_t 的轉(zhuǎn)場濾鏡,濾鏡在第一個視頻 [dur_0 - trans_t / 2.0f] 開始作用,直到第一個視頻結(jié)束,然后繼續(xù)在第二個視頻的開始作用,持續(xù) [trans_t / 2.0f]。

          pts 依次是之前視頻時長的累加,公式如下:

          vTrack_1 和 aTrack_1 開始點的 pts : [0 + dur_0];

          vTrack_2 和 aTrack_2 開始點的 pts : [dur_0 + dur_1]。

          vTrack_n 和 aTrack_n 開始點的 pts : [dur_0 + dur_1 + ... + dur_n]。

          3.2 重疊轉(zhuǎn)場

          在兩個視頻之間添加持續(xù)時間 trans_t 的轉(zhuǎn)場濾鏡,濾鏡是同時作用在兩個視頻上的,因此濾鏡在第一個視頻的 [dur_0 - 1.0f] 時開始作用,直到第一個視頻結(jié)束,同時開始第二個視頻的解碼,并作為濾鏡的第二視頻輸入源。

          pts 的計算需要將轉(zhuǎn)場的作用時間裁剪掉,公式如下:

          vTrack_1 和 aTrack_1 開始點的 pts: [0 + dur_0 - trans_t];

          vTrack_2 和 aTrack_2 開始點的 pts: [dur_0 + dur_1 - 2 * trans_t]。

          vTrack_n 和 aTrack_n 開始點的 pts: [dur_0 + dur_1 + ... + dur_n - n * trans_t]

          四. 轉(zhuǎn)場中的音視頻同步

          因為采用的是pull的方式從解碼向編碼輸入數(shù)據(jù),因此在添加重疊場景的轉(zhuǎn)場時,在轉(zhuǎn)場的時間段內(nèi),同時存在2個音頻軌道和2個視頻軌道,就需要考慮四個軌道的同步問題

          • 單個視頻的音視頻解碼同步

          重疊場景的轉(zhuǎn)場,若音視頻 demuxer 相差很大,比如第一個視頻的音頻已經(jīng) demuxer 結(jié)束,但是第一個視頻的視頻還在繼續(xù)處理,因為同時開啟了第二個視頻的 demuxer ,所以會有累加的音視頻不同步的情況。

          如上圖所示,在 decoder 之后添加AVSync模塊以解決此種情況的不同步問題,AVSync模塊采用視頻驅(qū)動音頻的同步模式,即,對音頻做緩存,以視頻幀驅(qū)動音頻幀向下傳遞,threshold 不超過100ms。

          • 兩個視頻之間的視頻解碼同步

          重疊場景下,轉(zhuǎn)場濾鏡需要同時輸入兩個視頻源,若第一個視頻解碼速度快,但是第二個視頻的解碼速度慢,會造成某一幀數(shù)據(jù)中只有第一個視頻,并沒有第二個視頻,或者濾鏡已經(jīng)持續(xù)了0.8s了,第二個視頻才有了輸入,造成整體的轉(zhuǎn)場效果較差。

          為了解決此種問題,加入 VTracks_Sync 同步模塊, Vtracks_Sync 保證兩個視頻的 pts 的diff在100ms之內(nèi),若 vtrack_0_pts – vtrack_1_pts > 100ms, 則對 vtrack_0 的 demuxer 做暫停,反之對 vtrack_1 的 demuxer 做暫停,以達兩個視頻源的同步

          五. 轉(zhuǎn)場濾鏡

          重疊轉(zhuǎn)場的漸變?yōu)V鏡,基本方案為 以vtrack_0 為濾鏡的主視頻輸入源 sTexture ,以 vtrack_1 為濾鏡第二個視頻輸入源 vTexture1 ,在 shader 中通過修改漸變因子,以達到不同輸入源的比重不同。

          以最簡單的淡入淡出濾鏡為例,offset 為漸變因子,例如持續(xù)時間為1s的轉(zhuǎn)場,則offset在1s內(nèi)從0漸變到1,作用到視頻幀的單位值計算公式:[offset_maxvalue / offset_maxcount]

          offset_maxvalue為漸變因子的最大值,即1

          offset_maxcount為作用幀數(shù),以幀率是20為例,1s的轉(zhuǎn)場,offset_maxcount即為20。

          void main()       
          {
                  vec4 video = texture2D(sTexture, vTextureCoord);
                  vec4 screen = texture2D(vTexture1, vTextureCoord);  
                  gl_FragColor = mix(video, screen, offset);
          };

          mix是對video和screen做線性混淆,即gl_FragColor = video(1- offset) + (screen * offset)

          最后歡迎大家加入 音視頻開發(fā)進階 知識星球 ,這里有知識干貨、編程答疑、開發(fā)教程,還有很多精彩分享。


          更多內(nèi)容可以在星球菜單中找到,隨著時間推移,干貨也會越來越多!!!


          給出 10元 優(yōu)惠券,漲價在即,目前還是白菜價,基本上提幾個問題就回本,投資自己就是最好的投資!!!


          加我微信 ezglumes ,拉你進技術交流群

          推薦閱讀:

          音視頻開發(fā)工作經(jīng)驗分享 || 視頻版

          OpenGL ES 學習資源分享

          開通專輯 | 細數(shù)那些年寫過的技術文章專輯

          Android NDK 免費視頻在線學習!!!

          你想要的音視頻開發(fā)資料庫來了

          推薦幾個堪稱教科書級別的 Android 音視頻入門項目

          覺得不錯,點個在看唄~


          瀏覽 61
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大香蕉在线69 | 大黄片AAA | 国产免费A片 | 中文字幕东京热 | 看操逼视频 |