ZLMediaKit獨(dú)家特性介紹

1欧芽、先播放后推流

  • 痛點(diǎn):推流成功前不能提前播放

  • 場(chǎng)景介紹:

    有些及時(shí)推流的場(chǎng)景莉掂,存在推流和播放同時(shí)發(fā)生的場(chǎng)景,這種場(chǎng)景一般是一對(duì)一的千扔,譬如說基于rtmp推流的行車記錄儀憎妙,用戶在調(diào)閱車載攝像頭視頻的,下發(fā)推流命令給設(shè)備時(shí)昏鹃,同時(shí)開始播放視頻,如果播放請(qǐng)求先于推流到達(dá)流媒體服務(wù)器诀诊,那么流媒體服務(wù)器通常會(huì)立即返回流未找到的錯(cuò)誤洞渤,為了解決這個(gè)問題,一般的解決方案是属瓣,通過設(shè)備確認(rèn)推流成功再開啟播放载迄,但是這樣往往會(huì)增加視頻打開延時(shí),拉低用戶體驗(yàn)抡蛙。zlmediakit針對(duì)此場(chǎng)景作出特別優(yōu)化护昧,可以在流不存在時(shí),先不回復(fù)播放器粗截,等推流成功后再返回播放成功惋耙,如果超時(shí)時(shí)間內(nèi),推流還不上線,那么再返回播放流不存在錯(cuò)誤绽榛,通過配置文件可以修改此延時(shí):

    [general]
    #播放最多等待時(shí)間湿酸,單位毫秒
    #播放在播放某個(gè)流時(shí),如果該流不存在灭美,
    #ZLMediaKit會(huì)最多讓播放器等待maxStreamWaitMS毫秒
    #如果在這個(gè)時(shí)間內(nèi)推溃,該流注冊(cè)成功,那么會(huì)立即返回播放器播放成功
    #否則返回播放器未找到該流届腐,該機(jī)制的目的是可以先播放再推流
    maxStreamWaitMS=15000
    

    提示: 此功能同樣適用于拉流铁坎,通過該功能可以實(shí)現(xiàn)按需推拉流。

2犁苏、無人觀看事件

  • 痛點(diǎn): 推流無人觀看時(shí)白白浪費(fèi)流量

  • 場(chǎng)景介紹:

    在一些物聯(lián)網(wǎng)應(yīng)用場(chǎng)景硬萍,設(shè)備推流給服務(wù)端,用戶通過app查看設(shè)備視頻傀顾,當(dāng)用戶關(guān)閉app時(shí)襟铭,設(shè)備應(yīng)該停止推流以節(jié)省流量。為了實(shí)現(xiàn)該功能短曾,一般的解決方案是播放端通過發(fā)送心跳維持設(shè)備推流寒砖,但是這樣往往存在狀態(tài)的不確定性,以及增加系統(tǒng)復(fù)雜度(想想app嫉拐、web哩都、小程序端同時(shí)維持推流心跳的場(chǎng)景)。針對(duì)此種場(chǎng)景婉徘,zlmediakit提供播放用戶統(tǒng)計(jì)功能漠嵌,在觀看數(shù)為0時(shí)會(huì)觸發(fā)無人觀看事件,用戶通過接收zlmediakit的 hook(http請(qǐng)求)盖呼,可以返回是否讓zlmediakit關(guān)閉該推流(或拉流)儒鹿,hook地址配置文件為:

    [hook]
    #是否啟用hook事件,啟用后几晤,推拉流都將進(jìn)行鑒權(quán)
    enable=1
    #無人觀看流事件约炎,通過該事件,可以選擇是否關(guān)閉無人觀看的流蟹瘾。配合general.streamNoneReaderDelayMS選項(xiàng)一起使用
    on_stream_none_reader=https://127.0.0.1/index/hook/on_stream_none_reader
    

    提示: hook介紹地址

3圾浅、流未找到事件

  • 痛點(diǎn): 我們只需對(duì)外提供播放url,而不是其他憾朴!

  • 場(chǎng)景介紹:

    通常而言狸捕,我們通過播放url來分發(fā)視頻內(nèi)容,但是這些視頻內(nèi)容是及時(shí)生成的众雷,在無人播放時(shí)灸拍,它并不存在(不存在推流或拉流代理)做祝。這種場(chǎng)景下,通常的做法是用戶需要限制客戶端株搔,因?yàn)樘峁┑牟皇遣シ舥rl剖淀,而是獲取url的api,用戶先獲取播放url用于觸發(fā)設(shè)備推流纤房,然后才能播放纵隔,這種方式通常而言比較繁瑣,需要特定的播放前邏輯炮姨,限制了一些應(yīng)用場(chǎng)景捌刮。zlmediakit提供流未找到事件,可以匯報(bào)給你的業(yè)務(wù)服務(wù)器舒岸,告知流不存在绅作,這個(gè)時(shí)候,你可以再從容控制設(shè)備開始推流蛾派,或者讓zlmediakit開始拉流代理俄认,hook地址配置文件為:

    [hook]
    #是否啟用hook事件,啟用后洪乍,推拉流都將進(jìn)行鑒權(quán)
    enable=1
    #播放時(shí)眯杏,未找到流事件,通過配合hook.on_stream_none_reader事件可以完成按需拉流
    on_stream_not_found=https://127.0.0.1/index/hook/on_stream_not_found
    

    提示: hook介紹地址

4壳澳、斷連續(xù)推

  • 痛點(diǎn):推流斷開岂贩,推流器重連了,導(dǎo)致播放器都全部斷開了巷波!

  • 場(chǎng)景介紹:

    一般推流器斷開萎津,服務(wù)器處理播放器的邏輯有這幾種,一種是立即斷開所有播放這個(gè)流的播放器抹镊,同時(shí)銷毀推流器锉屈、播放器對(duì)象以便節(jié)省資源,這也是zlmediakit的默認(rèn)做法垮耳。另外一種是以srs為代表颈渊,推流器斷開后,基本什么也不做氨菇,不回收推流器開辟的資源儡炼,也不斷開播放器(而是讓播放器主動(dòng)超時(shí)斷開)妓湘。

    srs這種處理方式有個(gè)好處查蓉,就是推流器重新推流后,播放器可以接著播放榜贴,用戶體驗(yàn)比較好豌研。壞處就是資源不能及時(shí)回收妹田,如果有惡意鏈接不主動(dòng)及時(shí)超時(shí)斷開,可能會(huì)消耗服務(wù)器大量的文件描述符資源鹃共,同時(shí)由于推流器創(chuàng)建的媒體源資源無法主動(dòng)釋放鬼佣,當(dāng)創(chuàng)建很多個(gè)推流時(shí),內(nèi)存占用不能及時(shí)降低霜浴。

    zlmediakit現(xiàn)在針對(duì)這種場(chǎng)景晶衷,新增支持?jǐn)噙B續(xù)推功能,解決了推流重連導(dǎo)致播放器斷開的問題阴孟,也解決了資源無法及時(shí)回收的弊端晌纫,做法是,在推流器斷開時(shí)永丝,延時(shí)銷毀媒體源資源對(duì)象(同時(shí)延時(shí)斷開播放器)锹漱,當(dāng)推流器再次推流時(shí),復(fù)用該資源對(duì)象慕嚷,播放器可以接著觀看視頻哥牍;如果超時(shí)后,推流器未上線喝检,那么再斷開播放器并回收所有資源嗅辣。超時(shí)延時(shí)配置文件為:

    [general]
    #推流斷開后可以在超時(shí)時(shí)間內(nèi)重新連接上繼續(xù)推流,這樣播放器會(huì)接著播放蛇耀。
    #置0關(guān)閉此特性(推流斷開會(huì)導(dǎo)致立即斷開播放器)
    #此參數(shù)不應(yīng)大于播放器超時(shí)時(shí)間
    continue_push_ms=15000
    
  • 實(shí)現(xiàn)代碼片段:

    void RtmpSession::onError(const SockException& err) {
        //省略無關(guān)代碼
    
        GET_CONFIG(uint32_t, continue_push_ms, General::kContinuePushMS);
        if (_push_src && continue_push_ms) {
            //取消推流對(duì)象所有權(quán)
            _push_src_ownership = nullptr;
            auto push_src = std::move(_push_src);
            //延時(shí)若干秒再銷毀對(duì)象(注銷流, 同時(shí)觸發(fā)斷開所有播放器操作)
            getPoller()->doDelayTask(continue_push_ms, [push_src]() { return 0; });
        }
    }
    
    void RtmpSession::onCmd_publish(AMFDecoder &dec) {
      //省略大量無關(guān)代碼
      auto src = MediaSource::find(RTMP_SCHEMA, _media_info._vhost, _media_info._app, _media_info._streamid);
    
      while (src) {
        //嘗試斷連后繼續(xù)推流
        auto rtmp_src = dynamic_pointer_cast<RtmpMediaSourceImp>(src);
        if (!rtmp_src) {
          //源不是rtmp推流產(chǎn)生的
          break;
        }
        auto ownership = rtmp_src->getOwnership();
        if (!ownership) {
          //獲取推流源所有權(quán)失敗
          break;
        }
        //復(fù)用之前推流資源對(duì)象
        _push_src = std::move(rtmp_src);
        //持有對(duì)象所有權(quán)
        _push_src_ownership = std::move(ownership);
        break;
      }
      //省略大量無關(guān)代碼
    }
    

    提示:斷連續(xù)推功能支持rtsp/rtmp/webrtc推流辩诞。

5、集群部署

  • 痛點(diǎn): 溯源方式單一纺涤,邊沿服務(wù)器不能使用HLS译暂。

  • 場(chǎng)景介紹:

    一般流媒體集群實(shí)現(xiàn)方式采用溯源方式實(shí)現(xiàn),服務(wù)器分為源站和邊沿站撩炊。源站一般用于接收推流外永,它一般不直接承載用戶的播放請(qǐng)求,而是通過邊沿服務(wù)器向其拉流同時(shí)分發(fā)給播放器拧咳,通過該模式可以支持海量的用戶播放請(qǐng)求伯顶。srs很早之前已經(jīng)通過配置文件的方式支持該功能,由于zlmediakit比較早也提供按需拉流的功能骆膝,本質(zhì)上也支持溯源模式的集群祭衩,不過用戶需要對(duì)接hook和api,開發(fā)門檻比較高阅签,所以最近zlmediakit也支持了通過配置文件的方式來實(shí)現(xiàn)集群模式掐暮,配置文件如下:

    [cluster]
    #設(shè)置源站拉流url模板, 格式跟printf類似,第一個(gè)%s指定app,第二個(gè)%s指定stream_id,
    #開啟集群模式后政钟,on_stream_not_found和on_stream_none_reader hook將無效.
    #溯源模式支持以下類型:
    #rtmp方式: rtmp://127.0.0.1:1935/%s/%s
    #rtsp方式: rtsp://127.0.0.1:554/%s/%s
    #hls方式: http://127.0.0.1:80/%s/%s/hls.m3u8
    #http-ts方式: http://127.0.0.1:80/%s/%s.live.ts
    #支持多個(gè)源站路克,不同源站通過分號(hào)(;)分隔
    origin_url=
    #溯源總超時(shí)時(shí)長(zhǎng)樟结,單位秒,float型精算;假如源站有3個(gè)瓢宦,那么單次溯源超時(shí)時(shí)間為timeout_sec除以3
    #單次溯源超時(shí)時(shí)間不要超過general.maxStreamWaitMS配置
    timeout_sec=15
    

    zlmediakit的溯源方式支持rtsp/rtmp/hls/http-ts(http-flv的方式暫未開放), 方式多樣豐富灰羽,同時(shí)源站不分主備驮履,采用round robin方式來實(shí)現(xiàn)源站的負(fù)載均衡。需要指出的是廉嚼,由于zlmediakit很早就支持hls的按需拉流功能疲吸,所以zlmediakit的邊沿站也支持hls協(xié)議(其實(shí)支持zlmediakit任意支持的協(xié)議),這點(diǎn)是srs不具備的前鹅。

    另外需要指出的是摘悴,由于zlmediakit同時(shí)支持rtsp和webrtc,而它們兩者都是基于rtp的舰绘,在zlmediakit內(nèi)部蹂喻,無須轉(zhuǎn)協(xié)議簡(jiǎn)單處理后就可互聯(lián)互通,所以使用zlmediakit來做大規(guī)模的webrtc低延時(shí)直播已經(jīng)成為可能捂寿;相較于傳統(tǒng)的基于rtmp的cdn口四,rtsp更適合作為webrtc的cdn基礎(chǔ)傳輸協(xié)議,開發(fā)者不需要處理繁瑣的解復(fù)用復(fù)用邏輯秦陋,即可平滑的實(shí)現(xiàn)rtsp與webrtc的互轉(zhuǎn)蔓彩。

6、WebRTC單端口驳概、多線程赤嚼、支持連接遷移

  • 痛點(diǎn):支持多線程的webrtc服務(wù)器不支持單端口,支持單端口的不支持多線程(同時(shí)可能不支持鏈接遷移)

  • 場(chǎng)景介紹:

    由于webrtc傳輸是基于udp協(xié)議的顺又,傳統(tǒng)的webrtc服務(wù)器都是多端口模式更卒,譬如janus/mediasoup。這給部署和管理帶來極大痛苦,而且由于端口個(gè)數(shù)有限(理論上限6萬多)稚照,每個(gè)webrtc客戶端要占用1至4個(gè)端口蹂空,受限于端口數(shù)量,一臺(tái)webrtc服務(wù)器最多可以承載1~6萬左右的客戶端數(shù)果录。

    而支持單端口的webrtc服務(wù)器(譬如srs)上枕,又不支持多線程;由于webrtc計(jì)算復(fù)雜度(加解密)遠(yuǎn)大于直播弱恒,其性能跟直播比有數(shù)量級(jí)的差距辨萍,所以往往單線程在webrtc的應(yīng)用場(chǎng)景已經(jīng)力不從心。

    zlmediakit針對(duì)這些痛點(diǎn)斤彼,提出了最佳解決方案:

    • 支持單udp端口部署分瘦,一個(gè)udp端口承載所有客戶端。
    • 單udp端口支持多線程琉苇,單端口多次bind/connect方式實(shí)現(xiàn)一個(gè)客戶端對(duì)應(yīng)一個(gè)fd嘲玫,fd均勻分配到不同線程。
    • 用戶網(wǎng)絡(luò)遷移時(shí)(譬如wifi切換為4G)并扇,通過stun包鎖定用戶去团,實(shí)現(xiàn)無感知的連接遷移,用戶體驗(yàn)不中斷穷蛹。

    以上3個(gè)特性都同時(shí)具備的土陪,目前在開源界唯zlmediakit一家。

    提示: 關(guān)于怎么解決webrtc單端口連接遷移和多線程連接遷移時(shí)線程安全問題的請(qǐng)觀看該視頻

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末肴熏,一起剝皮案震驚了整個(gè)濱河市鬼雀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蛙吏,老刑警劉巖源哩,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異鸦做,居然都是意外死亡励烦,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門泼诱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來座哩,“玉大人狰晚,你說我怎么就攤上這事。” “怎么了康栈?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)析藕。 經(jīng)常有香客問我慷垮,道長(zhǎng),這世上最難降的妖魔是什么句灌? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任夷陋,我火速辦了婚禮,結(jié)果婚禮上胰锌,老公的妹妹穿的比我還像新娘骗绕。我一直安慰自己,他們只是感情好资昧,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布酬土。 她就那樣靜靜地躺著,像睡著了一般格带。 火紅的嫁衣襯著肌膚如雪撤缴。 梳的紋絲不亂的頭發(fā)上刹枉,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音屈呕,去河邊找鬼微宝。 笑死,一個(gè)胖子當(dāng)著我的面吹牛虎眨,可吹牛的內(nèi)容都是我干的蟋软。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼嗽桩,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼岳守!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起碌冶,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤湿痢,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后扑庞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蒙袍,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年嫩挤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了害幅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡岂昭,死狀恐怖以现,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情约啊,我是刑警寧澤邑遏,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站恰矩,受9級(jí)特大地震影響记盒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜外傅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一纪吮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧萎胰,春花似錦碾盟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春熙尉,著一層夾襖步出監(jiān)牢的瞬間联逻,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來泰國打工检痰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留包归,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓攀细,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親爱态。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谭贪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348