阿里妹導讀:天貓雙十一已經成為被大眾普遍接受的文化符號,而貓晚則是連接線下線上的重要節點。2017年天貓晚會的前臺直播任務被交給了優酷來承擔。 優酷直播,優酷主客團隊,優酷架構組等多方組成了聯合項目組,合力承擔優酷雙十一貓晚直播的開發任務。?
雖然優酷直播在線上已經有業務穩定運行,但是我們還是遇到了大量問題需要解決。
除開直播晚會現場這個最重要的功能之外,晚會項目組還規劃了點贊/分享有禮,競猜,開寶箱,紅包雨等五花八門的互動玩法,需要在原有的Native直播間上增加大量的功能。
更加雪上加霜的是,晚會的招商并未結束,對直播會場的需求一直在變化。特別是直播會場換膚的需求可能導致會場的框架結構發生大幅度變化,用老的Native直播間應對這種需求變化比較困難。
所以我們決定用Weex重寫一個新的優酷直播間,全面還原當前的Native直播間的業務,同時添加對各種雙十一互動玩法的支撐。老的Naitve直播間僅僅作為降級的備用直播間。
在開始正式工作之前,我們的第一件事情是劃分功能模塊,確定哪些模塊用Weex sdk或者aliweex自帶的原生組件實現, 哪些模塊需要把現有的Native代碼封裝為一個Weex Component供Weex業務代碼引用。
上圖即為雙十一優酷直播間的最終形態,其大致的技術架構圖和功能如下圖所示。
經過評估,我們做出如下模塊劃分:
會場框架: 由Weex業務代碼搭建
回看列表tab: 是一個包含圖文的視頻列表,由Weex原生實現
聊天tab: 包含了大量聊天氣泡動效和復雜的業務邏輯,將原有的聊天室Native代碼封裝為Weex Component
圖文直播tab:包含了投放圖片,文字,視頻,商品鏈接等復雜的邏輯,將原有的Native代碼封裝為Weex Component
播放器組件:將原有的優酷直播播放器Native代碼封裝為Weex Component
點贊標簽: 這個組件被點擊或者收到服務端推送的互動消息時會飄出大量的動畫,我們的選擇是將原有的Native代碼封裝為Weex component
自定義Tab: 這個組件我們自行封裝了一個webview的Component,包含多種功能
1) 利用百川能力加載淘寶商品,實現邊看邊買 2) 加載互動h5頁面,實現紅包雨,競猜等功能 3) 加載阿里星球投放的H5頁面等
其余的跳轉,分享,監控埋點等功能模塊封裝為Weex Module供Weex業務代碼使用
在功能模塊拆分完畢之后,整個直播間已經完全成為組件化,模塊化的,可以隨意地組合,分解,定制。
無論未來的會場設計如何變化,只要編寫新的會場皮膚,根據需要嵌入各種自定義標簽,就能組合出需要的直播會場。
運營同學在優酷直播中臺的投放系統編輯主持人話題,換膚,紅包雨等互動消息后,具體的投放信息會被服務端填入互動玩法動態模板,通過PowerMsg通道下發到端上; 當端上收到此類互動消息之后,直接通過globalEvent發給Weex直播會場,會場解析收到的字段后,根據指令顯示主持人話題,拉起寶箱,紅包雨頁面等。
與一般情況下的Weex頁面降級到H5頁面不同,我們的降級邏輯是發生加載/跳轉/運行異常時,從Weex直播間跳轉到Native直播間; 所以我們沒有沿用Weex常見的降級邏輯,而是另外實現了一套downgrade邏輯。
在開發直播會場的過程中,我們遇到了tabbar框架和自定義Weex Component手勢沖突的問題。
我們希望上下滑動的手勢被當前tab接收,可以在當前列表中上下滑動
我們希望左右滑動的手勢被tabbar接收,可以在不同的tab之間切換
但是結合使用tabbar和自定義Weex Component,要么上下左右手勢全部被當前tab吃掉,導致無法在tab之間切換。要么上下左右手勢都被tabbar吃掉,導致當前tab無法上下滑動
上圖是Android View點擊事件分發的簡化邏輯
父View與子View同時可以滑動時就會產生滑動沖突, 常見套路的一種是在父View的onInterceptTouchEvent()做攔截:
public boolean onInterceptTouchEvent(MotionEvent event){
? ? boolean intercepted = false;
? ? switch(event.getActionMasked){
? ? ? ? case MotionEvent.ACTION_DOWN:
? ? ? ? ? ? intercepted = false;
? ? ? ? ? ? break;
? ? ? ? case MotionEvent.ACTION_MOVE:?
? ? ? ? ? ? if(父控件攔截){
? ? ? ? ? ? ? ? intercepted = true;
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? intercepted =false;
? ? ? ? ? ? }
? ? ? ? ? ? break;
? ? ? ? ...
? ? }
? ? ...
? ? return intercepted;
}
最后我們的解法是重寫了一個自定義Div標簽, 將自定義Weex Component嵌入自定義Div標簽中,自定義Div標簽吃掉上下滑動手勢并傳給自定義Weex Component,將左右滑動手勢拋出讓身為父View的tabbar處理,這樣就解決了這個手勢沖突問題。
然而,直播會場的Weex代碼使用了ExpressionBinding來優化滑動性能,新的解法導致ExpressionBinding失效了。
為了解決這個問題,我們又重寫了Weex的WXGesture手勢識別代碼,覆蓋掉WXComponent自帶的默認手勢識別代碼,使得ExpressionBinding重新生效。
ExpressionBinding的執行順序如下:
touchstart?->?panstart?->?ExpressionBinding panstart?->
ExpressionBinding panmove?->?ExpressionBinding panend?->?
touchend?->?panend
其核心概念是檢測出panstart事件,然后執行js層預先傳下來的“手勢處理邏輯”,而不是將識別出的手勢傳給js層處理。
我們對自定義Div標簽和自定義Weex Component的修改使得ExpressionBinding識別不到panstart事件了。所以我們重寫的WXGesture會在合適地方給自己所在的WXComponent發出:
WXGestureType.HighLevelGesture.HORIZONTALPAN
或者:
WXGestureType.HighLevelGesture.VERTICALPAN
事件,人為地觸發ExpressionBinding的識別代碼執行,最終使得ExpressionBinding可以與自定義Div標簽和自定義的Weex Component協同工作。
之前優酷直播頁面的轉屏是直接將Activity轉過來,然后讓視頻撐滿屏幕; 若要恢復豎屏則把Activity再轉回來,恢復vieoView為原始大小,讓其余的布局顯示出來。
由于新的Weex直播會場復雜度大大提高,切換橫豎屏的體驗變得很糟糕,每次切換之后畫面要黑屏一會兒才能把布局重新顯示出來。
經過多番嘗試,我們采用如下的解法來提高體驗:豎屏轉橫屏時,先記錄下videoView的各種布局參數,然后將videoView從它的父View中取出,直接attach到當前Window的decorView上。橫屏轉回豎屏時,將videoView從decorView中取出,add到舊的父View中,然后重設各種布局參數。
經過這個優化之后,轉屏體驗被大大提升了; 即使在幾年前的低端機器上,也能很快速地完成橫豎屏切換動作。
如圖所示,雙十一直播會場的直播視頻是嵌入到一個天貓電視機熒幕內的。實現方式是在自定義video標簽之上覆蓋一個天貓電視機圖片,使得視頻只從帶圓角的框中露出。?
這個實現方式在iOS端是沒問題的,在Android上卻失效了; 視頻和圖片的層級存在問題,在Android上視頻的四個邊角仍然會透出來,視覺上非常難看。
我們的解決辦法是給自定義播放器組件添加"borderRadius"屬性,將UED設計稿中的電視機圖片圓角值量出來,設置給自定義video標簽,把這個值透傳到Native層,經過750px轉換之后,將視頻VideoView在Native端直接切出合適的圓角。
最終,呈現出來的帶圓角視頻畫面與電視機圖片的圓角完美契合,看上去就像是一體的。
懶加載
Weex直播間是默認是豎屏的,但是也可以轉屏幕進入橫屏狀態。最開始進入Weex直播間時,舊邏輯是同時初始化豎屏下的布局和橫屏下的布局,耗時比較長。我們的修改是進入直播間時只初始化豎屏下需要的組件,將橫屏下需要的組件延遲加載,真正需要時才創建和初始化。
優化冗余布局
優化減少Layout層級,將設置Visibility為gone的冗余View全部刪除。
此外,Weex直播會場頁也做了大量的層級/View精簡的動作,兩者結合起來最終使得加載體驗有了很大的提高。
飄贊動畫優化
直播間的點贊圖標是一個Native封裝的Weex Component,當用戶手動點擊或者收到其他用戶的點贊推送時,點在圖標會飄出若干個紅心或者服務端下發的其他圖片。
粗略一看點贊功能實現的沒有什么問題,但是在晚會預演的高并發條件下問題就暴露出來了,由于用戶量太大,點贊推送消息太多,Android端的點贊動畫會變得非常卡頓。
我們的解決辦法是做了一個Orange開關,在較低性能的機器上減少或者屏蔽飄贊動畫;收到點贊消息推送后,不再立即飄出點贊動畫,而是點贊數大于某個閾值,或者大于某個時間間隔才飄出動畫,減少端上的渲染壓力。
此外,我們注意到飄贊動畫是飄出顯示區域之后直接銷毀,需要飄出新動畫時再創建新的圖片,我們有考慮引入對象池的技術預先分配一些動畫幀并復用,但是由于時間關系未能發布到線上。
1?zcache將Weex bundle JS,圖片等靜態資源通過zcache推送到客戶端上。
(1) 減輕了貓晚當天,客戶端請求服務端拉取資源的壓力
(2)由于待請求的資源就在本地,大大提高了頁面渲染的速度
(3) 提高了頁面加載成功率
2?請求合并由于某些mtop接口功能龐雜,Weex和Native代碼都要請求,且調用時序無法確定。我們封裝了一個Mtop Weex module,兼顧mtop請求和DataPool的功能,Weex和Native代碼都通過這個module來發出mtop請求;當某個請求發出之后,短期內對同一個接口的重復請求會被緩存; 第一個請求數據返回之后,結果會通知給所有被緩存的mtop請求方。通過這個小小的優化,我們將服務端QPS壓力降低了十多萬。
3?貓晚當天,只請求最低限度的服務端接口,不再請求諸如“直播間預告訂閱”之類的非必要接口。
最終,優酷的雙11直播取得較好的成績:
1.助力天貓雙11,引導點擊用戶655萬。
2.貓晚直播同時在線達209萬。
我們在直播會場的關鍵路徑和優酷直播播放器均加上了埋點信息, 根據統計信息:
以雙十一直播會場為基礎,依據老的標準直播間樣式重寫了一份皮膚之后,Weex直播間已經在優酷直播業務中全量上線,老的Native直播間已經下線。我們為雙十一Weex直播間開發的各種互動玩法已經落地為優酷直播的常態化運營手段。
此次雙十一貓晚直播是優酷歷史上采用Weex承接的規模最大的項目,也是阿里歷史上直播在線人數最高的項目。在各部門的通力合作之下,整個晚會的直播任務運行平穩,沒有出現任何意外情況。
在當前的雙十一直播會場成果基礎上,Weex直播間不僅承擔了目前線上全部的優酷直播業務,還會承擔即將到來的跨年晚會,春節聯歡晚會的直播任務,直播團隊還將推出更多酷炫的互動玩法,更加流暢的直播加載體驗,敬請期待。
你可能還喜歡
關注「阿里技術」
把握前沿技術脈搏
評論
查看更多