如何使用attachMediaStream?

kea*_*kea 3 javascript webrtc

我尝试通过WebRTC socket.io测试一个视频通话和聊天练习。我无法在firefox上收到控制台错误,但无法攻击它们之间的两个本地/远程流。我的浏览器代码是这个

'use strict';
var p = navigator.mediaDevices.getUserMedia ({video: true, audio: true});
// Clean-up function:
// collect garbage before unloading browser's window
window.onbeforeunload = function(e){
hangup();
}
// Data channel information
var sendChannel, receiveChannel;
var sendButton = document.getElementById("sendButton");
var sendTextarea = document.getElementById("dataChannelSend");
var receiveTextarea = document.getElementById("dataChannelReceive");
// HTML5 <video> elements
var localVideo = document.querySelector('#localVideo');
var remoteVideo = document.querySelector('#remoteVideo');
// Handler associated with Send button
sendButton.onclick = sendData;
// Flags...
var isChannelReady = false;
var isInitiator = false;
var isStarted = false;
// WebRTC data structures
// Streams
var SStream;
var BStream;
var localStream;
var remoteStream;
// PeerConnection
var pc;
var pc_constraints = {
'optional': [
{'DtlsSrtpKeyAgreement': true}
]};
var sdpConstraints = {};
// Let's get started: prompt user for input (room name)
var room = prompt('Enter room name:');
// Connect to signaling server
var socket = io.connect("http://localhost:8181");
// Send 'Create or join' message to singnaling server
if (room !== '') {
console.log('Create or join room ', room);
socket.emit('create or join',room);
}


// Server-mediated message exchanging...
// 1. Server-->Client...
// this peer is the initiator

socket.on('created', function (room){
console.log('Created room ' + room);
isInitiator = true;
// Call getUserMedia()
				p.then (function (MediaStream) {
				SStream=MediaStream;
				localVideo.src = window.URL.createObjectURL (MediaStream);
				localVideo.onloadedmetadata = function (e) {
				console.log("add local stream");
				sendMessage('got user media');
				};
				});
				p.catch (function (err) {console.log (err.name);});
			checkAndStart();
			});
			
// Handle 'join' message coming back from server:
// another peer is joining the channel
			socket.on('join',function(room){
			console.log('this peer is the iniator of room '+room+' !');
			isChannelReady=true;
			})

// Handle 'joined' message coming back from server:
// this is the second peer joining the channel
			socket.on('joined', function (room){
			console.log('This peer has joined room ' + room);
			isChannelReady = true;
		// Call getUserMedia()
			p.then (function (MediaStream) {
			isChannelReady = true;
			BStream=MediaStream;
			remoteVideo.src = window.URL.createObjectURL (MediaStream);
			remoteVideo.onloadedmetadata = function (e) {
			console.log("add remote stream");
			sendMessage('got user media');
			};
			});
			p.catch (function (err) {console.log (err.name);});
			});

			
			
// Server-sent log message...
			socket.on('log', function (array){
			console.log.apply(console, array);
			});
// Receive message from the other peer via the signaling server
socket.on('message', function (message){
console.log('Received message: ', message);
	if (message === 'got user media') {
		console.log('sono in if');
		checkAndStart();
	} 
		else if (message.type === 'offer') {
				if (!isInitiator && !isStarted) {
					checkAndStart();
				}
			pc.setRemoteDescription(new RTCSessionDescription(message));
			doAnswer();
			}		 
				else if (message.type === 'answer' && isStarted) {
				pc.setRemoteDescription(new RTCSessionDescription(message));
				} 
					else if (message.type === 'candidate' && isStarted) {
					var candidate = new RTCIceCandidate({sdpMLineIndex:message.label,candidate:message.candidate});
					pc.addIceCandidate(candidate);
					}
						else if (message === 'bye' && isStarted) {
						handleRemoteHangup();
						}	
});



// 2. Client-->Server
// Send message to the other peer via the signaling server
function sendMessage(message){
console.log('Sending message: ', message);
socket.emit('message', message);
}
// Channel negotiation trigger function
function checkAndStart() {
if (!isStarted && isChannelReady) {
	createPeerConnection();
isStarted = true;
if (isInitiator) {
doCall();
}
}
}
// PeerConnection management...
function createPeerConnection() {
try {
/*posso aggiungere turn, google ecc...*/
	pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:93.33.165.245' }] }, {
	'optional': [
	{'DtlsSrtpKeyAgreement': true}
	]});

	if(isInitiator){
		SStream.getTracks().forEach(track => pc.addTrack(track,SStream));
		pc.ontrack= handleRemoteStreamAdded;}
	else{
		BStream.getTracks().forEach(track => pc.addTrack(track,BStream));}
	pc.onicecandidate = handleIceCandidate;
	console.log('create RTCPeerConnection');
	} 
catch (e) {
	console.log('Failed to create PeerConnection, exception: ' + e.message);
	alert('Cannot create RTCPeerConnection object.');
return;
}
pc.ontrack= handleRemoteStreamAdded;
pc.onremovestream = handleRemoteStreamRemoved;
if (isInitiator) {
try {
// Create a reliable data channel
sendChannel = pc.createDataChannel("sendDataChannel",
{reliable: true});
console.log('Created send data channel');
} catch (e) {
alert('Failed to create data channel. ');
console.log('createDataChannel() failed with exception: ' + e.message);
}
sendChannel.onopen = handleSendChannelStateChange;
sendChannel.onmessage = handleMessage;
sendChannel.onclose = handleSendChannelStateChange;
} else { // Joiner
pc.ondatachannel = gotReceiveChannel;
}
}
// Data channel management
function sendData() {
var data = sendTextarea.value;
if(isInitiator) sendChannel.send(data);
else receiveChannel.send(data);
console.log('Sent data: ' + data);
}
// Handlers...
function gotReceiveChannel(event) {
console.log('Receive Channel Callback');
receiveChannel = event.channel;
receiveChannel.onmessage = handleMessage;
receiveChannel.onopen = handleReceiveChannelStateChange;
receiveChannel.onclose = handleReceiveChannelStateChange;
}
function handleMessage(event) {
console.log('Received message: ' + event.data);
receiveTextarea.value += event.data + '\n';
}
function handleSendChannelStateChange() {
var readyState = sendChannel.readyState;
console.log('Send channel state is: ' + readyState);
// If channel ready, enable user's input
if (readyState == "open") {
dataChannelSend.disabled = false;
dataChannelSend.focus();
dataChannelSend.placeholder = "";
sendButton.disabled = false;
} else {
dataChannelSend.disabled = true;
sendButton.disabled = true;
}
}
function handleReceiveChannelStateChange() {
var readyState = receiveChannel.readyState;
console.log('Receive channel state is: ' + readyState);
// If channel ready, enable user's input
if (readyState == "open") {
dataChannelSend.disabled = false;
dataChannelSend.focus();
dataChannelSend.placeholder = "";
sendButton.disabled = false;
} else {
dataChannelSend.disabled = true;
sendButton.disabled = true;
}
}



// ICE candidates management
function handleIceCandidate(event) {
console.log('handleIceCandidate event: ', event);
if (event.candidate) {
sendMessage({
type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate});
} else {
console.log('End of candidates.');
}
}
// Create Offer
function doCall() {
console.log('Creating Offer...');
pc.createOffer(setLocalAndSendMessage, onSignalingError, sdpConstraints);
}
// Signaling error handler
function onSignalingError(error) {
console.log('Failed to create signaling message : ' + error.name);
}
// Create Answer
function doAnswer() {
console.log('Sending answer to peer.');
pc.createAnswer(setLocalAndSendMessage, onSignalingError, sdpConstraints);
}
// Success handler for both createOffer()
// and createAnswer()
function setLocalAndSendMessage(sessionDescription) {
pc.setLocalDescription(sessionDescription);
sendMessage(sessionDescription);
}
// Remote stream handlers...
function handleRemoteStreamAdded(event) {
attachMediaStream(BStream, event.stream);
BStream = event.stream;
}
function handleRemoteStreamRemoved(event) {
console.log('Remote stream removed. Event: ', event);
}
// Clean-up functions...
function hangup() {
console.log('Hanging up.');
stop();
sendMessage('bye');
}
function handleRemoteHangup() {
console.log('Session terminated.');
stop();
isInitiator = false;
}
function stop() {
isStarted = false;
if (sendChannel) sendChannel.close();
if (receiveChannel) receiveChannel.close();
if (pc) pc.close();
pc = null;
sendButton.disabled=true;
}
Run Code Online (Sandbox Code Playgroud)

有人告诉我我错了哪里以及如何解决?

jib*_*jib 5

attachMediaStream不属于WebRTC。这是一个用于显示设置或(Chrome仍不支持,但Canary支持)的shim adapter.jsvideo.srcvideo.srcObject

无论如何,您传递的参数都是错误的,应该是一个元素和一个流,而不是两个流。即做到:

attachMediaStream(remoteVideo, event.streams[0]);
Run Code Online (Sandbox Code Playgroud)

或更好,请使用adapter.js现在在所有浏览器上支持的规范方式:

remoteVideo.srcObject = event.streams[0];
Run Code Online (Sandbox Code Playgroud)

重要提示:pc.ontrack事件包含event.streams(复数),而不是event.stream!-这是一个数组,因为一个轨道可能(但很少有)存在于多个流中。

如果您没有使用最新的adapter.js,那么请注意,该功能pc.ontrack目前仅在Firefox中本地可用,因此在Chrome中,您将需要较旧的pc.onaddstream(及其event.stream)。

PS:您当前正在设置remoteVideo.src本地视频。不要那样做

PPS:删除pc_constraints。确实很老的东西会破坏Chrome。

这是ontrack(在Chrome中使用https小提琴)的演示:

attachMediaStream(remoteVideo, event.streams[0]);
Run Code Online (Sandbox Code Playgroud)
remoteVideo.srcObject = event.streams[0];
Run Code Online (Sandbox Code Playgroud)