之前寫(xiě)了一篇文章,利用nginx和nginx-rtmp-module實(shí)現(xiàn)直播。
不過(guò),之前只是做到了能夠直播而已,只能一個(gè)人推流,并沒(méi)有實(shí)現(xiàn)多人多頻道輸入輸出,也沒(méi)有權(quán)限控制,只要知道rtmp的URL就能夠推送。
本文是在之前文章的基礎(chǔ)上繼續(xù)的。
原文地址:通過(guò)Nginx-rtmp-module搭建直播服務(wù)器并實(shí)現(xiàn)直播
一、權(quán)限控制方面
說(shuō)實(shí)話,我查這個(gè)查了很久,也沒(méi)查出個(gè)所以然,最后還是花了半天的時(shí)間,研究了一下nginx-rtmp-module的文檔,最后搞了半天才弄明白。
文檔中主要有兩個(gè)部分需要注意:
live配置的publish_notify部分
https://github.com/arut/nginx-rtmp-module/wiki/Directives#publish_notify
publish_notify中Notify的配置部分
https://github.com/arut/nginx-rtmp-module/wiki/Directives#notify
1、live的publish_notify
所謂的publish_notify是涉及publish_notify默認(rèn)是off的,主要涉及推送的過(guò)程中一些事件。
開(kāi)啟publish_notify即可進(jìn)行Notify的配置操作。
publish_notify on;
2、Notify的配置
Notify的配置相關(guān)是涉及直播的事件并執(zhí)行回調(diào)代碼。
比如:推流鏈接、直播開(kāi)啟、直播結(jié)束狀態(tài),然后異步調(diào)用http的鏈接,進(jìn)行一些邏輯的處理。
主要的配置參數(shù)有下面這些:
on_connect
on_play
on_publish
on_done
on_play_done
on_publish_done
on_record_done
on_update
......
從上面的配置參數(shù)可以看出,能夠觸發(fā)連接、直播、輸出、直播結(jié)束等等,從而能夠進(jìn)行權(quán)限驗(yàn)證、
比如,當(dāng)觸發(fā)推流的時(shí)候,通過(guò) on_publish?http://www.example.com/uri?進(jìn)行權(quán)限控制,接收相關(guān)參數(shù)并進(jìn)行控制,如果用戶不存在,則不允許推流。
二、多頻道輸入輸出
這里的多頻道輸入輸出意思是:多個(gè)人直播,每個(gè)人有不同的輸出地址。
1、直播推流端
多個(gè)人有不同的推流和直播地址,就涉及了直播參數(shù),而實(shí)際上,各大平臺(tái)直播的時(shí)候,除了地址,都有一個(gè)直播密鑰或者是直播碼。
以O(shè)BS舉例,串流類型選擇自定義流媒體服務(wù)器,然后會(huì)出現(xiàn)一個(gè)URL和流密鑰。

而流密鑰就是實(shí)現(xiàn)多頻道輸入輸出的重點(diǎn)。
2、rtmp Publish配置
既然需要進(jìn)行權(quán)限控制,就要使用publish,首先進(jìn)行權(quán)限的驗(yàn)證,證明有推流權(quán)限。
所以rtmp的配置如下(最后會(huì)給出一個(gè)完整的配置示例):
因?yàn)橹皇翘接憴?quán)限控制,因此hls之類的不需要關(guān)心,我也注釋了。
? ? #設(shè)置直播的application名稱是 myapp
? ? application myapp{
? ? ? ? live on; #live on表示開(kāi)啟直播模式? ? ? ?
? ? ? ? publish_notify on;
? ? ? ? on_publish http://tp5.ptbird-ubuntu/on_publish.html;
? ? ? ? #hls on;
? ? ? ? #hls_path /tmp/hls;
? ? ? ? #hls_fragment 2s;
? ? ? ? #hls_playlist_length 6s;
? ? }
關(guān)鍵配置是:on_publish?http://tp5.ptbird-ubuntu/on_publish.html;
后面的?http://tp5.ptbird-ubuntu/on_publish.html?是假設(shè)在web服務(wù)器上的處理程序,網(wǎng)上有的將這個(gè)邏輯假設(shè)在本機(jī)nginx,我是建議不要混在一起,直接在別的能夠連接的web服務(wù)器上部署即可。
我是架設(shè)在我的另一臺(tái)ubuntu kylin的web服務(wù)器上。
反正能訪問(wèn)的php處理就可以了,別的說(shuō)多了也沒(méi)用。
3、權(quán)限驗(yàn)證URL
一個(gè)示例的配置如下所示,這是一個(gè)模板配置示例。

流密鑰的格式是:test?pass=123456,可以看出這個(gè)非常像url的get參數(shù)配置,test就是用戶的name,而pass就是密碼。
為什么沒(méi)有name=test
因?yàn)閚ame是rtmp on_publish的默認(rèn)參數(shù),name是不能更改的。
絕對(duì)不能使用GET['name'],而應(yīng)該使用POST
一開(kāi)始我總是使用get去獲取參數(shù),但是發(fā)現(xiàn)一直無(wú)法成功,也沒(méi)辦法驗(yàn)證 - -
后來(lái)網(wǎng)上查了查,發(fā)現(xiàn)不能使用get獲取,雖然流密鑰的格式像是get類型,但是必須使用POST獲取參數(shù)。
自定義參數(shù)
除了name不能更改之外,其他的都是可以自定義參數(shù)的
比如pass=123456&check=123456這樣的
三、代碼驗(yàn)證權(quán)限
1、ThinkPHP5版本
這里使用php進(jìn)行驗(yàn)證,我順便將上面?http://tp5.ptbird-ubuntu/on_publish.html?這個(gè)url部署在一個(gè)thinkphp5的框架中。
因此實(shí)際上我是有一個(gè)路由的,才會(huì)使用html后綴的URL。
// 配置直播推送的url
Route::rule('on_publish','index/Publish/index');
實(shí)際的邏輯很簡(jiǎn)單:
接收兩個(gè)參數(shù)
通過(guò)數(shù)據(jù)庫(kù)進(jìn)行驗(yàn)證
返回驗(yàn)證信息
必須返回http頭,返回2xx表示成功,3xx表示跳轉(zhuǎn),4xx表示失敗
一般驗(yàn)證失敗都是返回404就可以,一定返回標(biāo)準(zhǔn)的404頭(一開(kāi)始我一直驗(yàn)證失敗,后面發(fā)現(xiàn),就是返回的頭的問(wèn)題)
而處理的代碼如下:
下面代碼是基于thinkphp5來(lái)處理的,其中沒(méi)有涉及數(shù)據(jù)庫(kù)的操作,只是有兩個(gè)參數(shù)test和test2兩個(gè)用戶,兩個(gè)密碼
而返回http頭的狀態(tài)也是用的thinkphp5的返回方式,下面會(huì)有第二種普通的處理方式。
<?php
/**
* Author: root
* Date? : 17-3-19
* time? : 下午4:58
* Site? : www.ptbird.cn
* There I am , in the world more exciting!
*/
namespace app\index\controller;
use think\Request;
class Publish {
? ? // index
? ? public function index(Request $request){
? ? ? ? // 接受name和pass param可以自動(dòng)選擇get或者是post
? ? ? ? $name=$request->param('name');
? ? ? ? $pass=$request->param('pass');
? ? ? ? // 設(shè)置用戶名和密碼
? ? ? ? $savename= "test";
? ? ? ? $savepass = "123456";
? ? ? ? if(empty($name) || empty($pass)){
? ? ? ? ? ? echo "串碼流不正確";
? ? ? ? ? ? // 這個(gè)是thinkphp5的返回頭信息的函數(shù)
? ? ? ? ? ? return json('')->code(404)->header(['Not Found']);
? ? ? ? }else{
? ? ? ? ? ? if(strcmp($name,$savename)==0 && strcmp($pass,$savepass)==0){
? ? ? ? ? ? ? ? // 默認(rèn)是返回2xx的頭,因此不需要進(jìn)行控制
? ? ? ? ? ? ? ? echo "串碼流正確";
? ? ? ? ? ? ? ? // 我在這里添加了另一個(gè)test2 和 123456的用戶
? ? ? ? ? ? }else if(strcmp($name,'test2')==0 && strcmp($pass,'123456')==0){
? ? ? ? ? ? ? ? echo "串碼流正確";
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? echo "串碼流不正確";
? ? ? ? ? ? ? ? return json('')->code(404)->header(['Not Found']);
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
2、普通的php驗(yàn)證
下面的代碼,是網(wǎng)上的代碼,一個(gè)道理,就不多說(shuō)了。
// ?user=user&pass=pass
@$name = $_POST['name'];
@$pass = $_POST['pass'];
$savename= test;
$savepass = password;
if(empty($name) || empty($pass)){
? ? echo "串碼流不正確!";
? ? header('HTTP/1.0 404 Not Found');
}else{
? ? if (strcmp($name, $savename) == 0 && strcmp($pass, $savepass) == 0) {
? ? ? ? echo "串碼流正確!";
? ? } else {
? ? ? ? echo "串碼流不正確!";
? ? ? ? header('HTTP/1.0 404 Not Found');
? ? }
}
四、直播與觀看直播
經(jīng)過(guò)上面的配置,現(xiàn)在可以進(jìn)行多人直播。
上面的操作中我有兩個(gè)用戶,一個(gè)是test,另一個(gè)是test2,現(xiàn)在分別使用這兩個(gè)用戶進(jìn)行直播。
1、test用戶的直播 使用OBS 18

2、test2用戶的直播 使用obs 0.65

3、test3用戶的直播(失敗)
將用戶名設(shè)置成test3

因?yàn)榉祷亓?04,因此直播失敗。

五、總結(jié)
on_publish可以實(shí)現(xiàn)權(quán)限控制,而其他的notify參數(shù),比如on_connect可以設(shè)置當(dāng)用戶進(jìn)行推流之后,就可以設(shè)置用戶的直播狀態(tài)為進(jìn)行直播等等。
之后再繼續(xù)研究....