我添加了一个简单的webRTC应用程序,它将在其中连接浏览器窗口,从我的相机流式传输视频数据。最终目标是在页面上获得两个视频流,一个视频流直接来自相机,另一个来自浏览器在本地建立的WebRTC连接。
不幸的是,远程视频流没有显示。知道为什么吗?
<video id="yours" autoplay></video>
<video id="theirs" autoplay></video>
这是JavaScript
function hasUserMedia() {
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia ||
navigator.msGetUserMedia;
return !!navigator.getUserMedia;
}
function hasRTCPeerConnection() {
window.RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection
|| window.mozRTCPeerConnection;
return !!window.RTCPeerConnection;
}
var yourVideo = document.querySelector('#yours'),
theirVideo = document.querySelector('#theirs'),
yourConnection, theirConnection;
if (hasUserMedia()) {
navigator.getUserMedia({ video: true, audio: false }, function(stream) {
yourVideo.src = window.URL.createObjectURL(stream);
if (hasRTCPeerConnection()) {
startPeerConnection(stream);
} else {
alert("Sorry, your browser does not support WebRTC.");
}
}, function (error) {
console.log(error);
});
}else{
alert("Sorry, your browser does not support WebRTC.");
}
function startPeerConnection(stream){
var configuration = {
"iceServers": [{ "url": "stun:stun.1.google.com:19302"
}]
};
yourConnection = new RTCPeerConnection(configuration);
theirConnection = new RTCPeerConnection(configuration);
// Setup stream listening
yourConnection.addStream(stream);
theirConnection.onaddstream = function (event) {
theirVideo.src = window.URL.createObjectURL(event.stream);
console.log('stream added');
};
// console.log(yourConnection);
//console.log(theirConnection);
// Setup ice handling
yourConnection.onicecandidate = function (event) {
if (event.candidate) {
theirConnection.addIceCandidate(new RTCIceCandidate(event.
candidate));
}
};
theirConnection.onicecandidate = function (event) {
if (event.candidate) {
yourConnection.addIceCandidate(new RTCIceCandidate(event.
candidate));
}
};
// Begin the offer
yourConnection.createOffer(function (offer) {
yourConnection.setLocalDescription(offer);
theirConnection.setRemoteDescription(offer);
theirConnection.createAnswer(function (offer) {
theirConnection.setLocalDescription(offer);
yourConnection.setRemoteDescription(offer);
});
});
};
我正在关注Dan Ristic关于WebRTC的书,并了解他在编码方面的工作。不幸的是,远程视频没有显示。
添加故障回调以使其正常工作。您不仅不会看到其他错误,而且这样做确实可以使它正常工作,原因很奇怪:
您是所谓的WebIDL重载的受害者。发生了什么事,有两个版本的WebRTC API,并且您正在混合使用它们。
有一个现代的promise API,例如:
pc.createOffer(options).then(successCallback, failureCallback);
和已弃用的回调版本,例如:
pc.createOffer(successCallback, failureCallback, options);
换句话说,有两个createOffer
函数采用不同数量的参数。
不幸的是,您打第一个createOffer
是因为您只传递了一个参数!第一个createOffer
期望一个选项对象,不幸的是,在WebIDL中,该选项对象与功能是无法区分的。因此,它被视为有效参数(空选项对象)。即使这引起了TypeError
,也不会引起异常,因为Promise API拒绝返回的Promise而不是抛出异常:
pc.createOffer(3).catch(e => console.log("Here: "+ e.name)); // Here: TypeError
您也不会检查返回的承诺,因此会丢失错误。
这是一个有效的版本(适用于Chrome的https fiddle):
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
window.RTCPeerConnection = window.RTCPeerConnection ||
window.webkitRTCPeerConnection;
var yourConnection, theirConnection;
navigator.getUserMedia({ video: true, audio: false }, function(stream) {
yourVideo.src = window.URL.createObjectURL(stream);
var config = { "iceServers": [{ "urls": "stun:stun.1.google.com:19302"}] };
yourConnection = new RTCPeerConnection(config);
theirConnection = new RTCPeerConnection(config);
yourConnection.addStream(stream);
theirConnection.onaddstream = function (event) {
theirVideo.src = window.URL.createObjectURL(event.stream);
};
yourConnection.onicecandidate = function (e) {
if (e.candidate) {
theirConnection.addIceCandidate(new RTCIceCandidate(e.candidate),
success, failure);
}
};
theirConnection.onicecandidate = function (e) {
if (e.candidate) {
yourConnection.addIceCandidate(new RTCIceCandidate(e.candidate),
success, failure);
}
};
yourConnection.createOffer(function (offer) {
yourConnection.setLocalDescription(offer, success, failure);
theirConnection.setRemoteDescription(offer, success, failure);
theirConnection.createAnswer(function (offer) {
theirConnection.setLocalDescription(offer, success, failure);
yourConnection.setRemoteDescription(offer, success, failure);
}, failure);
}, failure);
}, failure);
function success() {};
function failure(e) { console.log(e); };
<video id="yourVideo" width="160" height="120" autoplay></video>
<video id="theirVideo" width="160" height="120" autoplay></video>
但是回调很费力。我强烈建议改用新的Promise API(Chrome浏览器为https):
var pc1 = new RTCPeerConnection(), pc2 = new RTCPeerConnection();
navigator.mediaDevices.getUserMedia({video: true, audio: true})
.then(stream => pc1.addStream(video1.srcObject = stream))
.catch(log);
var add = (pc, can) => pc.addIceCandidate(can).catch(log);
pc1.onicecandidate = e => add(pc2, e.candidate);
pc2.onicecandidate = e => add(pc1, e.candidate);
pc2.ontrack = e => video2.srcObject = e.streams[0];
pc1.oniceconnectionstatechange = e => log(pc1.iceConnectionState);
pc1.onnegotiationneeded = e =>
pc1.createOffer().then(d => pc1.setLocalDescription(d))
.then(() => pc2.setRemoteDescription(pc1.localDescription))
.then(() => pc2.createAnswer()).then(d => pc2.setLocalDescription(d))
.then(() => pc1.setRemoteDescription(pc2.localDescription))
.catch(log);
var log = msg => console.log(msg);
<video id="video1" height="120" width="160" autoplay muted></video>
<video id="video2" height="120" width="160" autoplay></video><br>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句