日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務,提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

作者:vivo 互聯(lián)網(wǎng)服務器團隊-Li Guolin

一、前言

隨著5G時代的到來,音視頻行業(yè)也可能迎來一個行業(yè)的春天,直播則是新視頻行業(yè)一直以來的一個重要的產品形態(tài),從最初的秀場直播,游戲直播,到今年由于疫情,目前比較火的在線教育直播,帶貨直播等,各類新的直播形式則是越來越多的展示在大眾面前。

作為技術開發(fā)的我們,今天我們一起簡單的了解一下,如何快速搭建一套最簡單的直播系統(tǒng),簡單地了解一下主流直播的架構模型。

二、推拉流模型

首先我們先看一張完整的直播推拉流的模型圖,我們可以很清楚地看到直播宏觀上的架構模型圖

玩轉直播:如何從 0 到 1 構建簡單直播系統(tǒng)

2.1 直播三個主要模塊

推流模塊

推流模塊主要分為音視頻數(shù)據(jù)的采集,如果是秀場類直播,可以做美顏濾鏡相關功能,用來提升直播的畫面品質和用戶體驗,最后通過編碼壓縮,降低音視頻數(shù)據(jù)的體積,最后通過流媒體傳輸協(xié)議將數(shù)據(jù)按照固定格式傳遞到RTMP服務器,這樣整個推流端的工作就完成了。

RTMP服務端模塊

傳統(tǒng)意義上的RTMP服務器其實可能就只有轉碼的功能,將推流端傳遞過來的數(shù)據(jù),轉成flv等網(wǎng)絡格式的數(shù)據(jù)文件,方便播放端的觀看,不過目前云商都提供了一整套的解決方案,例如清晰度轉碼,內容健康檢查,直播封面的生成,數(shù)據(jù)統(tǒng)計,錄制回放等功能,這也是在RTMP服務器的基礎上,進行的業(yè)務封裝,這樣才能提供一整套的解決方案。

播放端模塊

播放端的邏輯就相對比較簡單,簡而言之就是獲取拉流地址,進行音視頻的播放,不過在實際開發(fā)的過程中,播放端的業(yè)務工作量和技術優(yōu)化點都是最多的,如上圖所示的首屏秒開,解碼優(yōu)化,切換直播間等功能,都是需要花費大量的精力,根據(jù)業(yè)務不斷地去演進優(yōu)化的。

三、搭建步驟

本入門直播簡單教程主要分為如下幾個模塊

搭建直播服務器

使用OBS進行推流

直播流如何觀看

直播間消息的實現(xiàn)

3.1 搭建直播服務器

直播服務器實時地將推流端上傳的視頻流進行解析和編解碼,以用于支持rtmp、hls或httpflv等直播協(xié)議的觀看端進行觀看。

玩轉直播:如何從 0 到 1 構建簡單直播系統(tǒng)

當前市面上有很多開源的直播服務器解決方案,如 livego、srs 和 Nginx-rtmp ,亦或者是目前比較主流的云解決方案,目前阿里云,七牛云,騰訊云等都提供了標準的成熟的解決方案,本篇文章旨在快速地搭建一個簡單的直播,所以我們可以采用livego這個開放源代碼的方式去搭建推拉流服務器,livego 使用純 go 語言編寫,性能高且跨平臺,安裝和使用非常簡單,支持常用的傳輸協(xié)議、文件格式和編碼格式,或者安裝上文所示,直接在云商開播直播服務。

安裝 livego 主要有三種方式:1)直接下載二進制可運行文件;2)從Docker啟動;3)從源碼編譯。


 

docker run -p 1935:1935 -p 7001:7001 -p 7002:7002 -p 8090:8090 -d gwuhaolin/livego

其中,各個端口的含義如下:

8090:HTTP 管理訪問監(jiān)聽地址

1935:RTMP 服務監(jiān)聽地址

7001:HTTP-FLV 服務監(jiān)聽地址

7002:HLS 服務監(jiān)聽地址

3.2 使用OBS推流

OBS(Open Broadcaster Software)是一款開源免費的提供視頻錄制和直播功能的軟件,去OBS官網(wǎng)下載對應平臺的軟件進行安裝即可。

要想推流,首先要解決的是“推什么”的問題,也就是要明確流的來源。打開OBS,點擊新建“來源”按鈕,如下圖中第1步所示,可以看到OBS支持的來源比較豐富,有媒體源、顯示器采集、瀏覽器和窗口采集等等。此處用現(xiàn)有的mp4文件來進行循環(huán)推流,因此來源選擇“媒體源”,名稱用默認的就行,點擊“確定”后,設置要播放的視頻文件,然后點擊“確定”即可。

玩轉直播:如何從 0 到 1 構建簡單直播系統(tǒng)

然后,要解決的就是“往哪推”的問題,也就是需要有一個可用的推流地址才行。

前面我們已經搭建好了livego直播服務器,它提供了一個默認推流地址:
rtmp://localhost:1935/live,一個標準的RTMP服務器的推流URL類似這種格式:rtmp://domain/AppName/StreamName,但是要想使用該推流地址,需要有授權的 channelkey 才行。

通過訪問
http://localhost:8090/control/get?room=movie 就可以獲取用于推流的 channelkey,如下所示,其中 data 字段就是此次獲取到的 channelkey。

{ "status": 200, "data": "rfBd56ti2SMtYvSgD5xAV0YU99zampta7Z7S575KLkIZ9PYk"}

到現(xiàn)在,推流地址和 channelkey 都有了,只需要在OBS里面進行相關設置就可以進行推流。首先點擊“控件”的“設置”按鈕,進入設置面板。

玩轉直播:如何從 0 到 1 構建簡單直播系統(tǒng)

然后,選擇“推流”選項。服務選擇“自定義”,

服務器設置為:
rtmp://localhost:1935/live,串流密鑰設置為前面獲取到的 channelkey:rfBd56ti2SMtYvSgD5xAV0YU99zampta7Z7S575KLkIZ9PYk 。設置好后,點擊“控件”的“開始推流”按鈕,就可以進行推流了。

玩轉直播:如何從 0 到 1 構建簡單直播系統(tǒng)

一般情況下,默認的輸出配置就足以應付大多數(shù)場景了,但是要想獲得更適合自己想要的的直播效果的話,可以在“輸出”選項里設置“高級”輸出模式,對此無需求的話可以直接跳過本部分。如下圖所示,在高級輸出設置界面,可以對串流、錄像、音頻和回放緩存進行配置,其中,最重要的就是對串流的設置。編碼器軟件可以選擇 x264 和 QuickSync H.264,使用強大的 x264就可以。“重新縮放輸出”可以設置輸出的分辨率,默認使用原視頻的分辨率。

玩轉直播:如何從 0 到 1 構建簡單直播系統(tǒng)

比特率(碼率)的含義是視頻經過壓縮編碼后每秒的數(shù)據(jù)量的大小,單位是 Kbps,此處 K=1000。該值越大,每秒推送的視頻數(shù)據(jù)流就越大,視頻質量也越高,但是占用的帶寬也更多,可以根據(jù)需要進行調整,一般秀場直播常用2000~2500Kbps就可,游戲直播可能對碼率的要求比較高一點,可以做對應的調整。

直播推流時,可以使用多種碼率控制方式,主要有CBR、ABR、VBR和CRF。

CBR(Constant Bitrate)恒定碼率,一定時間范圍內比特率基本保持恒定。使用該模式時,在視頻動態(tài)畫面較多的場景下,圖像質量會變差,而在靜態(tài)畫面較多的場景下,圖像質量又會變好。

VBR(Variable Bitrate)可變碼率,其碼率可以隨著圖像的復雜程度的不同而變化。使用該模式時,在圖像內容比較簡單的場景下,分配較少的碼率,而在圖像內容復雜的場景下,則分配較多的碼率。這樣既保證了質量,又兼顧到帶寬限制,優(yōu)先考慮到圖像質量。

ABR(Average Bitrate)平均比特率,是VBR的一種插值參數(shù)。簡單場景分配較低碼率,復雜場景分配足夠碼率,這一點類似VBR。同時,一定時間內平均碼率又接近設置的目標碼率,這一點又類似CBR。可以認為ABR是CBR和VBR的折中方案。

CRF(Constant Rate Factor)恒定碼率系數(shù)。CRF值可以理解為對視頻的清晰度和流暢度期望的一個固定輸出值,即無論是在復雜場景還是在簡單場景下,都希望有一個穩(wěn)定的主觀視頻質量。

關鍵幀間隔(Group of Pictures,GOP)指的是一組由一個I幀、多個P幀和B幀組成的一個幀序列。一幀就是視頻中的一個畫面,其中:

I幀(intra coded picture):最完整的畫面,自帶全部信息,無需參考其他幀即可解碼,每個GOP都是以I幀開始;

P幀(predictive coded picture):幀間預測編碼幀,需要參考前面的I幀或P幀,才能進行解碼,壓縮率較高;

B幀(bipredictive coded picture):雙向預測編碼幀,以前幀后幀作為參考幀,壓縮率最高。

對于普通視頻,加大GOP長度有利于減小視頻體積,但是在直播場景下,GOP過大會導致客戶端的首屏播放時間變長。GOP越小圖片質量越高,建議設為2秒,最長不要超過4秒。

3.3 直播流觀看

我們剛剛已經搭建完成了RTMP服務器,并且使用目前比較成熟,功能比較豐富的推流工具OBS進行推流,接下來我們就要解決如何在用戶終端進行觀看了的問題。

FLV(Flash Video)是一種網(wǎng)絡視頻格式,是一種流媒體格式,目前主流的一些直播網(wǎng)絡使用的流媒體格式比較多的都是flv,它能夠不需要安裝任何插件即可進行播放。

3.3.1 小試牛刀:使用VLC工具觀看

VLC 是一款音視頻播放器,可以播放本地媒體,也可以播放網(wǎng)絡上的媒體,到官網(wǎng)


https://www.videolan.org/index.zh.html 下載對應的安裝包安裝即可。

點擊“媒體”tab下的“打開網(wǎng)絡串流”選項,然后網(wǎng)絡地址設置為:


rtmp://localhost:1935/live/movie ,點擊“確定”后就可以看到OBS推流的視頻啦。

玩轉直播:如何從 0 到 1 構建簡單直播系統(tǒng)玩轉直播:如何從 0 到 1 構建簡單直播系統(tǒng)

使用VLC主要是方便開發(fā)同學進行觀看測試,例如觀看卡頓的問題,分辨率查看,時延問題的定位,VLC算是一個比較專業(yè)的工具,能夠方便我們去定位問題和解決問題的

3.3.2 使用flv.js進行瀏覽器端的觀看

flv.js是目標最為流行的html5的純的JAVAscript,也是目前國內比較主流的瀏覽器終端播放flv格式的解決方案,本小節(jié)我們就使用flv.js進行簡單的播放,打開如下的網(wǎng)址:
http://bilibili.github.io/flv.js/demo/

玩轉直播:如何從 0 到 1 構建簡單直播系統(tǒng)

可以看到如圖所示的,將如下streamURL的輸入框輸入
http://127.0.0.1:7001/live/movie.flv 后,點擊switch to MediaDataSource后Load即可播放如下的畫面。

玩轉直播:如何從 0 到 1 構建簡單直播系統(tǒng)

3.3.3 直播協(xié)議的簡單介紹

玩轉直播:如何從 0 到 1 構建簡單直播系統(tǒng)

到目前為止,我們已經成功的搭建了RTMP小框架,了解了整個推拉流的完整過程,接下來我們就需要對與RTMP協(xié)議幾個強相關的直播網(wǎng)絡傳輸協(xié)議有一個入門的了解。

國內常見的直播協(xié)議有幾個:

RTMP

HLS

HTTP-FLV

HLS全稱是 HTTP Live Streaming。這是 Apple 提出的直播流協(xié)議。目前,IOS 和 高版本 Android 都支持 HLS,HLS 主要的兩塊內容是 .m3u8 文件和 .ts 播放文件。接收服務器會將接收到的視頻流進行緩存,然后緩存到一定程度后,會將這些視頻流進行編碼格式化,同時會生成一份 .m3u8 文件和其它很多的 .ts 文件,HLS的優(yōu)點是跨平臺性比較好,HTML5可以直接打開播放,移動端兼容性良好,缺點也是比較明顯,就是時延比較高,如果有些直播,例如互動性不高的直播,可以使用該協(xié)議,HLS網(wǎng)絡傳輸格式是非常適合用于點播的場景。

RTMP全稱 Real Time Messaging Protocol,即實時消息傳送協(xié)議,對于開發(fā)者來說,我們先明確RTMP是應用層協(xié)議,底層是使用的TCP傳輸協(xié)議,這邊我們知道RTMP是音視頻相關領域的協(xié)議,所以這塊使用TCP作為主要的傳輸層協(xié)議也給后續(xù)RTMP關于網(wǎng)絡的各種各樣的演進,留下了很多的空間,在直播行業(yè),特別是在推流端,RTMP協(xié)議是名副其實的霸主,基本上所有主流的直播網(wǎng)站都是支持rtmp協(xié)議進行推流的,關于RTMP的具體協(xié)議細節(jié),后續(xù)文章有具體的分析。

FLV(Flash Video)是 Adobe 公司推出的另一種視頻格式,是一種在網(wǎng)絡上傳輸?shù)牧髅襟w數(shù)據(jù)存儲容器格式。其格式相對簡單輕量,不需要很大的媒體頭部信息。整個 FLV 由 The FLV Header, The FLV Body 以及其它 Tag 組成。因此加載速度極快。采用 FLV 格式封裝的文件后綴為 .flv。

玩轉直播:如何從 0 到 1 構建簡單直播系統(tǒng)

流媒體協(xié)議 RTMP, HTTP-FLV, HLS 簡單對比:

玩轉直播:如何從 0 到 1 構建簡單直播系統(tǒng)

3.3.4 直播中的消息

在秀場直播系統(tǒng)中,如果說音視頻功能的實現(xiàn),是給直播裝扮上了華麗的新裝外表的話,那么直播系統(tǒng)中消息系統(tǒng)的實現(xiàn),則是整個直播華麗新裝下的靈魂,如何搭建高可用的直播間消息系統(tǒng),也是每一個直播系統(tǒng)必須要解決的問題。

在設計秀場直播的消息系統(tǒng)之前,我們需要簡單地梳理一下直播間的消息類型。

通知類消息

例如送禮、彈幕、進場、榜單變化、等級變化等等消息。他們的特征是通知用戶直播間的事件,營造直播間氛圍,提升用戶觀看直播的體驗。

功能類消息

例如踢人、反垃圾審核、紅包、PK消息等等。這類消息的特征是輔助直播業(yè)務開展,在流程上串聯(lián)開播端、觀看端、服務端三個角色。

我們可以從業(yè)務角度中,分析出直播間的各類消息雖然因為業(yè)務形態(tài)各式各樣,最終呈現(xiàn)的形式也是多彩絢麗,但是我們可以從各類的消息展現(xiàn)形式可以分析出,消息從開發(fā)的角度,有如下幾個特性,我們按照消息是否可丟棄,和實時性劃分,我們可以把所有的業(yè)務消息歸為如下幾類:

玩轉直播:如何從 0 到 1 構建簡單直播系統(tǒng)

在直播系統(tǒng)中,秀場直播,帶貨直播的直播間消息信令通信是比較偏多的,主要是因為業(yè)務性質所決定的,秀場直播和帶貨直播這兩類直播的互動性相對比較強,玩法也比較多樣,按照我們上圖的分類,每一個業(yè)務的消息的可丟棄性和實時性要求都不一樣,所以在開發(fā)消息系統(tǒng)的時候,也需要對消息進行優(yōu)先級排序,對消息分發(fā)的實時性也要有業(yè)務性能考量。

剛剛針對直播間消息實時性和不可丟棄性這兩個屬性做了業(yè)務上相關的闡述,不過對于直播消息而言,第一要素是穩(wěn)定性,消息如何準確穩(wěn)定地分發(fā)到指定的直播間,也是我們需要考慮的問題之一,直播消息的分發(fā)實現(xiàn),從總體上說可以分為兩種實現(xiàn)方式,第一是依靠直播間的實時通訊(Instant Messaging),也就是我們常說的IM消息系統(tǒng),第二個是依靠http短輪詢,例如客戶端每隔1秒來請求一次服務器,服務器返回這一秒內發(fā)生的增量消息信息,客戶端獲取到這些增量信息,再根據(jù)具體的消息業(yè)務類型,再進行相對業(yè)務的頁面UI渲染,這樣就可以了,從技術上說,一個是“推”模型,一個是“拉”模型,今天我們因為搭建一個簡單的直播間消息系統(tǒng),我們先用一個簡單的"拉"模型進行簡單的實現(xiàn)。

基本實現(xiàn)思路:客戶端每隔一個極短的時間,例如1秒亦或者更短的時間,根據(jù)直播間的id來調用服務端的接口,輪詢該直播間發(fā)生的消息,服務端這邊我們使用redis的SortedSet的數(shù)據(jù)結構來存儲消息,其中key是直播間的房間id,score是服務器接收到該消息事件生成的時間戳,value可以簡單地直接存儲該消息序列化后的字符串,這樣可以按照時間順序地去存儲消息,并且配置過期消息的刪除邏輯,整個消息的存儲就可以簡單地搭建起來。

消息存儲用java的偽代碼所示:

long time = new Date.getTime;try { // redis中插入消息數(shù)據(jù) jedisTemplate.zadd(V_UNIQUE_ROOM_ID, time, JSON.toJSONString(roomMessage)); // 按照概率性的去刪除redis中過期的消息數(shù)據(jù) if (probability) { deleteOverTimeCache(V_UNIQUE_ROOM_ID); } } catch (Exception e) { log.error("message save error", e); }

可以看到消息存儲,如果使用redis的sortedSet進行存儲還是比較方便的,接下來我們需要處理就是redis中過期消息的刪除,因為無效的過期消息是沒有價值的(所有的消息可以做持久化存儲),redis中如果單一的key存儲的消息過多,也會導致消息的慢查,和內存的使用量不斷增大,這是我們不想看到的,這邊因為是示例代碼,所以簡單地處理一下刪除邏輯。

private void deleteOverTimeCache(String roomId) { Long totalCount = jedisTemplate.zcard(roomId); log.info("deleteOldTimeCache size is {}", totalCount); if (totalCount < 600) { return; } // 倒序刪除過期數(shù)據(jù) Set<Tuple> tuples = jedisTemplate.zrangeWithScores(roomId, -601, -1); if (CollectionUtils.isNotEmpty(tuples)) { for (Tuple tuple : tuples) { // 這是第一個-600條的那個score double score = tuple.getScore; jedisTemplate.zremrangeByScore(roomId, 0d, score); break; } } }

上面的偽代碼probability首先先做一個概率性的判斷,例如我們做百分之一的隨機判斷,判斷該次請求是否要進行消息的刪除(請注意我們刪除的邏輯是放在插入的邏輯之中的。如果每一次插入都需要判斷是否要刪除過期數(shù)據(jù),會影響插入的性能)。如果通過概率性判斷后,我們就優(yōu)先判斷某一個直播間的消息個數(shù),如果消息個數(shù)還是比較少的話,則退出刪除邏輯,如果超過消息閥值,則按照時間倒序刪除已經過期的消息。

說完了http短輪詢消息的存儲后,我們最后再簡單地說一下客戶端消息查詢實現(xiàn)邏輯。客戶端通過直播間id和時間戳兩個字段來請求服務端以查詢直播間消息,其中"時間戳"是每一次服務端返回的,這個時間戳是漸進式的,當下一次客戶端來請求服務端的數(shù)據(jù)的時候,都會帶來上次服務端返回的時間戳,偽代碼如下:

@Override public RoomMessage queryRoomMessages(MessageMessageReq messageMessageReq) { RoomMessage result = new RoomMessage; long timestamp = messageMessageReq.getTimestamp; Set<Tuple> tuples = ; if (timestamp == 0) { // 如果傳遞是0,說明這個客戶端終端是第一次來輪詢,我們只要返回一個最近最新的消息返回即可 tuples = jedisTemplate.zrevrangeWithScores(UNIQUE_ROOM_ID, 0, 0); } else // 加上一毫秒,返回后續(xù)的消息,每次返回5個,防止客戶端因為低端手機原因,過多的消息渲染不出來 tuples = jedisTemplate.zrangeByScoreWithScores(UNIQUE_ROOM_ID, timestamp + 1, System.currentTimeMillis, 0, 5); } List<EachRoomMessage> eachRoomMessages = new ArrayList<>; long lastTimestamp = 0L; if (!CollectionUtils.isEmpty(tuples)) { for (Tuple tuple : tuples) { //最后一次循環(huán)后,會把最后一條消息產生的時間戳,返回給客戶端,這樣下次客戶端就可以拿著這個時間戳來進行查詢 lastTimestamp = new Double(tuple.getScore).longValue; eachRoomMessages.add(JSON.parseobject(tuple.getElement, EachRoomMessage.class)); } } result.setTimestamp(lastTimestamp); result.setEachRoomMessages(eachRoomMessages); return result; }

上述三段比較完整地代碼主要陳述了一個依賴http短輪詢這種方式快速實現(xiàn)的直播間的能力,這種方式是比較粗糙的,不過卻是一個很好的實現(xiàn)思路,目前我們線上部分業(yè)務也是根據(jù)這個輪詢的思想進行部分模塊的實現(xiàn)。

這樣實現(xiàn)的思路也有一個小坑,如果有采用該思路去實現(xiàn)的,可以嘗試去規(guī)避。如果Android客戶端斷網(wǎng)的情況下,輪詢的線程是不會停止的,例如是晚上8點整斷網(wǎng)的,8點01分恢復網(wǎng)絡的,當網(wǎng)絡恢復的時候,第一次輪詢就會導致服務端返回大量的消息,這邊是需要進行處理的,否則會返回過多的消息,服務端也會出現(xiàn)慢查,客戶端因為渲染過期的消息也會出現(xiàn)部分消息展示區(qū)間出現(xiàn)閃跳。例如公屏區(qū)可能會"發(fā)瘋"般的出現(xiàn)各類消息,這些可以通過客戶端和服務端的雙方約定進行規(guī)避,例如客戶端當出現(xiàn)網(wǎng)絡問題的時候,在超過5秒以上,可以把時間戳置為0,要求服務端返回最新的直播間消息即可,中間丟失掉的消息,可以在業(yè)務返回內的進行丟棄。

四、小結

本文主要是想讓大家對直播有一個初步的了解,了解直播基本的概念模型,一些基礎的概念,后續(xù)我們會深入直播具體的模塊的學習,進一步去了解直播的原理,也能夠幫助我們更好的做好直播的業(yè)務。

分享到:
標簽:直播 系統(tǒng)
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定