我必须创建一个WebRTC解决方案,在私有网络中我有多个IP摄像头,并且必须将源流式传输到网络外的移动应用程序。我正在使用Kurento Media Server来帮助我从摄像机的RTSP流生成WebRTC流。我也在专用网络中安装了KMS(Kurento Media Server)。
我遵循类似的设置https://github.com/lulop-k/kurento-rtsp2webrtc,除了我创建了一个带有PlayerEndpoint的管道,其中相机流URI和WebRTCEndpoint连接到它,如下所示。
function playCam(message){
console.log("Message:" + JSON.stringify(message));
var cam_url = message.cam_url;
var sdpOffer = message.sdpOffer;
getKurentoClient(function(error, kurentoClient) {
console.log("Kurento client created.");
kurentoClient.create('MediaPipeline', function(error, pipeline) {
if (error) {
console.log("Error: Creating Media Pipeline failed.");
stop(pipeline);
return;
}
console.log("Pipeline created.");
pipeline.create("PlayerEndpoint", {uri: cam_url}, function(error, player){
if(error) {
console.log("Error: Creating PlayerEndpoint failed.");
stop(pipeline);
return;
}
console.log("PlayerEndpoint created.");
pipeline.create("WebRtcEndpoint", function(error, webRtcEndpoint){
remoteWebRtcEndpoint = webRtcEndpoint;
console.log("WebRtcEndpoint created.");
webRtcEndpoint.processOffer(sdpOffer, function(error, sdpAnswer){
sendSdpAnswer(sdpAnswer);
for(var i = 0; i < remoteCandidates.length; i++){
addIceRemoteCandidate(remoteCandidates[i]);
}
webRtcEndpoint.gatherCandidates(function(error) {
console.log("Gathering Ice candidates created.");
});
});
player.connect(webRtcEndpoint, function(error){
console.log("PlayerEndpoint-->WebRtcEndpoint connection established");
player.play(function(error){
console.log("Player playing ...");
});
});
webRtcEndpoint.on('OnIceCandidate', function(event) {
console.log(JSON.stringify(event));
var candidate = kurento.getComplexType('IceCandidate')(event.candidate);
sendIceCandidate(candidate);
});
});
});
});
});
}
我在云中使用了一个Web套接字来发出sdpOffer,sdpAnswer,iceCandidate消息的信号。
在客户端,我有使用WebRTC Peer的javascript实现,如下所示。
var ws = new WebSocket(ws.url);
var webRtcPeer;
ws.onmessage = function(message) {
var parsedMessage = JSON.parse(message.data);
switch (parsedMessage.id) {
case 'iceCandidate':
webRtcPeer.addIceCandidate(parsedMessage.candidate)
break;
case 'sdpAnswer':
webRtcPeer.processAnswer(parsedMessage.sdpAnswer);
break;
default:
onError('Unrecognized message', parsedMessage);
}
}
window.addEventListener('load', function(){
var videoOutput = document.getElementById('videoOutput');
var address = camera_rtsp_stream_url;
var pipeline;
function start() {
var options = {
remoteVideo : videoOutput,
configuration: {
iceServers:[
{ "url": turn_url,
"username": uname,
"credential": pass
}
]
}
};
webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly(options,
function(error){
webRtcPeer.generateOffer(onOffer);
setIceCandidateCallbacks();
});
}
function onOffer(error, sdpOffer){
var message = {
id : 'sdpOffer',
name: 'peer',
cam_url: address,
sdpOffer : sdpOffer
};
sendMessage(message);
}
});
function sendMessage(message) {
var jsonMessage = JSON.stringify(message);
ws.send(jsonMessage);
}
function setIceCandidateCallbacks(){
webRtcPeer.on('icecandidate', function(candidate){
candidate = kurentoClient.register.complexTypes.IceCandidate(candidate);
var message = {
id : 'iceCandidate',
name: 'peer',
iceCandidate : candidate
};
sendMessage(message);
});
}
页面中的Feed仍无效。但是,git repo中的示例非常完美。有什么我想念的东西。
提前致谢。
编辑:
这是我的SDP优惠。
v=0
o=- 62767501284085133 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:AoAe
a=ice-pwd:tp+DQSO/OTvBaDZYQOmb5Yxe
a=fingerprint:sha-256 14:03:6A:CB:9D:86:B5:57:09:30:97:D8:0A:0E:59:A2:0F:8D:5F:24:46:3E:14:C7:D3:23:B2:11:39:4C:61:33
a=setup:actpass
a=mid:audio
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=recvonly
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:126 telephone-event/8000
m=video 9 UDP/TLS/RTP/SAVPF 100 101 107 116 117 96 97 99 98
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:AoAe
a=ice-pwd:tp+DQSO/OTvBaDZYQOmb5Yxe
a=fingerprint:sha-256 14:03:6A:CB:9D:86:B5:57:09:30:97:D8:0A:0E:59:A2:0F:8D:5F:24:46:3E:14:C7:D3:23:B2:11:39:4C:61:33
a=setup:actpass
a=mid:video
a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:4 urn:3gpp:video-orientation
a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=recvonly
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:100 VP8/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=rtpmap:101 VP9/90000
a=rtcp-fb:101 ccm fir
a=rtcp-fb:101 nack
a=rtcp-fb:101 nack pli
a=rtcp-fb:101 goog-remb
a=rtcp-fb:101 transport-cc
a=rtpmap:107 H264/90000
a=rtcp-fb:107 ccm fir
a=rtcp-fb:107 nack
a=rtcp-fb:107 nack pli
a=rtcp-fb:107 goog-remb
a=rtcp-fb:107 transport-cc
a=fmtp:107 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:116 red/90000
a=rtpmap:117 ulpfec/90000
a=rtpmap:96 rtx/90000
a=fmtp:96 apt=100
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=101
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=107
a=rtpmap:98 rtx/90000
a=fmtp:98 apt=116
SDP答案如下所示:
v=0
o=- 3687061549 3687061549 IN IP4 0.0.0.0
s=Kurento Media Server
c=IN IP4 0.0.0.0
t=0 0
a=msid-semantic: WMS
a=group:BUNDLE audio video
m=audio 1 UDP/TLS/RTP/SAVPF 111 0
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=mid:audio
a=rtcp:9 IN IP4 0.0.0.0
a=rtpmap:111 opus/48000/2
a=rtpmap:0 PCMU/8000
a=setup:active
a=sendonly
a=rtcp-mux
a=fmtp:111 minptime=10;useinbandfec=1
a=ssrc:174718429 cname:user1410268339@host-e518075a
a=ice-ufrag:Y1e8
a=ice-pwd:rLobIsorf9OWA8VkEvGbJN
a=fingerprint:sha-256 EF:8B:94:E4:CF:2A:82:BD:2D:07:F6:35:B8:2A:4C:4A:7F:A5:8D:FE:06:5F:38:6C:E7:F8:10:07:3C:11:E1:28
m=video 1 UDP/TLS/RTP/SAVPF 100
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=mid:video
a=rtcp:9 IN IP4 0.0.0.0
a=rtpmap:100 VP8/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 goog-remb
a=setup:active
a=sendonly
a=rtcp-mux
a=ssrc:3344771 cname:user1410268339@host-e518075a
a=ice-ufrag:Y1e8
a=ice-pwd:rLobIsorf9OWA8VkEvGbJN
a=fingerprint:sha-256 EF:8B:94:E4:CF:2A:82:BD:2D:07:F6:35:B8:2A:4C:4A:7F:A5:8D:FE:06:5F:38:6C:E7:F8:10:07:3C:11:E1:28