gpt4 book ai didi

javascript - WEBRTC 带 socket 的开关量输入设备

转载 作者:行者123 更新时间:2023-12-04 13:51:38 26 4
gpt4 key购买 nike

我有一个应用程序。在此应用程序中,我无法更改发送给对方的视频。

'use strict';

var Meeting = function (socketioHost) {
var exports = {};

var _isInitiator = false;
var _localStream;
var _remoteStream;
var _turnReady;
var _pcConfig = {'iceServers': [{'url': 'stun:stun.l.google.com:19302'}]};
var _constraints = {
video: {
width: {ideal: 320},
height: {ideal: 240},
frameRate: {ideal: 20}
},
audio: {
googEchoCancellation: true,
googAutoGainControl: true,
googNoiseSuppression: true,
googHighpassFilter: true,
googEchoCancellation2: true,
googAutoGainControl2: true,
googNoiseSuppression2: true
},
options: {
mirror: true
}
};

if(navigator.userAgent.includes("iPhone")) {
var _constraints = {
video : true
}
}

var _defaultChannel;
var _privateAnswerChannel;
var _offerChannels = {};
var _opc = {};
var _apc = {};
var _sendChannel = {};
var _room;
var _myID;
var _onRemoteVideoCallback;
var _onLocalVideoCallback;
var _onChatMessageCallback;
var _onChatReadyCallback;
var _onChatNotReadyCallback;
var _onParticipantHangupCallback;
var _host = socketioHost;


////////////////////////////////////////////////
// PUBLIC FUNCTIONS
////////////////////////////////////////////////
/**
*
* Add callback function to be called when a chat message is available.
*
* @param name of the room to join
*/
function joinRoom(name) {
_room = name;

_myID = generateID();

// Open up a default communication channel
initDefaultChannel();

if (_room !== '') {
console.log('Create or join room', _room);
_defaultChannel.emit('create or join', {room:_room, from:_myID});
}

// Open up a private communication channel
initPrivateChannel();

//console.log(_devices);

navigator.mediaDevices.getUserMedia(_constraints)
.then(handleUserMedia)
.catch(handleUserMediaError);

window.onbeforeunload = function(e){
_defaultChannel.emit('message',{type: 'bye', from:_myID});
}
}


/**
*
* Send a chat message to all channels.
*
* @param message String message to be send
*/
function sendChatMessage(message) {
console.log("Sending "+message)
for (var channel in _sendChannel) {
if (_sendChannel.hasOwnProperty(channel)) {
_sendChannel[channel].send(message);
}
}
}

/**
*
* Toggle microphone availability.
*
*/
function toggleMic() {
var tracks = _localStream.getTracks();
for (var i = 0; i < tracks.length; i++) {
if (tracks[i].kind=="audio") {
tracks[i].enabled = !tracks[i].enabled;
}
}
}


/**
*
* Toggle video availability.
*
*/
function toggleVideo() {
var tracks = _localStream.getTracks();
for (var i = 0; i < tracks.length; i++) {
if (tracks[i].kind=="video") {
tracks[i].enabled = !tracks[i].enabled;
}
}
}

/**
*
* Add callback function to be called when remote video is available.
*
* @param callback of type function(stream, participantID)
*/
function onRemoteVideo(callback) {
_onRemoteVideoCallback = callback;
}

/**
*
* Add callback function to be called when local video is available.
*
* @param callback function of type function(stream)
*/
function onLocalVideo(callback) {
_onLocalVideoCallback = callback;
}

/**
*
* Add callback function to be called when chat is available.
*
* @parama callback function of type function()
*/
function onChatReady(callback) {
_onChatReadyCallback = callback;
}

/**
*
* Add callback function to be called when chat is no more available.
*
* @parama callback function of type function()
*/
function onChatNotReady(callback) {
_onChatNotReadyCallback = callback;
}

/**
*
* Add callback function to be called when a chat message is available.
*
* @parama callback function of type function(message)
*/
function onChatMessage(callback) {
_onChatMessageCallback = callback;
}

/**
*
* Add callback function to be called when a a participant left the conference.
*
* @parama callback function of type function(participantID)
*/
function onParticipantHangup(callback) {
_onParticipantHangupCallback = callback;
}

////////////////////////////////////////////////
// INIT FUNCTIONS
////////////////////////////////////////////////

function initDefaultChannel() {
_defaultChannel = openSignalingChannel('');

_defaultChannel.on('created', function (room){
console.log('Created room ' + room);
_isInitiator = true;
});

_defaultChannel.on('join', function (room){
console.log('Another peer made a request to join room ' + room);
});

_defaultChannel.on('joined', function (room){
console.log('This peer has joined room ' + room);
});

_defaultChannel.on('message', function (message){
console.log('Client received message:', message);
if (message.type === 'newparticipant') {
var partID = message.from;

// Open a new communication channel to the new participant
_offerChannels[partID] = openSignalingChannel(partID);

// Wait for answers (to offers) from the new participant
_offerChannels[partID].on('message', function (msg){
if (msg.dest===_myID) {
if (msg.type === 'answer') {
_opc[msg.from].setRemoteDescription(new RTCSessionDescription(msg.snDescription))
.then(setRemoteDescriptionSuccess)
.catch(setRemoteDescriptionError);
} else if (msg.type === 'candidate') {
var candidate = new RTCIceCandidate({sdpMLineIndex: msg.label, candidate: msg.candidate});
console.log('got ice candidate from '+msg.from);
_opc[msg.from].addIceCandidate(candidate, addIceCandidateSuccess, addIceCandidateError);
}
}
});

// Send an offer to the new participant
createOffer(partID);

} else if (message.type === 'bye') {
hangup(message.from);
} else if(message.type === 'change') {
$('#' + message.from).remove();
if(_myID !== message.from) {
createOffer(message.from);
}

}
});
}

function initPrivateChannel() {
// Open a private channel (namespace = _myID) to receive offers
_privateAnswerChannel = openSignalingChannel(_myID);

// Wait for offers or ice candidates
_privateAnswerChannel.on('message', function (message){
if (message.dest===_myID) {
if(message.type === 'offer') {
var to = message.from;
createAnswer(message, _privateAnswerChannel, to);
} else if (message.type === 'candidate') {
var candidate = new RTCIceCandidate({sdpMLineIndex: message.label, candidate: message.candidate});
_apc[message.from].addIceCandidate(candidate, addIceCandidateSuccess, addIceCandidateError);
}
}
});
}

function requestTurn(turn_url) {
var turnExists = false;
for (var i in _pcConfig.iceServers) {
if (_pcConfig.iceServers[i].url.substr(0, 5) === 'turn:') {
turnExists = true;
_turnReady = true;
break;
}
}

if (!turnExists) {
console.log('Getting TURN server from ', turn_url);
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (xhr.readyState === 4 && xhr.status === 200) {
var turnServer = JSON.parse(xhr.responseText);
console.log('Got TURN server: ', turnServer);
_pcConfig.iceServers.push({
'url': 'turn:' + turnServer.username + '@' + turnServer.turn,
'credential': turnServer.password
});
_turnReady = true;
}
}
xhr.open('GET', turn_url, true);
xhr.send();
}
}


///////////////////////////////////////////
// UTIL FUNCTIONS
///////////////////////////////////////////

/**
*
* Call the registered _onRemoteVideoCallback
*
*/
function addRemoteVideo(stream, from) {
// call the callback
_onRemoteVideoCallback(stream, from);
}


/**
*
* Generates a random ID.
*
* @return a random ID
*/
function generateID() {
var s4 = function() {
return Math.floor(Math.random() * 0x10000).toString(16);
};
return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4();
}


////////////////////////////////////////////////
// COMMUNICATION FUNCTIONS
////////////////////////////////////////////////

/**
*
* Connect to the server and open a signal channel using channel as the channel's name.
*
* @return the socket
*/
function openSignalingChannel(channel) {
var namespace = _host + '/' + channel;
var sckt = io.connect(namespace);
return sckt;
}

function logout(from) {
hangup(from)
window.dispatchEvent(new Event('beforeunload'))
}

/**
*
* Send an offer to peer with id participantId
*
* @param participantId the participant's unique ID we want to send an offer
*/
function createOffer(participantId) {
console.log('Creating offer for peer '+participantId);

_opc[participantId] = new RTCPeerConnection(_pcConfig);
_opc[participantId].onicecandidate = handleIceCandidateAnswerWrapper(_offerChannels[participantId], participantId);
_opc[participantId].onaddstream = handleRemoteStreamAdded(participantId);
_opc[participantId].onremovestream = handleRemoteStreamRemoved;
_opc[participantId].addStream(_localStream);

try {
// Reliable Data Channels not yet supported in Chrome
_sendChannel[participantId] = _opc[participantId].createDataChannel("sendDataChannel", {reliable: false});
_sendChannel[participantId].onmessage = handleMessage;
//console.log('Created send data channel');
} catch (e) {
alert('Failed to create data channel. ' + 'You need Chrome M25 or later with RtpDataChannel enabled');
//console.log('createDataChannel() failed with exception: ' + e.message);
}
_sendChannel[participantId].onopen = handleSendChannelStateChange(participantId);
_sendChannel[participantId].onclose = handleSendChannelStateChange(participantId);

var onSuccess = function(participantId) {
return function(sessionDescription) {
var channel = _offerChannels[participantId];

// Set Opus as the preferred codec in SDP if Opus is present.
sessionDescription.sdp = preferOpus(sessionDescription.sdp);

_opc[participantId].setLocalDescription(sessionDescription);
console.log('Sending offer to channel '+ channel.name);
channel.emit('message', {snDescription: sessionDescription, from:_myID, type:'offer', dest:participantId});
}
}

_opc[participantId].createOffer(onSuccess(participantId), handleCreateOfferError);
}

function createAnswer(sdp, cnl, to) {
_apc[to] = new RTCPeerConnection(_pcConfig);
_apc[to].onicecandidate = handleIceCandidateAnswerWrapper(cnl, to);
_apc[to].onaddstream = handleRemoteStreamAdded(to);
_apc[to].onremovestream = handleRemoteStreamRemoved;
_apc[to].addStream(_localStream);
_apc[to].setRemoteDescription(new RTCSessionDescription(sdp.snDescription))
.then(setRemoteDescriptionSuccess)
.catch(setRemoteDescriptionError);

_apc[to].ondatachannel = gotReceiveChannel(to);

var onSuccess = function(channel) {
return function(sessionDescription) {
// Set Opus as the preferred codec in SDP if Opus is present.
sessionDescription.sdp = preferOpus(sessionDescription.sdp);

_apc[to].setLocalDescription(sessionDescription);
console.log('Sending answer to channel '+ channel.name);
channel.emit('message', {snDescription:sessionDescription, from:_myID, type:'answer', dest:to});
}
}

_apc[to].createAnswer(onSuccess(cnl), handleCreateAnswerError);
}

function hangup(from) {
console.log('Bye received from '+ from);

if (_opc.hasOwnProperty(from)) {
_opc[from].close();
_opc[from] = null;
}

if (_apc.hasOwnProperty(from)) {
_apc[from].close();
_apc[from] = null;
}

_onParticipantHangupCallback(from);
}


////////////////////////////////////////////////
// HANDLERS
////////////////////////////////////////////////

// SUCCESS HANDLERS

function handleUserMedia(stream) {
console.log('Adding local stream');
_onLocalVideoCallback(stream);
_localStream = stream;
_defaultChannel.emit('message', {type:'newparticipant', from: _myID});
}

function changeHandleUserMedia(stream) {
_onLocalVideoCallback(stream);
_localStream = stream;

_defaultChannel.emit('message', {type:'change', from: _myID});
}

function handleRemoteStreamRemoved(event) {
console.log('Remote stream removed. Event: ', event);
}

function handleRemoteStreamAdded(from) {
return function(event) {
//console.log('Remote stream added');
addRemoteVideo(event.stream, from);
_remoteStream = event.stream;
}
}

function handleIceCandidateAnswerWrapper(channel, to) {
return function handleIceCandidate(event) {
console.log('handleIceCandidate event');
if (event.candidate) {
channel.emit('message',
{type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate,
from: _myID,
dest:to}
);

} else {
console.log('End of candidates.');
}
}
}

function setLocalDescriptionSuccess() {}

function setRemoteDescriptionSuccess() {}

function addIceCandidateSuccess() {}

function gotReceiveChannel(id) {
return function(event) {
console.log('Receive Channel Callback');
_sendChannel[id] = event.channel;
_sendChannel[id].onmessage = handleMessage;
_sendChannel[id].onopen = handleReceiveChannelStateChange(id);
_sendChannel[id].onclose = handleReceiveChannelStateChange(id);
}
}

function handleMessage(event) {
console.log('Received message: ' + event.data);
_onChatMessageCallback(event.data);
}

function handleSendChannelStateChange(participantId) {
return function() {
var readyState = _sendChannel[participantId].readyState;
console.log('Send channel state is: ' + readyState);

// check if we have at least one open channel before we set hat ready to false.
var open = checkIfOpenChannel();
enableMessageInterface(open);
}
}

function handleReceiveChannelStateChange(participantId) {
return function() {
var readyState = _sendChannel[participantId].readyState;
// check if we have at least one open channel before we set hat ready to false.
var open = checkIfOpenChannel();
enableMessageInterface(open);
}
}

function checkIfOpenChannel() {
var open = false;
for (var channel in _sendChannel) {
if (_sendChannel.hasOwnProperty(channel)) {
open = (_sendChannel[channel].readyState == "open");
if (open == true) {
break;
}
}
}

return open;
}

function enableMessageInterface(shouldEnable) {
if (shouldEnable) {
_onChatReadyCallback();
} else {
_onChatNotReadyCallback();
}
}

// ERROR HANDLERS

function handleCreateOfferError(event){
console.log('createOffer() error: ', event);
}

function handleCreateAnswerError(event){
console.log('createAnswer() error: ', event);
}

function handleUserMediaError(error){
console.log('getUserMedia error: ', error);
}

function setLocalDescriptionError(error) {
console.log('setLocalDescription error: ', error);
}

function setRemoteDescriptionError(error) {
console.log('setRemoteDescription error: ', error);
}

function addIceCandidateError(error) {}


////////////////////////////////////////////////
// CODEC
////////////////////////////////////////////////

// Set Opus as the default audio codec if it's present.
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 || mLineIndex === undefined) {
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;
}


////////////////////////////////////////////////
// EXPORT PUBLIC FUNCTIONS
////////////////////////////////////////////////

exports.joinRoom = joinRoom;
exports.toggleMic = toggleMic;
exports.toggleVideo = toggleVideo;
exports.onLocalVideo = onLocalVideo;
exports.onRemoteVideo = onRemoteVideo;
exports.onChatReady = onChatReady;
exports.onChatNotReady = onChatNotReady;
exports.onChatMessage = onChatMessage;
exports.sendChatMessage = sendChatMessage;
exports.onParticipantHangup = onParticipantHangup;
exports.changeHandleUserMedia = changeHandleUserMedia;
exports.logout = logout;
exports.opc = _opc;
exports.apc = _apc;
return exports;

};


我从这里提供我的链接,而且效果很好。你能举例说明我如何做到这一点吗?
$( document ).ready(function() {
/////////////////////////////////
// CREATE MEETING
/////////////////////////////////
meeting = new Meeting(host);

meeting.onLocalVideo(function(stream) {
//alert(stream.getVideoTracks().length);
document.querySelector('#localVideo').srcObject = stream;


$("#micMenu").on("click",function callback(e) {
$(this).toggleText("mic_off", "mic");
meeting.toggleMic();
});

$("#videoMenu").on("click",function callback(e) {
$(this).toggleText("videocam_off", "videocam");
meeting.toggleVideo();
});

$("#speakerMenu").on("click", function callback(e) {
$(this).toggleText("volume_off", "volume_up");
$("#localVideo").prop('muted', true);
});

$('#chatMenu').on('click', function callback(e) {
$(this).toggleText('speaker_notes_off', 'chat');
});

$('#close').on('click', function callback(e) {
meeting.logout($('.videoWrap').eq(1).attr('id'));
});


$(document).on('change', '#videoInput', function callback(e) {

var mediaParams = {
video: {mandatory: {sourceId: $(this).val()}}
};

navigator.mediaDevices.getUserMedia(mediaParams)
.then(function(stream){
meeting.handleUserMedia(stream);

})
.catch(function(e) { });
});

}
);

meeting.onRemoteVideo(function(stream, participantID) {
addRemoteVideo(stream, participantID);
}
);

meeting.onParticipantHangup(function(participantID) {
// Someone just left the meeting. Remove the participants video
removeRemoteVideo(participantID);
}
);

meeting.onChatReady(function() {
console.log("Chat is ready");
}
);

meeting.onChatNotReady(function() {
console.log("Chat is not ready");
}
);

var room = window.location.pathname.match(/([^\/]*)\/*$/)[1];
meeting.joinRoom(room);

}); // end of document.ready

显然我正在更改本地视频。但我无法为其他用户更改它。

最佳答案

在我的实践中,本地和远程视频都可以查看,我的代码如下
包.json:

{
"name": "peer to peer",
"version": "1.0.0",
"description": "point to point by webrtc & websocket",
"main": "index.js",
"scripts": {
"dev": "node index.js"
},
"author": "webrtc",
"license": "ISC",
"dependencies": {
"express": "^4.17.1",
"express-ws": "^4.0.0"
}
}
索引.js:
const app = require('express')();
const wsInstance = require('express-ws')(app);

app.ws('/', ws => {
ws.on('message', data => {
// post cast
wsInstance.getWss().clients.forEach(server => {
if (server !== ws) {
server.send(data);
}
});
});
});

app.get('/', (req, res) => {
res.sendFile('./client/index.html', { root: __dirname });
});

app.get('/p2p', (req, res) => {
res.sendFile('./client/p2p.html', { root: __dirname });
});

app.listen(8091);
索引.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>p2p webrtc</title>
<style>
.container {
width: 250px;
margin: 100px auto;
padding: 10px 30px;
border-radius: 4px;
border: 1px solid #ebeef5;
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
color: #303133;
}
</style>
</head>
<body>
<div class="container">
<p>seheme:</p>
<ul>
<li>open<a href="/p2p?type=answer" target="_blank">answer</a>;</li>
<li>open<a href="/p2p?type=offer" target="_blank">offer</a>;</li>
<li> comfirm connected ws ;</li>
<li> offer send 'start' button;</li>
</ul>
</div>
</body>
</html>
p2p.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
.container {
width: 100%;
display: flex;
display: -webkit-flex;
justify-content: space-around;
padding-top: 20px;
}
.video-box {
position: relative;
width: 800px;
height: 400px;
}
#remote-video {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
border: 1px solid #eee;
background-color: #F2F6FC;
}
#local-video {
position: absolute;
right: 0;
bottom: 0;
width: 240px;
height: 120px;
object-fit: cover;
border: 1px solid #eee;
background-color: #EBEEF5;
}
.start-button {
position: absolute;
left: 50%;
top: 50%;
width: 100px;
display: none;
line-height: 40px;
outline: none;
color: #fff;
background-color: #409eff;
border: none;
border-radius: 4px;
cursor: pointer;
transform: translate(-50%, -50%);
}
.logger {
width: 40%;
padding: 14px;
line-height: 1.5;
color: #4fbf40;
border-radius: 6px;
background-color: #272727;
}
.logger .error {
color: #DD4A68;
}
</style>
</head>
<body>
<div class="container">
<div class="video-box">
<video id="remote-video"></video>
<video id="local-video" muted></video>
<button class="start-button" onclick="startLive()">start</button>
</div>
<div class="logger"></div>
</div>
<script>
const message = {
el: document.querySelector('.logger'),
log (msg) {
this.el.innerHTML += `<span>${new Date().toLocaleTimeString()}:${msg}</span><br/>`;
},
error (msg) {
this.el.innerHTML += `<span class="error">${new Date().toLocaleTimeString()}:${msg}</span><br/>`;
}
};

const target = location.search.slice(6);
const localVideo = document.querySelector('#local-video');
const remoteVideo = document.querySelector('#remote-video');
const button = document.querySelector('.start-button');

localVideo.onloadeddata = () => {
message.log('play local video');
localVideo.play();
}
remoteVideo.onloadeddata = () => {
message.log('play remote video');
remoteVideo.play();
}

document.title = target === 'offer' ? 'offer' : 'answer';

message.log('Multi-hole channel (WebSocket) is being created...');
const socket = new WebSocket('ws://localhost:8091');
socket.onopen = () => {
message.log('The signaling channel is successfully created!');
target === 'offer' && (button.style.display = 'block');
}
socket.onerror = () => message.error('Failed to create signaling channel!');
socket.onmessage = e => {
const { type, sdp, iceCandidate } = JSON.parse(e.data)
if (type === 'answer') {
peer.setRemoteDescription(new RTCSessionDescription({ type, sdp }));
} else if (type === 'answer_ice') {
peer.addIceCandidate(iceCandidate);
} else if (type === 'offer') {
startLive(new RTCSessionDescription({ type, sdp }));
} else if (type === 'offer_ice') {
peer.addIceCandidate(iceCandidate);
}
};

const PeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
!PeerConnection && message.error('The browser does not support WebRTC!');
const peer = new PeerConnection();

peer.ontrack = e => {
if (e && e.streams) {
message.log('Receive the other party's audio/video stream data...');
remoteVideo.srcObject = e.streams[0];
}
};

peer.onicecandidate = e => {
if (e.candidate) {
message.log('Collect and send candidates');
socket.send(JSON.stringify({
type: `${target}_ice`,
iceCandidate: e.candidate
}));
} else {
message.log('The candidate collection is complete!');
}
};

async function startLive (offerSdp) {
target === 'offer' && (button.style.display = 'none');
let stream;
try {
message.log('Try to call the local camera/microphone');
stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
message.log('The camera/microphone is successfully acquired!');
localVideo.srcObject = stream;
} catch {
message.error('Camera/microphone acquisition failed!');
return;
}

message.log(`------ WebRTC ${target === 'offer' ? 'offer' : 'answer'}seheme ------`);
message.log('Add a media track to the track set');
stream.getTracks().forEach(track => {
peer.addTrack(track, stream);
});

if (!offerSdp) {
message.log('Create a local SDP');
const offer = await peer.createOffer();
await peer.setLocalDescription(offer);

message.log(`Transmission initiator local SDP`);
socket.send(JSON.stringify(offer));
} else {
message.log('SDP received from the sender');
await peer.setRemoteDescription(offerSdp);

message.log('Create receiver (answer) SDP');
const answer = await peer.createAnswer();
message.log(`Transmission receiver (response) SDP`);
socket.send(JSON.stringify(answer));
await peer.setLocalDescription(answer);
}
}
</script>
</body>
</html>
使用代码:
npm install                 //npm install dependency

npm run dev //open localhost:8091
希望能帮到你!

关于javascript - WEBRTC 带 socket 的开关量输入设备,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68906519/

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