webrtc流媒体的播放,本质上也是基于建立端到端的RTC连接、接收推送过来的视频流数据的过程。webrtc流地址本质上就具有很强的规则性,其中包含信令服务器地址、基本参数等。
SRS(Simple Real-Time Media Server)是一个强大的开源的流媒体服务器, webrtcs视频流的播放本身就是一个订阅(播放)的过程,因此 SRS 源码中自然包含播放的代码,即
srs.sdk.js 是基于 SRS 实时视频服务器、对浏览器支持的 WebRTC 基础功能的封装
系统需要的环境
- 1,Srs的安装Docker | SRS
- 2,搭建https://www.rabbitmq.com/
RabbitMQ主要是用于后台的数据交付到队列内,然后前端页面使用ws(wss)来展示数据。朋友们可以根据业务需求自行修改.
// 下面的代码是回流,显示数据到页面上
//换域名如果你的域名启用https,Stomp.client要使用wss://
//换域名如果你的域名启用http,Stomp.client要使用ws://
//如果使用http://127.0.0.1 ,就使用Stomp.client要使用ws://
//var client = Stomp.client('wss://rabbit.ggiooo.com:15674/wss');
var client = Stomp.client('wss://rabbit.ggiooo.com:15674/ws');
//订阅rabbmiq队列
var on_connect = function(x) {
id = client.subscribe("/queue/rtc_publisher_queue", function(d) {
console.log("d ===>",d)
vm.testprint(d);
});
};
var on_error = function() {
console.log('error');
};
client.connect('guest', 'guest', on_connect, on_error, 'dou');
Stomp.client就是连接ws rabbitMQ队列协议。然后建立on_connect。
client.connect('用户名','密码',on_connet,on_error,'主机名')
二,启动js rtc推流
sdk = new SrsRtcPublisherAsync();
....
// For example: webrtc://r.ossrs.net/live/livestream
var url = $("#txt_url").val();
sdk.publish(url).then(function(session){
...
}
url是SRS服务端的webrtc地址
文档链接:Docker | SRS
打开地址:http://localhost:1985/rtc/v1/whep/?app=live&stream=livestream
你就能找到WebRTC协议的地址
关于SRS的教程很多,我这边不详细说明SRS。请百度查询SRS
三,下面是index.html的核心代码。
<!DOCTYPE html>
<html>
<head>
<title>SRS</title>
<meta charset="utf-8">
<style>
body{
padding-top: 30px;
}
</style>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"/>
<script type="text/javascript" src="js/jquery-1.12.2.min.js"></script>
<script type="text/javascript" src="js/adapter-7.4.0.min.js"></script>
<script type="text/javascript" src="js/srs.sdk.js"></script>
<script type="text/javascript" src="js/winlin.utility.js"></script>
<script type="text/javascript" src="js/srs.page.js"></script>
<script src="js/stomp.js"></script>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div class="container">
<div class="form-inline">
URL:
<input type="text" id="txt_url" class="input-xxlarge" value="">
<button class="btn btn-primary" id="btn_publish">开始推流</button>
</div>
<label></label>
<video id="rtc_media_player" width="320" autoplay muted></video>
<label></label>
SessionID: <span id='sessionid'></span>
<div style="display:none">
<label></label>
Audio: <span id='acodecs'></span><br/>
Video: <span id='vcodecs'></span>
</div>
<div id="app" style="margin: 10px;" >
<div v-for="(item,i) in lists">
<img :src="item.scene_img" style="width:220px;height:220px; " />
<p style="font-size:14px">[视频创建时间:{{item.created_at}}]-[AI完成时间{{item.last_at}}]
<br> {{item.scene_msg}}</p>
</div>
</div>
</div>
<script type="text/javascript">
$(function(){
var sdk = null; // Global handler to do cleanup when republishing.
$('#rtc_media_player').show();
// Close PC when user replay.
if (sdk) {
sdk.close();
}
sdk = new SrsRtcPublisherAsync();
// User should set the stream when publish is done, @see https://webrtc.org/getting-started/media-devices
// However SRS SDK provides a consist API like https://webrtc.org/getting-started/remote-streams
$('#rtc_media_player').prop('srcObject', sdk.stream);
// Optional callback, SDK will add track to stream.
// sdk.ontrack = function (event) { console.log('Got track', event); sdk.stream.addTrack(event.track); };
// https://developer.mozilla.org/en-US/docs/Web/Media/Formats/WebRTC_codecs#getting_the_supported_codecs
sdk.pc.onicegatheringstatechange = function (event) {
if (sdk.pc.iceGatheringState === "complete") {
$('#acodecs').html(SrsRtcFormatSenders(sdk.pc.getSenders(), "audio"));
$('#vcodecs').html(SrsRtcFormatSenders(sdk.pc.getSenders(), "video"));
}
};
// For example: webrtc://r.ossrs.net/live/livestream
var url = $("#txt_url").val(); //rtmp地址
sdk.publish(url).then(function(session){
$('#sessionid').html(session.sessionid);
$('#simulator-drop').attr('href', session.simulator + '?drop=1&username=' + session.sessionid);
}).catch(function (reason) {
// Throw by sdk.
if (reason instanceof SrsError) {
if (reason.name === 'HttpsRequiredError') {
alert(`WebRTC推流必须是HTTPS或者localhost:${reason.name} ${reason.message}`);
} else {
alert(`${reason.name} ${reason.message}`);
}
}
// See https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#exceptions
if (reason instanceof DOMException) {
if (reason.name === 'NotFoundError') {
alert(`找不到麦克风和摄像头设备:getUserMedia ${reason.name} ${reason.message}`);
} else if (reason.name === 'NotAllowedError') {
alert(`你禁止了网页访问摄像头和麦克风:getUserMedia ${reason.name} ${reason.message}`);
} else if (['AbortError', 'NotAllowedError', 'NotFoundError', 'NotReadableError', 'OverconstrainedError', 'SecurityError', 'TypeError'].includes(reason.name)) {
alert(`getUserMedia ${reason.name} ${reason.message}`);
}
}
sdk.close();
$('#rtc_media_player').hide();
console.error(reason);
});
};
$('#rtc_media_player').hide();
var query = parse_query_string();
srs_init_rtc("#txt_url", query);
$("#btn_publish").click(startPublish);
// Never play util windows loaded @see https://github.com/ossrs/srs/issues/2732
if (query.autostart === 'true') {
window.addEventListener("load", function(){ startPublish(); });
}
});
</script>
</body>
<script>
// 下面的代码是回流,显示数据到页面上
//换域名如果你的域名启用https,Stomp.client要使用wss://
//换域名如果你的域名启用http,Stomp.client要使用ws://
//如果使用http://127.0.0.1 ,就使用Stomp.client要使用ws://
//var client = Stomp.client('wss://rabbit.ggiooo.com:15674/wss');
var client = Stomp.client('wss://rabbit.ggiooo.com:15674/ws');
//订阅rabbmiq队列
var on_connect = function(x) {
id = client.subscribe("/queue/rtc_publisher_queue", function(d) {
console.log("d ===>",d)
vm.testprint(d);
});
};
var on_error = function() {
console.log('error');
};
client.connect('guest', 'guest', on_connect, on_error, 'dou');
</script>
<script>
var _data ={
lists :[]
};
var vm=new Vue({
el:'#app',
data:_data,
onLoad:function(){
},
mounted:function(){
},
methods:{
addValueToFront(newValue) {
this.lists.unshift(newValue); //向数组添加数组
console.log(this.lists);
},
testprint(d) {
console.log("57 >>>")
let jsonObject = JSON.parse(d.body);
if (jsonObject.hasOwnProperty('scene_img')) {
let scene_img = 'https://hs.ggiooo.com/upimgloads/'+
jsonObject.scene_img.replace("/www/srs5/output/images/",'')
let scene_msg =jsonObject.scene_msg
this.addValueToFront({'scene_img':scene_img,'scene_msg':scene_msg,'created_at':jsonObject.created_at,'last_at':jsonObject.last_at})
}
}
}
})
</script>
</html>
3-1,关于wss的用法:
链接:http://ossrs.net/lts/zh-cn/docs/v6/doc/getting-started#webrtc-using-https
【WebRTC using HTTPS】推流时, 若需要在非本机使用WebRTC,比如SRS运行在远程服务器,在笔记本或者手机上使用WebRTC,则需要开启HTTPS API。
直白说就是要加上请使用你的证书文件,代替上面配置中的key和cert
3-2,推流的逻辑图
3-3,上面的代码没办法实现手机摄像头使用后置
//修改js/srs.sdk.js
//函数SrsRtcPublisherAsync名
self.constraints = {
audio: true,
video: {
facingMode: { exact: "environment" }, //后置摄像头
width: {ideal: 320, max: 576}
}
};
以上的实现是作者【黑金】业务需求经过采坑已经实现的,不是网上抄袭的。如果对webrtcs推流感兴趣的朋友,欢迎加微信来聊。