直播技術(shù)(二) —— 直播間的上下切換(一)

版本記錄

版本號(hào) 時(shí)間
V1.0 2018.07.30

前言

最近在兩家公司任職做的都是直播相關(guān)的業(yè)務(wù),音視頻的門檻現(xiàn)在是越來越低,很多的三方視頻云等都支持直播相關(guān)的業(yè)務(wù),從推流拉流到美顏、濾鏡、貼紙甚至人體識(shí)別等都有很多的第三方公司支持。但是,好一點(diǎn)的公司還是自己研發(fā)自己的視頻云SDK,這樣可以不受三方束縛,定制性也更好些,相信看過我寫過的文章的人,發(fā)現(xiàn)了我寫過和直播相關(guān)的技術(shù),這里我另起一個(gè)模塊和大家繼續(xù)分享直播相關(guān)技術(shù),感興趣的就給個(gè)贊支持一下。感興趣看上面幾篇文章。
1. 直播技術(shù)(一) —— 移動(dòng)直播連麥幾種處理方案(一)

設(shè)計(jì)初衷

大家要明白一點(diǎn),那就是為什么要在直播間里面實(shí)現(xiàn)上下切換?首先,和大家說一下,這個(gè)不是產(chǎn)品設(shè)計(jì)的必選項(xiàng),但是一定是一個(gè)拉分項(xiàng),為什么這么說?因?yàn)楫?dāng)我們不能上下切換直播間的時(shí)候,那我們?cè)趺床僮鳎瑹o非就是點(diǎn)擊X按鈕退出直播間,在Feed流列表里面繼續(xù)找想看的主播然后再進(jìn)去,時(shí)間久了這樣的操作就很繁瑣了。

這個(gè)設(shè)計(jì)不是腦袋發(fā)熱自己瞎想的,有很多主流直播APP都能在直播間內(nèi)切換主播(上下或者左右切換直播間),比如花椒和抖音都是上下切換直播間。如下所示。

抖音短視頻主頁(yè)
花椒Feed流頁(yè)面
花椒直播間

設(shè)計(jì)實(shí)現(xiàn)

1. 視圖層次問題

首先要面對(duì)的問題就是視圖層次的問題,我們本來的播放器的根View上有一個(gè)視頻層,視頻層上面是一個(gè)禮物渲染層,在往上是其他幾個(gè)視圖,比如H5活動(dòng)視圖,上面是操作層容器視圖,在操作層容器視圖中是分享、關(guān)閉、送禮還有公屏等其他操作。

但是要加上直播間上下切換視圖,那么就需要添加滾動(dòng)控件,滾動(dòng)的控件scrollView、UITableView、UICollectionView等都可以滿足需求,但是從集成容易度等幾個(gè)方面考慮,UICollectionView都是最佳的選項(xiàng)。

控件選好了,那么應(yīng)該放在哪個(gè)層次上呢?這個(gè)就和產(chǎn)品業(yè)務(wù)需求相關(guān)了。這里給大家提供兩個(gè)方法供大家選擇。

  • 另外實(shí)例化一個(gè)VC,在這個(gè)VC中放一個(gè)collectionview,然后將直播間的控制器VC添加掉這個(gè)collectionview的cell上,讓cell持有一個(gè)播放器,這樣滾動(dòng)cell就切換了直播間。但是這個(gè)在實(shí)踐上有問題,那就是cell復(fù)用帶來的,cell復(fù)用會(huì)實(shí)例化三個(gè)播放器實(shí)例,在這三個(gè)播放器實(shí)例中循環(huán)復(fù)用,所以有點(diǎn)卡頓,效果不是很好。

  • 就用一個(gè)播放器VC,在插入一個(gè)自定義view放在index=1的位置,這樣除了根view,它就是在最底層的,然后在這個(gè)自定義view上放一個(gè)collectionview,并將直播間的容器視圖add到collectionview的cell上,這樣也可實(shí)現(xiàn)滾動(dòng)。這個(gè)是經(jīng)過實(shí)踐證明可行的。

  • 還有一個(gè)方法也是實(shí)例化一個(gè)VC,在這個(gè)VC中放一個(gè)collectionview,讓這個(gè)VC持有一個(gè)播放器對(duì)象,這樣我們?cè)诨綄?duì)應(yīng)的cell的時(shí)候,可以只用這一個(gè)播放器,那樣,如果是第一個(gè)就實(shí)例化播放器并拉流,然后在滾動(dòng)collectionview的時(shí)候找到對(duì)應(yīng)的cell并將播放器根視圖添加到cell上,停止上一個(gè)cell播放的內(nèi)容并重新給播放器地址重新拉流。這個(gè)是我們采取的技術(shù)方案。

以上只是初步的視圖層次的方案,其實(shí)還有很多數(shù)據(jù)源以及播放器等很多初始化的問題,下面我們繼續(xù)。

2. 數(shù)據(jù)源問題

這里就看產(chǎn)品的需求了,是可以“無限”滾動(dòng),即使是第一個(gè)cell也可以向上滾動(dòng)還是到第一個(gè)cell就不用滾動(dòng)了,這個(gè)和產(chǎn)品需求相關(guān)了。

我們一般常見的情況就是如果數(shù)據(jù)源只有一個(gè),那么就不要滾動(dòng)了,如果數(shù)據(jù)源中對(duì)象個(gè)數(shù)大于1,那么就可以無限滾動(dòng),假如是index = 0的直播間向上滾動(dòng)可以直接滾動(dòng)到index = count - 1的直播間,這個(gè)如何實(shí)現(xiàn)呢?其實(shí)最簡(jiǎn)單的一個(gè)方法就是collectionView的數(shù)據(jù)源item的個(gè)數(shù)設(shè)置一個(gè)很大的數(shù)目,比如說10000個(gè),然后將當(dāng)前的直播間cell置于5000個(gè)的位置,那么就可以上下5000個(gè)滾動(dòng)了,近似無限上下切換。

這里,還有個(gè)問題,就是直接用那個(gè)數(shù)組在直播間內(nèi)進(jìn)行切換,那么是否需要下拉下一頁(yè)數(shù)據(jù)呢?這個(gè)是要看產(chǎn)品需求的,如果第一頁(yè)數(shù)據(jù)拉的很多的話,比如100個(gè)數(shù)據(jù),那么其實(shí)可以不用下拉下一頁(yè)數(shù)據(jù),很少有人一刷上下切換100個(gè)直播間的。這個(gè)是可選項(xiàng)不是必選項(xiàng),具體依項(xiàng)目而定。

3. 播放器問題

由于VC持有了播放器,那么滾動(dòng)cell的時(shí)候就需要重新給url進(jìn)行拉流和播放,這樣就可以保證進(jìn)入直播間后只需要實(shí)例化一次播放器,當(dāng)上下切換的時(shí)候可以直接給播放器一個(gè)新的Feed流重新拉流即可。

4. 消息問題

由于不同直播間的消息是不同的,所以快速滑動(dòng)直播間進(jìn)行切換的時(shí)候,其實(shí)很容易竄消息,這個(gè)應(yīng)該如何處理呢?

其實(shí),在我們切換直播間的時(shí)候,對(duì)于消息首先要做的就是將VC持有的消息數(shù)據(jù)清空。這樣切換到另一個(gè)直播間后就不會(huì)引起消息的混亂和竄直播間。

其實(shí)有一個(gè)終極大招,那就是直播間消息返回roomId,這樣我們切換直播間就可以用消息返回的roomId和當(dāng)前Feed數(shù)據(jù)帶的roomId進(jìn)行比較是一個(gè)就使用,不是一個(gè)就扔掉。

5. 接口問題

這個(gè)也是需要考慮的一個(gè)點(diǎn),前面說過我們控制器VC只實(shí)例化一次播放器,切換到別的直播間只更換Feed流并不重新實(shí)例化,那么這里就有一個(gè)問題,如果切換到下一個(gè)直播間,那么我們上一個(gè)直播間的進(jìn)入房間拉取的一些接口才返回我們應(yīng)該怎么辦?

這個(gè)是很大的問題,因?yàn)槲覀儼l(fā)送出請(qǐng)求后,具體什么時(shí)候回來就不是我們控制的了,極大的概率就是我們都已經(jīng)切換到下一個(gè)直播間了,但是上一個(gè)直播間接口數(shù)據(jù)才返回。

這個(gè)有下面幾個(gè)方案,可以選擇:

  • 可以每切換一個(gè)直播間都重新實(shí)例化一個(gè)對(duì)象去請(qǐng)求,這樣我們就算上一個(gè)直播間的請(qǐng)求結(jié)果在切換直播間后才返回我們就不用介意了,因?yàn)樗梢苑祷?,但是我們可以不用,只需要在新的直播間重新實(shí)例化一個(gè)干凈的對(duì)象去重新請(qǐng)求即可,這個(gè)是我們Android端的方案。

  • 很多時(shí)候由于我們是復(fù)用的播放器對(duì)象,有時(shí)候請(qǐng)求寫的還是單例,不能重新實(shí)例化去請(qǐng)求數(shù)據(jù)。這樣我們可以這么做那就是每一個(gè)請(qǐng)求都給個(gè)標(biāo)記identify,在返回結(jié)果的地方,如果該task的任務(wù)和標(biāo)記的是同一個(gè)那么就說明是我們這個(gè)直播間想要的請(qǐng)求,如果不是一個(gè)就說明可能是上一個(gè)直播間的請(qǐng)求才回來,我們直接舍棄即可。

另外,一個(gè)方案可以參考消息帶roomId的機(jī)制,這個(gè)用于判斷直播間是最好的。

6. 手勢(shì)問題

這個(gè)也是需要處理的問題,由于我選擇了collectionviewCell嵌套播放器VC的這種設(shè)計(jì),所以設(shè)計(jì)到很多手勢(shì)的交互。比如說:公屏信息是大家聊天的地方,有時(shí)候我們喜歡看歷史消息,這個(gè)時(shí)候就要注意了,不能滑動(dòng)公屏這個(gè)tableview讓后面的collectionview發(fā)生滾動(dòng)。但是,很不幸的是這個(gè)問題是存在的,當(dāng)我們將tableview一直拖動(dòng)到底部的時(shí)候,系統(tǒng)就會(huì)將手勢(shì)傳遞給后面的視圖進(jìn)行響應(yīng),這就引起了后面的collectionview發(fā)生了滾動(dòng)切換,很明顯這個(gè)不是我們希望的。

同樣,禮物面板、關(guān)注面板、私聊面板以及其他視圖等都需要處理。不能讓他們也跟著滾到別的播放器里面。

這里一個(gè)可行方案就是自定義collectionview并重寫其hitTest方法,判斷下一個(gè)響應(yīng)者,如果是上面涉及到的那幾個(gè)控件,那么就將collectionview的滾動(dòng)enabled = NO,后面的collectionview就不會(huì)滾動(dòng)了,這樣點(diǎn)擊或者拖動(dòng)其他地方都可以切換直播間,操作上面那幾個(gè)視圖就沒問題了。

類似的代碼如下所示:

// JJSwitchCollectionView就是自定義的負(fù)責(zé)滾動(dòng)的視圖,繼承自UICollectionView
@implementation JJSwitchCollectionView

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    BOOL canBeScrolled = YES;
    UIView *view = [super hitTest:point withEvent:event];
    UIResponder *debugResponder = (UIResponder *)[super hitTest:point withEvent:event];
    // JJPlayingSwitchCell就是JJSwitchCollectionView的cell
    while (debugResponder != nil && ![debugResponder.nextResponder isKindOfClass:[JJPlayingSwitchCell class]]) {
        // 這里JJChatTableView就是公屏的tableView
        if ([debugResponder isKindOfClass:[JJChatTableView class]]) {
            canBeScrolled = NO;
            break;
        }
        debugResponder = debugResponder.nextResponder;
    }
    self.scrollEnabled = canBeScrolled;
    return view;
}

@end

7. 禮物渲染問題

這個(gè)需要注意我們渲染大禮物時(shí)間比較長(zhǎng)或者有人連續(xù)送小禮物的時(shí)候,這樣切換直播間的之后就會(huì)將渲染的禮物帶到下一個(gè)直播間內(nèi)部。

對(duì)于這種情況我們需要:

  • 清空待渲染的數(shù)組對(duì)象。
  • 將當(dāng)前正在渲染的圖層都停掉并移除。

后記

本篇主要就講述了切換直播間的一些設(shè)計(jì)及問題的解決,感興趣的給個(gè)贊或者關(guān)注~~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容