gpt4 book ai didi

javascript - Webrtc 远程视频流不工作

转载 作者:搜寻专家 更新时间:2023-11-01 04:30:18 24 4
gpt4 key购买 nike

在设置 remoteDescription 时,我在 firefox 中遇到以下错误:

DOMException [InvalidStateError: “无法在状态 have-local-offer 中设置远程报价”代码:11nsresult: 0x8053000b地点:http://localhost:8080/resources/assets/js/test-online.js:111]

请在下面找到我的 test-online.js 代码

var localVideo;
var remoteVideo;
var peerConnection;
var serverConnection;
var peerConnectionConfig = {'iceServers': [{'url': 'stun:stun.services.mozilla.com'}, {'url': 'stun:stun.l.google.com:19302'}]};
pageReady();
var offerOptions = {
offerToReceiveAudio: 1,
offerToReceiveVideo: 1
};

var sdpConstraints = {'mandatory': {
'OfferToReceiveAudio':true,
'OfferToReceiveVideo':true }};

function pageReady() {
localVideo = document.getElementById('localVideo');
remoteVideo = document.getElementById('remoteVideo');

localVideo.addEventListener('loadedmetadata', function() {
trace('Local video videoWidth: ' + this.videoWidth +
'px, videoHeight: ' + this.videoHeight + 'px');
});

remoteVideo.addEventListener('loadedmetadata', function() {
trace('Remote video videoWidth: ' + this.videoWidth +
'px, videoHeight: ' + this.videoHeight + 'px');
});

remoteVideo.onresize = function() {
trace('Remote video size changed to ' +
remoteVideo.videoWidth + 'x' + remoteVideo.videoHeight);
// We'll use the first onsize callback as an indication that video has started
// playing out.
if (startTime) {
var elapsedTime = window.performance.now() - startTime;
trace('Setup time: ' + elapsedTime.toFixed(3) + 'ms');
startTime = null;
}
};

serverConnection = new SockJS("/onlineHandler");

serverConnection.onopen = function() {
console.log("Opening server connection");
};
serverConnection.onmessage = gotMessageFromServer;
serverConnection.onclose = function() {
console.log("Closing server connection");
};
//serverConnection.onmessage = gotMessageFromServer;

var constraints = {
video: true,
audio: true,
};

navigator.mediaDevices.getUserMedia(constraints)
.then(getUserMediaSuccess)
.catch(function(e) {
alert('getUserMedia() error: ' + e.name);
});
}

function getUserMediaSuccess(stream) {
trace('Received local stream');
localVideo.srcObject = stream;
localStream = stream;
}

function start(isCaller) {
trace('Starting call');
startTime = window.performance.now();
var videoTracks = localStream.getVideoTracks();
var audioTracks = localStream.getAudioTracks();
if (videoTracks.length > 0) {
trace('Using video device: ' + videoTracks[0].label);
}
if (audioTracks.length > 0) {
trace('Using audio device: ' + audioTracks[0].label);
}

peerConnection = new RTCPeerConnection(peerConnectionConfig);
peerConnection.onicecandidate = gotIceCandidate;
peerConnection.oniceconnectionstatechange = onIceStateChange;
peerConnection.onaddStream = gotRemoteStream;
peerConnection.addStream(localStream);

if(isCaller) {
peerConnection.createOffer(gotDescription, errorHandler , offerOptions);
}
}

function gotMessageFromServer(message) {
/* if(!peerConnection) start(false);

var signal = JSON.parse(message.data);
// console.log("Got Message from server :" + message.data);
if(signal.sdp) {;
console.log("hi in sdp" + message.data);
peerConnection.setRemoteDescription(new RTCSessionDescription(signal.sdp), function() {
console.log("Creating answer :");
if (peerConnection.remoteDescription.type == 'offer')
peerConnection.createAnswer(gotDescription, errorHandler);
}, errorHandler);
} else if(signal.ice) {
peerConnection.addIceCandidate(new RTCIceCandidate(signal.ice));
}*/
var signal = JSON.parse(message.data);
if (signal.type === 'offer') {
peerConnection.setRemoteDescription(new RTCSessionDescription(signal),doAnswer,errorHandler);
} else if (signal.type === 'answer') {
peerConnection.setRemoteDescription(new RTCSessionDescription(signal),doNothing, errorHandler);
} else if (signal.type === 'candidate') {
var candidate = new RTCIceCandidate({
sdpMLineIndex:signal.label,
candidate: signal.candidate
});
peerConnection.addIceCandidate(candidate);
} else if (signal === 'bye' && isStarted) {
handleRemoteHangup();
}
}
function doNothing(){

}

function doAnswer() {
console.log('Sending answer to peer.');
peerConnection.createAnswer(gotDescription, errorHandler, sdpConstraints);
}

function handleRemoteHangup() {
// console.log('Session terminated.');
// stop();
// isInitiator = false;
}

function gotIceCandidate(event) {
if(event.candidate != null) {

var message ={
type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate};

// serverConnection.send(JSON.stringify({'ice': event.candidate}));
serverConnection.send(JSON.stringify(message));
}
}

function onIceStateChange(event) {
if (peerConnection) {
trace(' ICE state: ' + peerConnection.iceConnectionState);
console.log('ICE state change event: ', event);
}
}

function gotDescription(description) {
// trace('Offer from peerConnection\n' + description.sdp);
description.sdp = preferOpus(description.sdp);
// pc.setLocalDescription(description);
console.log('setLocalAndSendMessage sending message' , description);
// trace('peerConnection setLocalDescription start');
peerConnection.setLocalDescription(
description,
function () {
serverConnection.send(JSON.stringify(description));
},
onSetSessionDescriptionError
);
}

function preferOpus(sdp) {
var sdpLines = sdp.split('\r\n');
var mLineIndex;
// Search for m line.
for (var i = 0; i < sdpLines.length; i++) {
if (sdpLines[i].search('m=audio') !== -1) {
mLineIndex = i;
break;
}
}
if (mLineIndex === null) {
return sdp;
}

// If Opus is available, set it as the default in m line.
for (i = 0; i < sdpLines.length; i++) {
if (sdpLines[i].search('opus/48000') !== -1) {
var opusPayload = extractSdp(sdpLines[i], /:(\d+) opus\/48000/i);
if (opusPayload) {
sdpLines[mLineIndex] = setDefaultCodec(sdpLines[mLineIndex], opusPayload);
}
break;
}
}

// Remove CN in m line and sdp.
sdpLines = removeCN(sdpLines, mLineIndex);

sdp = sdpLines.join('\r\n');
return sdp;
}

function extractSdp(sdpLine, pattern) {
var result = sdpLine.match(pattern);
return result && result.length === 2 ? result[1] : null;
}

// Set the selected codec to the first in m line.
function setDefaultCodec(mLine, payload) {
var elements = mLine.split(' ');
var newLine = [];
var index = 0;
for (var i = 0; i < elements.length; i++) {
if (index === 3) { // Format of media starts from the fourth.
newLine[index++] = payload; // Put target payload to the first.
}
if (elements[i] !== payload) {
newLine[index++] = elements[i];
}
}
return newLine.join(' ');
}

// Strip CN from sdp before CN constraints is ready.
function removeCN(sdpLines, mLineIndex) {
var mLineElements = sdpLines[mLineIndex].split(' ');
// Scan from end for the convenience of removing an item.
for (var i = sdpLines.length-1; i >= 0; i--) {
var payload = extractSdp(sdpLines[i], /a=rtpmap:(\d+) CN\/\d+/i);
if (payload) {
var cnPos = mLineElements.indexOf(payload);
if (cnPos !== -1) {
// Remove CN payload from m line.
mLineElements.splice(cnPos, 1);
}
// Remove CN line in sdp
sdpLines.splice(i, 1);
}
}

sdpLines[mLineIndex] = mLineElements.join(' ');
return sdpLines;
}


function onSetSessionDescriptionError(error) {
trace('Failed to set session description: ' + error.toString());
}

function gotRemoteStream(event) {
remoteVideo.srcObject = event.stream;
trace('Received remote stream');
}

function errorHandler(error) {
console.log(error);
}

我的 html 代码如下:

    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html lang="en">
<head>
<link
href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css"
rel="stylesheet">
<!-- Meta tag to not followed by search engine. -->
<meta name="robots" content="noindex,nofollow,nosnippet,noodp,noarchive">
<meta name="keywords" content="JavaScript, WebRTC" />
<meta name="description" content="WebRTC codelab" />
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1">

<style>
video {
filter: hue-rotate(180deg) saturate(200%);
-moz-filter: hue-rotate(180deg) saturate(200%);
-webkit-filter: hue-rotate(180deg) saturate(200%);
/*-webkit-filter: grayscale(0.3) hue-rotate(360deg) saturate(10) opacity(0.7) sepia(0.5); */
}
</style>
</head>
<body>


<div id='videos'>
<video id='localVideo' autoplay muted></video>
<video id='remoteVideo' autoplay></video>
</div>

<input type="button" id="start" onclick="start(true)" value="Start Video"></input>
<script src="//cdn.jsdelivr.net/sockjs/1.0.0/sockjs.min.js"></script>
<script
src="${pageContext.request.contextPath}/resources/assets/js/jquery-2.1.1.min.js"></script>
<script
src="${pageContext.request.contextPath}/resources/assets/js/bootstrap.min.js"></script>
<script src ="${pageContext.request.contextPath}/resources/assets/js/adapter-0.2.10.js"></script>
<script src="${pageContext.request.contextPath}/resources/assets/js/test-online.js"></script>
</body>
</html>

我无法理解我在这里做错了什么。我仍然是 webrtc 领域的新手,只是想在我的代码中运行这个基本的东西。

最佳答案

offer-answer 交换是一个状态机,某些方法在某些状态下是不允许的。

调用setLocalDescription(或setRemoteDescription)将信令状态更改为“have-local-offer”(或“have-远程报价").

此时,应用程序的工作是将状态恢复为stableclosed,如described in the spec .

例如,应用程序负责处理眩光(这是双方同时发送报价的地方)。

还有a bug在 Firefox 中,它不允许您在 have-local-offer 中再次调用 createOffersetLocalDescription ,反之亦然(上面链接的规范中状态图中的小环)。但是从您的错误消息中听起来并不像您正在点击它。

关于javascript - Webrtc 远程视频流不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35552937/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com