Ich versuche, einen Web-basierte Live-Webcam-Streaming-Dienst einrichten, wo ein Benutzer live via Webcam (nur Web-basierte) übertragen kann, dh:Kann RTCPeerConnection für Live-Cam-Dienste verwendet werden oder brauche ich einen Medienserver?
Benutzer A Starten eine Live-Übertragung bei
http://www.example.com/user-a
Benutzern B , C, D, E und Zählung geht auf Besuche, dh uRL:
http://www.example.com/user-a
und wird die Live-Sendung/Stream sehen können. Ich spielte mit RTCPeerConnection
um Peer zu Peer zu erstellen, um Strom zu teilen, um Bandbreite und Serverlast zu sparen, und ich bin in der Lage, den folgenden Code zu verwenden, und OfferToReceiveAudio: true
, OfferToReceiveVideo: true
Bedingungen zu gehen. Es funktioniert ganz gut.
Jetzt habe ich es geschafft, neue Peer-Verbindung für jeden verbundenen Peer (Viewer) zu erstellen. Auf diese Weise kann jeder von der Webcam und andere (Peers) in der Lage sein, Broadcast zu sehen. Ich bin verwirrt, wenn dies ein skalierbarer Prozess ist, was bedeutet, wenn Benutzer-A sendet und Zuschauer sind 500+, und Benutzer-b sendet und Zuschauer sind 1000. Ist dies zuverlässig für Live-Übertragungen. Ich möchte einen Medienserver nicht einrichten, deshalb verwende ich webrtc Sache.
Kunde
var
ws = new WebSocket('wss://www.example.com:443'),
isRemote = false,
iStream = null,
iDescription = null,
iAnswer = null,
video = document.querySelector('video'),
peerConnCfg = {'iceServers':
[{'url': 'stun:stun.services.mozilla.com'}, {'url': 'stun:stun.l.google.com:19302'}]
},
mediaConstraints = {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true
},
peer;
ws.onmessage = function(message){
var json = JSON.parse(message.data);
if(isRemote==true){
if(json.result=="ok"){
StartWatch(json.sdp, json.ice);
}else{
console.log("Watch start failed...");
}
}else{
if(json.result=="ok" && json.action=="rsdp"){
peer.setRemoteDescription(new RTCSessionDescription(json.sdp), function() {
peer.addIceCandidate(new RTCIceCandidate(json.ice)).then(function(){
console.log("added remote ice");
}).catch(function(e){
console.log(e);
});
}, function(error){
console.log("Offer remote failed error : " + error);
});
}
console.log("Remote is false...");
}
};
function golive(){
peer = new RTCPeerConnection(peerConnCfg);
peer.onicecandidate = function(event){
console.log("Got candidate...");
if(event.candidate != null) {
ws.send(JSON.stringify({'mod' : 'golive', 'channel': 'channel-xyz', 'sdp' : iDescription, 'ice' : event.candidate}));
}
};
navigator.getUserMedia({ audio: true, video: { width: 1280, height: 720 } },
function(stream) {
iVideoStream = stream;
video.src = window.URL.createObjectURL(stream);
video.onloadedmetadata = function(e){
video.play();
};
peer.addStream(stream);
peer.createOffer(function(description){
//success
console.log("Got description...");
peer.setLocalDescription(description, function() {
iDescription = description;
}, function() {console.log('set description error')});
}, function(){
//error
});
},
function(err) {
console.log("The following error occurred: " + err.name);
}
);
}
function watch(){
ws.send(JSON.stringify({'mod' : 'watch', 'channel': 'channel-xyz'}));
}
function StartWatch(sdp, ice){
peer = new RTCPeerConnection(peerConnCfg);
peer.onicecandidate = function(event){
console.log("Got candidate...");
if(event.candidate != null) {
ws.send(JSON.stringify({'mod' : 'goliveupdate', 'channel': 'channel-xyz', 'sdp' : iAnswer, 'ice' : event.candidate}));
}
};
peer.onaddstream = function(event){
peer.addStream(event.stream);
video.src = window.URL.createObjectURL(event.stream);
video.onloadedmetadata = function(e){
video.play();
};
};
peer.setRemoteDescription(new RTCSessionDescription(sdp), function() {
peer.createAnswer(function(answer){
peer.setLocalDescription(answer, function() {
iAnswer = answer;
peer.addIceCandidate(new RTCIceCandidate(ice)).then(function(){
console.log("added");
}).catch(function(e){
console.log(e);
});
}, function (error) {
console.log("Local desc error: " + error);
});
}, function(error){
console.log("Answer Error: " + error);
});
}, function(error) { console.log('set description error: ' + error)});
}
//i.e waitForSocketConnection
function _init(){
setTimeout(function(){
if (ws.readyState === 1) {
console.log('Connected to WS');
<?php
if(!isset($_GET['v'])){
echo 'golive();';
}else{
echo 'isRemote = true; watch();';
}
?>
return;
}else{
_init();
}
}, 5);
}
_init();
Socket-Server für
"use strict";
var fs = require('fs');
var cfg = {
ssl: true,
port: 443,
ssl_key: '/home/csr/example_in.key',
ssl_cert: '/home/csr/example_in.crt'
};
var app = null;
var httpServ = (cfg.ssl) ? require('https') : require('http');
var processRequest = function(req, res) {
res.writeHead(200);
res.end("All glory to WebSockets!\n");
};
if (cfg.ssl) {
app = httpServ.createServer({
// providing server with SSL key/cert
key: fs.readFileSync(cfg.ssl_key),
cert: fs.readFileSync(cfg.ssl_cert)
}, processRequest).listen(cfg.port);
} else {
app = httpServ.createServer(processRequest).listen(cfg.port);
}
var WebSocketServer = require('ws').Server,
wss = new WebSocketServer({server: app, host:'www.example.in'}),
example = {
channels: [],
run: function(){
wss.on('connection', function(ws) {
//example.channels.push(ws);
ws.on('message', function(message) {
//example.respond(ws, message);
example.respond(ws, JSON.parse(message));
});
});
wss.on('close', function() {
example.closeChannel(ws);
});
},
closeChannel(ws){
for (var channel in example.channels) {
var _channel = example.channels[channel];
if (_channel[i] == ws){ delete _channel[i]; }
example.channels[channel] = example.swapArray(_channel);
if(example.channels && example.channels[channel] && !example.channels[channel].length)
delete example.channels[channel];
}
},
swapArray: function(arr) {
var swapped = [],
length = arr.length;
for (var i = 0; i < length; i++) {
if (arr[i])
swapped[swapped.length] = arr[i];
}
return swapped;
},
respond : function(ws, message){
//ws.send(message.mod); return;
switch(message.mod){
case "golive":
example.channels[message.channel] = {
name : message.channel,
socket : ws,
sdp : message.sdp,
rsdp: null,
ice: message.ice,
rice: null
};
ws.send(JSON.stringify({'result' : 'ok', 'action' : 'connected', 'channel': message.channel}));
break;
case "goliveupdate":
example.channels[message.channel].rsdp = message.sdp;
example.channels[message.channel].rice = message.ice;
example.channels[message.channel].socket.send(JSON.stringify({'result' : 'ok', 'action' : 'rsdp', 'sdp' : message.sdp, 'ice' : message.ice, 'message': 'A peer connected'}));
break;
case "watch":
if(example.channels[message.channel]){
example.channels[message.channel].socket.send(JSON.stringify({'result' : 'ok', 'message': 'A peer connected'}));
ws.send(JSON.stringify({
'result' : 'ok',
'action' : 'connected',
'message': 'Connected to ' + message.channel,
'sdp' : example.channels[message.channel].sdp,
'ice' : example.channels[message.channel].ice
}));
}else{
ws.send(JSON.stringify({'result' : 'ok', 'message': 'Unable to connect to ' + message.channel}));
}
break;
}
}
};
example.run();
Ok. Ich versuche nun, den red5 media server einzurichten und werde Sie dann updaten. – Appklony
@Appklony Ich bin kein Medienserver-Experte, aber ich stelle fest, dass auf ihrer Website steht: "Derzeit wird Unterstützung für WebRTC aufgebaut" ... – jib