ler*_*ler 0 javascript video node.js webrtc
我的脚本在哪里。两个用户可以使用webrtc聊天。当两个用户进入聊天室时。文字聊天会自动开始。我想添加一个botton以允许视频聊天。例如,有两个用户。当user_1和user_2进入聊天室,发起文本聊天时,他们可以彼此发送短信,并且当user_1单击视频图标时,user_2可以看到user_1。和用户_2在单击视频图标时发生的事情相同。这是我现在使用的代码。但是此代码无法正常工作,当我统计与某人聊天并单击视频图标时,我可以看到自己,但另一个用户却看不到我。我没有发布所有代码,因为它超过了300行,但我想您不能帮我修改此设置以使其正常工作,在此先感谢大家。
var pc_config = webrtcDetectedBrowser === 'firefox' ?
{'iceServers':[{'url':'stun:23.21.150.121'}]} : // IP address
{'iceServers': [{'url': 'stun:stun.l.google.com:19302'}]};
var pc_constraints = {
'optional': [
{'DtlsSrtpKeyAgreement': true},
{'RtpDataChannels': true}
]};
var sdpConstraints = {'mandatory': {
'OfferToReceiveAudio':true,
'OfferToReceiveVideo':true }};
var constraints = {video: true, audio: true};
var v_on_off = false;
v_call.on('click', function(){
if (!v_on_off) {
navigator.getUserMedia(constraints, handleUserMedia, handleUserMediaError);
if (isInitiator) {
maybeStart();
};
v_on_off = true;
} else {
// stop stream
}
});
function handleUserMedia(stream) {
localStream = stream;
attachMediaStream(localVideo, stream);
sendMessage('got user media');
}
var socket = io.connect();
if (room !== '') {
socket.emit('create or join', room);
}
socket.on('created', function (room){
isInitiator = true;
});
socket.on('join', function (room){
isChannelReady = true;
});
socket.on('joined', function (room){
isChannelReady = true;
});
function sendMessage(message){
socket.emit('message', message);
}
// this will start a text chat between too peers
sendMessage('got user media');
if (isInitiator) {
maybeStart();
}
socket.on('message', function (message){
console.log('Received message:', message);
if (message === 'got user media') {
maybeStart();
} else if (message.type === 'offer') {
if (!isInitiator && !isStarted) {
maybeStart();
}
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();
}
});
function maybeStart() {
if (!isStarted && isChannelReady) {
createPeerConnection();
isStarted = true;
if (isInitiator) {
doCall();
}
}
}
function createPeerConnection() {
try {
pc = new RTCPeerConnection(pc_config, pc_constraints);
if (typeof localStream != 'undefined') {
pc.addStream(localStream);
}
pc.onicecandidate = handleIceCandidate;
} catch (e) {
alert('Cannot create RTCPeerConnection object.');
return;
}
pc.onaddstream = handleRemoteStreamAdded;
pc.onremovestream = handleRemoteStreamRemoved;
if (isInitiator) {
try {
// Reliable Data Channels not yet supported in Chrome
sendChannel = pc.createDataChannel("sendDataChannel",
{reliable: false});
sendChannel.onmessage = handleMessage;
trace('Created send data channel');
} catch (e) {
alert('Failed to create data channel. ' +
'You need Chrome M25 or later with RtpDataChannel enabled');
trace('createDataChannel() failed with exception: ' + e.message);
}
sendChannel.onopen = handleSendChannelStateChange;
sendChannel.onclose = handleSendChannelStateChange;
} else {
pc.ondatachannel = gotReceiveChannel;
}
}
function gotReceiveChannel(event) {
trace('Receive Channel Callback');
sendChannel = event.channel;
sendChannel.onmessage = handleMessage;
sendChannel.onopen = handleReceiveChannelStateChange;
sendChannel.onclose = handleReceiveChannelStateChange;
}
function handleSendChannelStateChange() {
var readyState = sendChannel.readyState;
trace('Send channel state is: ' + readyState);
enableMessageInterface(readyState == "open");
}
function handleReceiveChannelStateChange() {
var readyState = sendChannel.readyState;
trace('Receive channel state is: ' + readyState);
enableMessageInterface(readyState == "open");
}
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.');
}
}
function doCall() {
var constraints = {'optional': [], 'mandatory': {'MozDontOfferDataChannel': true}};
// temporary measure to remove Moz* constraints in Chrome
if (webrtcDetectedBrowser === 'chrome') {
for (var prop in constraints.mandatory) {
if (prop.indexOf('Moz') !== -1) {
delete constraints.mandatory[prop];
}
}
}
constraints = mergeConstraints(constraints, sdpConstraints);
console.log('Sending offer to peer, with constraints: \n' +
' \'' + JSON.stringify(constraints) + '\'.');
pc.createOffer(setLocalAndSendMessage, null, constraints);
}
function doAnswer() {
console.log('Sending answer to peer.');
pc.createAnswer(setLocalAndSendMessage, null, sdpConstraints);
}
function handleRemoteStreamAdded(event) {
console.log('Remote stream added.');
attachMediaStream(remoteVideo, event.stream);
remoteStream = event.stream;
}
Run Code Online (Sandbox Code Playgroud)
这是服务器端代码:
socket.on('message', function (message) {
// channel-only broadcast...
socket.broadcast.to(message.channel).emit('message', message);
});
// Handle 'create or join' messages
socket.on('create or join', function (room) {
var numClients = io.sockets.clients(room).length;
// First client joining...
if (numClients == 0){
socket.join(room);
socket.emit('created', room);
} else if (numClients == 1) {
io.sockets.in(room).emit('join', room);
socket.join(room);
socket.emit('joined', room);
} else {
socket.emit('full', room);
}
});
Run Code Online (Sandbox Code Playgroud)
简而言之,为了将视频或音频添加到现有连接,您每次进行媒体更改时都需要重新协商连接。基本上,您注册一个侦听器:
pc.onnegotiationneeded = function() {
pc.createOffer(setLocalAndSendMessage, null);
};
Run Code Online (Sandbox Code Playgroud)
这会触发另一次要约/答案交换,就像发起连接的那一次一样。
一旦有了这些,negotiationneeded就会从需要重新协商的操作中触发一个事件。例如,“添加视频”按钮:
AddVideoButton.onclick = function() {
navigator.getUserMedia(constraints, handleUserMedia, handleUserMediaError);
};
Run Code Online (Sandbox Code Playgroud)
双方更新后,您就应该做生意。
有关完整示例,请参见我对类似问题的回答(仅适用于Firefox,因为具有箭头功能,对不起)。
它看起来像你使用adapter.js跨浏览器的WebRTC填充工具来照顾的浏览器之间的差异,这是伟大的!但是示例中的其他部分是特定于Chrome的或过时的,除非您遵循标准,否则其他浏览器将无法使用。您没有将问题标记为特定于Chrome,因此如果您不介意:
从pc_configFirefox 32开始(一年多以前),不再需要在您的浏览器中进行检测。相反,我会使用(注意urls复数):
var config = { iceServers: [{urls: 'stun:stun.l.google.com:19302'}] };
Run Code Online (Sandbox Code Playgroud)
的pc_constraints(早期铬)和sdpConstraints非标准。createOffer现在使用RTCOfferOptions(一个简单的字典),而不是约束(也请注意小写的'o'):
var options = { offerToReceiveAudio: true, offerToReceiveVideo: true };
Run Code Online (Sandbox Code Playgroud)
如果您使用的是新版本的adapter.js,则应该可以使用。
最后,RTP上的数据通道是非标准的(我认为不再需要吗?)
| 归档时间: |
|
| 查看次数: |
4106 次 |
| 最近记录: |