欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

小程序上視頻列表的渲染與性能優(yōu)化 - 新聞資訊 - 云南小程序開發(fā)|云南軟件開發(fā)|云南網(wǎng)站建設(shè)-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設(shè)/小程序開發(fā)/軟件開發(fā)

知識

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側(cè)重于功能的便捷,營銷的便利,運營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!

您當(dāng)前位置>首頁 » 新聞資訊 » 小程序相關(guān) >

小程序上視頻列表的渲染與性能優(yōu)化

發(fā)表時間:2021-1-5

發(fā)布人:葵宇科技

瀏覽次數(shù):111

小程序的部分組件是由客戶端渲染的原生組件,本文使用的 video 組件屬于其中之一。視頻列表涉及多個 video 組件的渲染、資源加載、滑動,處理不當(dāng)會帶來比較大的性能消耗。本文通過多種方案的對比,探討視頻列表渲染的最佳姿勢,達(dá)到性能優(yōu)化的目的。

一、背景

qq 小程序應(yīng)用商店上的“值得一玩”模塊,是由多個橫向排列的視頻組成的視頻列表。該模塊始終有一個視頻完全處于可視區(qū)域,下一個視頻的一部分露出。左右滑動列表切換下一個視頻到可視區(qū)域,在 wifi 條件下自動播放可視區(qū)域視頻。效果如下圖所示:

根據(jù)業(yè)務(wù)需要,視頻列表采用騰訊視頻插件 txv-video 代替 video 組件,txv-video 底層也是 video 組件,只是在上面多封裝了一層。

二.渲染方案對比

方案1:一次性渲染所有的 video 組件

剛拿到這個需求,想著 video 組件數(shù)量不多(最多5個),直接全部渲染影響應(yīng)該不大。效果如下所示:

可以看到,模塊加載時間過長,出現(xiàn)了 1-2s 的白屏現(xiàn)象。

下面從原生組件的渲染過程來解釋原因。原生組件有非同層渲染、同層渲染2種渲染方式。

非同層渲染下,video 組件的渲染過程:

1. WebView 渲染一個占位元素,包括創(chuàng)建組件,計算組件位置、大小,通知客戶端。

2. 客戶端在相同的位置上,根據(jù)寬高插入一塊原生區(qū)域進(jìn)行渲染。

同層渲染下,video 組件的渲染過程(ios和安卓渲染方式不同,此處以安卓為例):

1. WebView 創(chuàng)建一個 embed DOM 節(jié)點并指定組件類型。

2. chromium 內(nèi)核會創(chuàng)建一個  WebPlugin 實例,并生成一個渲染層 RenderLayer。

3. WebView 通知客戶端創(chuàng)建原生組件。

4. 客戶端將原生組件的畫面繪制到步驟2創(chuàng)建的 RenderLayer 所綁定的 SurfaceTexture 上。通知 chromium 內(nèi)核渲染該 RenderLayer 。

5. chromium 渲染該 embed 節(jié)點并上屏。

在非同層渲染下,原生組件的層級永遠(yuǎn)高于 Webview 的層級(無論 z-index 設(shè)置為多少),當(dāng)組件位置發(fā)生改變時, Webview 通知客戶端更新。這樣會導(dǎo)致在切換視頻時,video 組件位置的更新速度跟不上滑動速度,出現(xiàn)“連在一起”的現(xiàn)象。

安卓的同層渲染真正將原生組件視圖加到了 WebView 的渲染流程中且 embed 節(jié)點是真正的 DOM 節(jié)點。當(dāng)組件的位置發(fā)生改變時,WebView 更新,不用與客戶端通信。目前 qq 小程序的 video 組件已經(jīng)支持同層渲染。

可以看到,渲染過程涉及 WebView、客戶端、內(nèi)核的一系列操作。因此,當(dāng) video 組件個數(shù)越多時,渲染這些 video 組件耗費的時間越長。

方案2:開始只加載1個 video 組件,移動到目標(biāo)區(qū)域后再加載 video 組件

根據(jù)方案1的結(jié)論,減少模塊加載時渲染的video 組件個數(shù)。開始只渲染1個 video 組件,其余不在可視區(qū)域的用 image 標(biāo)簽代替,移動到可視區(qū)域后再渲染 video 組件。效果如下所示:

可以看到,相比方案1,模塊加載時間明顯減少。

同時發(fā)現(xiàn):在 wifi 條件下自動播放可視區(qū)域視頻,左右滑動時會發(fā)生卡頓現(xiàn)象。如下所示:

嘗試了開啟 3d 加速、先暫停視頻再滑動(避免直接滑動視頻帶來的性能問題)等方法都沒有明顯的改進(jìn)。在非 wifi 情況下,不自動播放可視區(qū)域視頻,不會發(fā)生卡頓現(xiàn)象。

滑動切換播放視頻的過程如下圖所示:

視圖層 Webview 處理 touch 事件,調(diào)用 callMethod 與 邏輯層 Appservice 通信;Appservice 收到當(dāng)前 video 組件的 index 信息后,setVid 加載資源,執(zhí)行 play 操作, 通知客戶端;客戶端播放當(dāng)前視頻,暫停上一個視頻。

從表象上看,卡頓現(xiàn)象的發(fā)生與滑動到目標(biāo)區(qū)域后是否播放視頻有關(guān)。是 Appservice 與客戶端的通信阻塞了 Webview 的操作?還是播放視頻導(dǎo)致了卡頓的發(fā)生呢?

小程序的卡頓通常發(fā)生在邏輯層與視圖層頻繁地通信、頁面節(jié)點數(shù)過多等情況下,Appservice 與客戶端的簡單一次通信并不會造成卡頓的發(fā)生,猜想是播放視頻導(dǎo)致了卡頓。去除自動播放視頻的操作,手動控制 video 組件播放或暫停,切換視頻時發(fā)現(xiàn)卡頓依然明顯。 卡頓與滑動到目標(biāo)區(qū)域后是否立即播放視頻沒有關(guān)系,而與播放過的video組件個數(shù)有關(guān),播放過的video組件個數(shù)越多,切換時越卡頓。

下面從 chromium 內(nèi)核對 video 標(biāo)簽的處理來解釋原因。

chromium 是通過 WebKit 解析網(wǎng)頁內(nèi)容的。當(dāng) WebKit 遇到 video>標(biāo)簽時,就會創(chuàng)建一個播放器實例。WebKit 并沒有自己實現(xiàn)播放器,而僅僅是創(chuàng)建一個播放器接口。通過這個播放器接口,可以使用平臺提供的播放器來播放視頻的內(nèi)容。 當(dāng)創(chuàng)建  video>標(biāo)簽時,僅僅創(chuàng)建了類型為 HTMLMediaElement 的 DOM 節(jié)點。當(dāng)為 video 組件的 src 賦值時,會調(diào)用接口創(chuàng)建播放器,進(jìn)行視頻資源信息加載、視頻解碼等一系列操作,“真正”渲染 video 組件。

上述操作會占用一部分系統(tǒng)資源,播放過的 video 組件個數(shù)越多,占用的系統(tǒng)資源越多,切換視頻時越卡頓。即使暫停視頻也沒用,video組件實例仍然存在沒被銷毀,依舊占用系統(tǒng)資源。

方案3:video 組件實例復(fù)用

根據(jù)方案1、2的結(jié)論,減少 video 組件實例個數(shù)??紤]采用3個 video 組件,索引為 index % 3 的 video 組件用來播放當(dāng)前視頻,索引為 ( index+1 ) % 3 的 video 組件用來預(yù)加載下一個視頻,索引為( index+2 ) % 3 的 video 組件用來緩存上一個視頻。在左右滑動切換時僅更改這3個 video 組件的 transform,達(dá)到視覺隱藏和實例復(fù)用的目的。從需求背景可以看到,本需求要求下一個視頻的一部分露出,與本方案不太符合,本方案更適合一個視頻占滿整個可視區(qū)域的使用場景,比如微視無限列表。

方案4:video 組件即用即毀,其余用 image 標(biāo)簽代替

從上面的分析可以得到,減少模塊加載時間和提高視頻切換性能的關(guān)鍵在于減少 video 組件實例數(shù),需要及時銷毀當(dāng)前沒有使用的 video 組件實例。因此,只渲染可視區(qū)域的 video 組件,其余用 image 標(biāo)簽代替,當(dāng) video 組件滑出可視區(qū)域后,及時銷毀該 video 組件實例。

關(guān)鍵代碼如下所示:

            class="topic-video"
            wx:if="{{ videoVid[index] && viewportList[index] }}"
            vid="{{ videoVid[index] }}"
            playerid="topic-video-{{ index }}"
            poster="{{ item.videoCover }}"
            bindplay="playVideo"
            bindpause="pauseVideo"
            muted="{{ true }}"
            showMuteBtn="{{ true }}"
            enableProgressGesture="{{ false }}"
            data-app="{{ item }}"
            bindtap="tapVideo"
            autoplay="{{ videoVid[index] }}"
            showFullscreenBtn="{{ false }}"
            showCenterPlayBtn="{{ false }}"
          >
          if="{{ !videoVid[index] || !viewportList[index] }}"
class="topic-video-image">
            "{{ item.videoCover }}" class="topic-video-cover">
image>
            <image
              src="../../images/ad-friend-watch/topic-video-play-btn.png"
              class="topic-video-play-btn"
              bind:tap="tapVideo"
            >image>
          view>

視頻切換效果如下所示:

可以看到,切換視頻時不存在卡頓現(xiàn)象,性能得到了明顯的提升。

本方案對 video 組件即用即毀,滑動到可視區(qū)域時才渲染組件,相比 video 組件實例復(fù)用,花費的時間會不會多很多呢?

從方案2中的分析可以得到,在 video 組件的 src 賦值前,僅創(chuàng)建了一個 DOM 節(jié)點,該步驟的時間花銷較小。在 video 組件的 src 賦值后,才“真正”渲染 video 組件。所以,對于切換到 src 沒有被賦值的 video 組件,本方案和 video 組件實例復(fù)用的時間花銷差不多。但是,對于視頻被播放過再切回該視頻的情況,因為該 video 組件已經(jīng)被銷毀,會再次經(jīng)歷渲染 video 組件、加載資源等操作,有一定的時間損耗和用戶流量的損耗??紤]到非wifi情況下不會自動播放視頻,視頻時長較短(15-30秒),且用戶來回滑的行為概率較小,相比明顯卡頓甚至卡死現(xiàn)象,還是更能讓人接受。

相關(guān)案例查看更多