Closed xpallas2020 closed 5 years ago
Hi jyang2019, Does it work with the same stream using the internal http server ? Using NGINX as an external server, you should provide the files webrtcstreamer.js,... Best Regards, Michel.
Hi Michel, Thanks for your kind help. It can work with the same stream using the internal http server. Please check the following files.
------ webrtcstreamer.js
/**
@param {string} srvurl - url of webrtc-streamer (default is current location)
*/
function WebRtcStreamer (videoElement, srvurl) {
this.videoElement = videoElement;
this.srvurl = srvurl || location.protocol+"//"+window.location.hostname+":"+window.location.port;
this.pc = null;
this.pcOptions = { "optional": [{"DtlsSrtpKeyAgreement": true} ] };
this.mediaConstraints = { offerToReceiveAudio: true, offerToReceiveVideo: true };
this.iceServers = null; this.earlyCandidates = []; }
/**
@param {string} stream - local stream to send */ WebRtcStreamer.prototype.connect = function(videourl, audiourl, options, localstream) { this.disconnect();
// getIceServers is not already received if (!this.iceServers) { console.log("Get IceServers");
var bind = this;
request("GET" , this.srvurl + "/api/getIceServers")
.done( function (response) {
if (response.statusCode === 200) {
bind.onReceiveGetIceServers.call(bind,JSON.parse(response.body), videourl, audiourl, options, localstream);
}
else {
bind.onError(response.statusCode);
}
}
);
} else { this.onReceiveGetIceServers(this.iceServers, videourl, audiourl, options, localstream); } }
/**
Disconnect a WebRTC Stream and clear videoElement source
*/
WebRtcStreamer.prototype.disconnect = function() {
var videoElement = document.getElementById(this.videoElement);
if (videoElement) {
videoElement.src = "";
}
if (this.pc) {
request("GET" , this.srvurl + "/api/hangup?peerid="+this.pc.peerid);
try {
this.pc.close();
}
catch (e) {
console.log ("Failure close peer connection:" + e);
}
this.pc = null;
} }
/*
GetIceServers callback
*/
WebRtcStreamer.prototype.onReceiveGetIceServers = function(iceServers, videourl, audiourl, options, stream) {
this.iceServers = iceServers;
this.pcConfig = iceServers || {"iceServers": [] };
try {
this.pc = this.createPeerConnection();
var peerid = Math.random();
this.pc.peerid = peerid;
var callurl = this.srvurl + "/api/call?peerid="+ peerid+"&url="+encodeURIComponent(videourl);
if (audiourl) {
callurl += "&audiourl="+encodeURIComponent(audiourl);
}
if (options) {
callurl += "&options="+encodeURIComponent(options);
}
if (stream) {
this.pc.addStream(stream);
}
// clear early candidates
this.earlyCandidates.length = 0;
// create Offer
var bind = this;
this.pc.createOffer(this.mediaConstraints).then(function(sessionDescription) {
console.log("Create offer:" + JSON.stringify(sessionDescription));
bind.pc.setLocalDescription(sessionDescription
, function() {
request("POST" , callurl, { body: JSON.stringify(sessionDescription) })
.done( function (response) {
if (response.statusCode === 200) {
bind.onReceiveCall.call(bind,JSON.parse(response.body));
}
else {
bind.onError(response.statusCode);
}
}
);
}
, function(error) {
console.log ("setLocalDescription error:" + JSON.stringify(error));
} );
}, function(error) {
alert("Create offer error:" + JSON.stringify(error));
});
} catch (e) {
this.disconnect();
alert("connect error: " + e);
}
}
/*
create RTCPeerConnection
*/
WebRtcStreamer.prototype.createPeerConnection = function() {
console.log("createPeerConnection config: " + JSON.stringify(this.pcConfig) + " option:"+ JSON.stringify(this.pcOptions));
var pc = new RTCPeerConnection(this.pcConfig, this.pcOptions);
var streamer = this;
pc.onicecandidate = function(evt) { streamer.onIceCandidate.call(streamer, evt); };
pc.onaddstream = function(evt) { streamer.onAddStream.call(streamer,evt); };
pc.oniceconnectionstatechange = function(evt) {
console.log("oniceconnectionstatechange state: " + pc.iceConnectionState);
var videoElement = document.getElementById(streamer.videoElement);
if (videoElement) {
if (pc.iceConnectionState === "connected") {
videoElement.style.opacity = "1.0";
}
else if (pc.iceConnectionState === "disconnected") {
videoElement.style.opacity = "0.25";
}
else if ( (pc.iceConnectionState === "failed") || (pc.iceConnectionState === "closed") ) {
videoElement.style.opacity = "0.5";
}
}
}
pc.ondatachannel = function(evt) {
console.log("remote datachannel created:"+JSON.stringify(evt));
evt.channel.onopen = function () {
console.log("remote datachannel open");
this.send("remote channel openned");
}
evt.channel.onmessage = function (event) {
console.log("remote datachannel recv:"+JSON.stringify(event.data));
}
}
try { var dataChannel = pc.createDataChannel("ClientDataChannel"); dataChannel.onopen = function() { console.log("local datachannel open"); this.send("local channel openned"); } dataChannel.onmessage = function(evt) { console.log("local datachannel recv:"+JSON.stringify(evt.data)); } } catch (e) { console.log("Cannor create datachannel error: " + e); }
console.log("Created RTCPeerConnnection with config: " + JSON.stringify(this.pcConfig) + "option:"+ JSON.stringify(this.pcOptions) ); return pc; }
/*
/*
RTCPeerConnection AddTrack callback */ WebRtcStreamer.prototype.onAddStream = function(event) { console.log("Remote track added:" + JSON.stringify(event));
var videoElement = document.getElementById(this.videoElement); videoElement.srcObject = event.stream; var promise = videoElement.play(); if (promise !== undefined) { promise.catch(error => { console.warn("error:"+error); videoElement.setAttribute("controls", true); }); } }
/*
AJAX /call callback */ WebRtcStreamer.prototype.onReceiveCall = function(dataJson) { var bind = this; console.log("offer: " + JSON.stringify(dataJson)); this.pc.setRemoteDescription(new RTCSessionDescription(dataJson) , function() { console.log ("setRemoteDescription ok"); while (bind.earlyCandidates.length) { var candidate = bind.earlyCandidates.shift();
request("POST" , bind.srvurl + "/api/addIceCandidate?peerid=" + bind.pc.peerid, { body: JSON.stringify(candidate) })
.done( function (response) {
if (response.statusCode === 200) {
console.log("addIceCandidate ok:" + response.body);
}
else {
bind.onError(response.statusCode);
}
}
);
}
request("GET" , bind.srvurl + "/api/getIceCandidate?peerid=" + bind.pc.peerid)
.done( function (response) {
if (response.statusCode === 200) {
bind.onReceiveCandidate.call(bind,JSON.parse(response.body));
}
else {
bind.onError(response.statusCode);
}
}
);
}
, function(error) {
console.log ("setRemoteDescription error:" + JSON.stringify(error));
});
}
/*
AJAX /getIceCandidate callback */ WebRtcStreamer.prototype.onReceiveCandidate = function(dataJson) { console.log("candidate: " + JSON.stringify(dataJson)); if (dataJson) { for (var i=0; i<dataJson.length; i++) { var candidate = new RTCIceCandidate(dataJson[i]);
console.log("Adding ICE candidate :" + JSON.stringify(candidate) );
this.pc.addIceCandidate(candidate
, function() { console.log ("addIceCandidate OK"); }
, function(error) { console.log ("addIceCandidate error:" + JSON.stringify(error)); } );
}
this.pc.addIceCandidate();
} }
/*
------ webrtcstreamer.html
Best regards, Jeff Yang
Hi Jeff, I don't understand what do you expected publishing webrtcstreamer.js. If you notice a problem in it, feel free to submit a pull request. Best Regards, Michel.
Thanks for your help. I just figured out this issue.
Hi Jeff,
One of the difference could be the options used by the rtsp connection.
By default index.html served by internal server ask for stream RTP over TCP, in the index.html served by your external HTTP server no options specified and then RTP is streamed over UDP.
Maybe the UDP is not reaching the RTSP consumer.
In order to configure RTP over TCP you can use
<html>
<head>
<script src="libs/request.min.js" ></script>
<script src="libs/adapter.min.js" ></script>
<script src="webrtcstreamer.js" ></script>
<script>
var webRtcServer = new WebRtcStreamer("video",location.protocol+"//"+window.location.hostname+":8000");
window.onload = function() { webRtcServer.connect("rtsp://184.72.239.149/vod/mp4:BigBuckBunny_175k.mov","","rtptransport=tcp") }
window.onbeforeunload = function() { webRtcServer.disconnect() }
</script>
</head>
<body>
<video id="video" />
</body>
</html>
Best Regards, Michel.
Tried to use the following way to access webrtc streamer in the NGINX http server. The nginx and the webrtc streamer were run in the same machine. But I can not see the video be shown in the browser and got some running exceptions which described as below.
exception log: ./webrtc-streamer -C streams.json Logger level:3 HTTP Listen at 0.0.0.0:8000 [000:000] [16874] (PeerConnectionManager.h:216): virtual void PeerConnectionManager::PeerConnectionObserver::OnRenegotiationNeeded() peerid:0.6662036064052618 [000:002] [16874] (PeerConnectionManager.h:222): virtual void PeerConnectionManager::PeerConnectionObserver::OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState) state:3 peerid:0.6662036064052618 [000:006] [16878] (PeerConnectionManager.cpp:823): audiourl:rtptransport=tcp idx_audioDevice:-1 [000:006] [16878] (PeerConnectionManager.cpp:834): Cannot create capturer audio:rtptransport=tcp [000:006] [16874] (PeerConnectionManager.h:216): virtual void PeerConnectionManager::PeerConnectionObserver::OnRenegotiationNeeded() peerid:0.6662036064052618 Created new TCP socket [000:007] [16874] (PeerConnectionManager.h:222): virtual void PeerConnectionManager::PeerConnectionObserver::OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState) state:0 peerid:0.6662036064052618 82 for connection Connecting to 192.168.0.65, port 554 on socket 82... ...remote connection opened Sending request: DESCRIBE rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream RTSP/1.0 CSeq: 2 User-Agent: LIVE555 Streaming Media v2019.03.06 Accept: application/sdp
Received 756 new bytes of response data. Received a complete DESCRIBE response: RTSP/1.0 200 OK CSeq: 2 Content-Type: application/sdp Content-Base: rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/ Content-Length: 597
v=0 o=- 1555496032394195 1555496032394195 IN IP4 192.168.0.65 s=Media Presentation e=NONE b=AS:5050 t=0 0 a=control:rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/ m=video 0 RTP/AVP 96 c=IN IP4 0.0.0.0 b=AS:5000 a=recvonly a=control:rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/trackID=1 a=rtpmap:96 H264/90000 a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z00AFJWoWCWhAAAHCAABX5AE,aO48gA== a=Media_header:MEDIAINFO=494D4B48010200000400000100000000000000000000000000000000000000000000000000000000; a=appversion:1.0
Sending request: SETUP rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/trackID=1 RTSP/1.0 CSeq: 3 User-Agent: LIVE555 Streaming Media v2019.03.06 Transport: RTP/AVP;unicast;client_port=38104-38105
[000:025] [16874] (PeerConnectionManager.h:133): virtual void PeerConnectionManager::DataChannelObserver::OnStateChange() channel:ServerDataChannel state:open [000:026] [16874] (PeerConnectionManager.h:212): virtual void PeerConnectionManager::PeerConnectionObserver::OnDataChannel(rtc::scoped_refptr)
[000:026] [16874] (PeerConnectionManager.h:133): virtual void PeerConnectionManager::DataChannelObserver::OnStateChange() channel:ClientDataChannel state:open
Received 204 new bytes of response data.
Received a complete SETUP response:
RTSP/1.0 200 OK
CSeq: 3
Session: 1898422682;timeout=60
Transport: RTP/AVP;unicast;client_port=38104-38105;server_port=8248-8249;ssrc=1c06c40b;mode="play"
Date: Wed, Apr 17 2019 10:13:52 GMT
Start playing sink for "video/H264" subsession markerSize:4 Sending request: PLAY rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/ RTSP/1.0 CSeq: 4 User-Agent: LIVE555 Streaming Media v2019.03.06 Session: 1898422682 Range: npt=0.000-
[000:055] [16874] (PeerConnectionManager.h:140): virtual void PeerConnectionManager::DataChannelObserver::OnMessage(const webrtc::DataBuffer&) channel:ClientDataChannel msg:local channel openned [000:063] [16874] (PeerConnectionManager.h:140): virtual void PeerConnectionManager::DataChannelObserver::OnMessage(const webrtc::DataBuffer&) channel:ServerDataChannel msg:remote channel openned Received 210 new bytes of response data. Received a complete PLAY response: RTSP/1.0 200 OK CSeq: 4 Session: 1898422682 RTP-Info: url=rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/trackID=1;seq=10332;rtptime=2497263682 Date: Wed, Apr 17 2019 10:13:52 GMT
Close session: video/H264 Created new TCP socket 65 for connection Connecting to 192.168.0.65, port 554 on socket 65... ...remote connection opened Sending request: DESCRIBE rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream RTSP/1.0 CSeq: 2 User-Agent: LIVE555 Streaming Media v2019.03.06 Accept: application/sdp
Received 756 new bytes of response data. Received a complete DESCRIBE response: RTSP/1.0 200 OK CSeq: 2 Content-Type: application/sdp Content-Base: rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/ Content-Length: 597
v=0 o=- 1555496042560709 1555496042560709 IN IP4 192.168.0.65 s=Media Presentation e=NONE b=AS:5050 t=0 0 a=control:rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/ m=video 0 RTP/AVP 96 c=IN IP4 0.0.0.0 b=AS:5000 a=recvonly a=control:rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/trackID=1 a=rtpmap:96 H264/90000 a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z00AFJWoWCWhAAAHCAABX5AE,aO48gA== a=Media_header:MEDIAINFO=494D4B48010200000400000100000000000000000000000000000000000000000000000000000000; a=appversion:1.0
Sending request: SETUP rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/trackID=1 RTSP/1.0 CSeq: 3 User-Agent: LIVE555 Streaming Media v2019.03.06 Transport: RTP/AVP;unicast;client_port=43276-43277
Received 204 new bytes of response data. Received a complete SETUP response: RTSP/1.0 200 OK CSeq: 3 Session: 102894382;timeout=60 Transport: RTP/AVP;unicast;client_port=43276-43277;server_port=8250-8251;ssrc=5bd14ed9;mode="play" Date: Wed, Apr 17 2019 10:14:02 GMT
Start playing sink for "video/H264" subsession markerSize:4 Sending request: PLAY rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/ RTSP/1.0 CSeq: 4 User-Agent: LIVE555 Streaming Media v2019.03.06 Session: 102894382 Range: npt=0.000-
Received 210 new bytes of response data. Received a complete PLAY response: RTSP/1.0 200 OK CSeq: 4 Session: 102894382 RTP-Info: url=rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/trackID=1;seq=10607;rtptime=2498181502 Date: Wed, Apr 17 2019 10:14:02 GMT
Close session: video/H264 Created new TCP socket 65 for connection Connecting to 192.168.0.65, port 554 on socket 65... ...remote connection opened Sending request: DESCRIBE rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream RTSP/1.0 CSeq: 2 User-Agent: LIVE555 Streaming Media v2019.03.06 Accept: application/sdp
Received 756 new bytes of response data. Received a complete DESCRIBE response: RTSP/1.0 200 OK CSeq: 2 Content-Type: application/sdp Content-Base: rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/ Content-Length: 597
v=0 o=- 1555496052716894 1555496052716894 IN IP4 192.168.0.65 s=Media Presentation e=NONE b=AS:5050 t=0 0 a=control:rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/ m=video 0 RTP/AVP 96 c=IN IP4 0.0.0.0 b=AS:5000 a=recvonly a=control:rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/trackID=1 a=rtpmap:96 H264/90000 a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z00AFJWoWCWhAAAHCAABX5AE,aO48gA== a=Media_header:MEDIAINFO=494D4B48010200000400000100000000000000000000000000000000000000000000000000000000; a=appversion:1.0
Sending request: SETUP rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/trackID=1 RTSP/1.0 CSeq: 3 User-Agent: LIVE555 Streaming Media v2019.03.06 Transport: RTP/AVP;unicast;client_port=41690-41691
Received 204 new bytes of response data. Received a complete SETUP response: RTSP/1.0 200 OK CSeq: 3 Session: 531847360;timeout=60 Transport: RTP/AVP;unicast;client_port=41690-41691;server_port=8254-8255;ssrc=418e8b9c;mode="play" Date: Wed, Apr 17 2019 10:14:12 GMT
Start playing sink for "video/H264" subsession markerSize:4 Sending request: PLAY rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/ RTSP/1.0 CSeq: 4 User-Agent: LIVE555 Streaming Media v2019.03.06 Session: 531847360 Range: npt=0.000-
Received 210 new bytes of response data. Received a complete PLAY response: RTSP/1.0 200 OK CSeq: 4 Session: 531847360 RTP-Info: url=rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/trackID=1;seq=44168;rtptime=2499092122 Date: Wed, Apr 17 2019 10:14:12 GMT
Close session: video/H264 Created new TCP socket 65 for connection Connecting to 192.168.0.65, port 554 on socket 65... ...remote connection opened Sending request: DESCRIBE rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream RTSP/1.0 CSeq: 2 User-Agent: LIVE555 Streaming Media v2019.03.06 Accept: application/sdp
Received 756 new bytes of response data. Received a complete DESCRIBE response: RTSP/1.0 200 OK CSeq: 2 Content-Type: application/sdp Content-Base: rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/ Content-Length: 597
v=0 o=- 1555496062834938 1555496062834938 IN IP4 192.168.0.65 s=Media Presentation e=NONE b=AS:5050 t=0 0 a=control:rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/ m=video 0 RTP/AVP 96 c=IN IP4 0.0.0.0 b=AS:5000 a=recvonly a=control:rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/trackID=1 a=rtpmap:96 H264/90000 a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z00AFJWoWCWhAAAHCAABX5AE,aO48gA== a=Media_header:MEDIAINFO=494D4B48010200000400000100000000000000000000000000000000000000000000000000000000; a=appversion:1.0
Sending request: SETUP rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/trackID=1 RTSP/1.0 CSeq: 3 User-Agent: LIVE555 Streaming Media v2019.03.06 Transport: RTP/AVP;unicast;client_port=38352-38353
Received 204 new bytes of response data. Received a complete SETUP response: RTSP/1.0 200 OK CSeq: 3 Session: 1014818784;timeout=60 Transport: RTP/AVP;unicast;client_port=38352-38353;server_port=8258-8259;ssrc=6059881e;mode="play" Date: Wed, Apr 17 2019 10:14:22 GMT
Start playing sink for "video/H264" subsession markerSize:4 Sending request: PLAY rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/ RTSP/1.0 CSeq: 4 User-Agent: LIVE555 Streaming Media v2019.03.06 Session: 1014818784 Range: npt=0.000-
Received 210 new bytes of response data. Received a complete PLAY response: RTSP/1.0 200 OK CSeq: 4 Session: 1014818784 RTP-Info: url=rtsp://admin:qzj123456@192.168.0.65:554/h264/ch1/sub/av_stream/trackID=1;seq=11158;rtptime=2500002742 Date: Wed, Apr 17 2019 10:14:22 GMT
^C