知識
不管是網(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
一、背景
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 組件。
方案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)案例查看更多
相關(guān)閱讀
- 云南網(wǎng)站建設(shè)制作
- 云南網(wǎng)絡(luò)營銷
- 網(wǎng)站建設(shè)百度官方
- 網(wǎng)站建設(shè)靠譜公司
- 云南做百度小程序的公司
- 網(wǎng)站建設(shè)開發(fā)
- 汽車回收管理系統(tǒng)
- 模版消息
- 云南小程序設(shè)計
- 河南小程序制作
- 昆明小程序定制開發(fā)
- 云南軟件設(shè)計
- web開發(fā)
- 前端技術(shù)
- 北京小程序制作
- 網(wǎng)絡(luò)公司
- 昆明網(wǎng)站建設(shè)公司
- 昆明網(wǎng)站設(shè)計
- 開通微信小程序被騙
- 云南小程序開發(fā)公司
- 汽車報廢回收管理軟件
- 云南etc微信小程序
- vue開發(fā)小程序
- 跳轉(zhuǎn)小程序
- 云南小程序開發(fā)公司哪家好
- 小程序被攻擊
- 二叉樹
- 網(wǎng)站開發(fā)
- 云南網(wǎng)站建設(shè)哪家公司好
- 云南網(wǎng)站建設(shè)招商