大家好!想請教大家有關WebRTC的一些問題
我想製作一個當兩端使用者開啟相同網址,便會建立一個會議空間
雙方則可進行視訊及共用白板
而我原先計畫其實只有視訊,是到後期才加入白板功能
爬了WebRTC官方文件後,發現可以使用captureStream這個API達到效果
但實作後還是沒辦法如其運作...
後來認為共用白板的製作太難達到,所以先以達到一端使用 一端觀看為主
目前還是仍無法成功傳輸CANVAS畫面QQ (視訊已可以運作)
window.onload裡是放白板本地端白板的行為
其餘則是實現WebRTC
window.onload = function () {
// Definitions
canvas = document.getElementById("paint-canvas");
var context = canvas.getContext("2d");
var boundings = canvas.getBoundingClientRect();
// Specifications
var mouseX = 0;
var mouseY = 0;
context.strokeStyle = 'black'; // initial brush color
context.lineWidth = 1; // initial brush width
var isDrawing = false;
// Handle Colors
var colors = document.getElementsByClassName('colors')[0];
colors.addEventListener('click', function(event) {
context.strokeStyle = event.target.value || 'black';
});
// Handle Brushes
var brushes = document.getElementsByClassName('brushes')[0];
brushes.addEventListener('click', function(event) {
context.lineWidth = event.target.value || 1;
});
// Mouse Down Event
canvas.addEventListener('mousedown', function(event) {
setMouseCoordinates(event);
isDrawing = true;
// Start Drawing
context.beginPath();
context.moveTo(mouseX, mouseY);
});
// Mouse Move Event
canvas.addEventListener('mousemove', function(event) {
setMouseCoordinates(event);
if(isDrawing){
context.lineTo(mouseX, mouseY);
context.stroke();
}});
// Mouse Up Event
canvas.addEventListener('mouseup', function(event) {
setMouseCoordinates(event);
isDrawing = false;
});
// Handle Mouse Coordinates
function setMouseCoordinates(event) {
mouseX = event.clientX - boundings.left;
mouseY = event.clientY - boundings.top;
}
// Handle Clear Button
var clearButton = document.getElementById('clear');
clearButton.addEventListener('click', function() {
context.clearRect(0, 0, canvas.width, canvas.height);
});
// Handle Save Button
var saveButton = document.getElementById('save');
saveButton.addEventListener('click', function() {
var imageName = prompt('Please enter image name');
var canvasDataURL = canvas.toDataURL();
var a = document.createElement('a');
a.href = canvasDataURL;
a.download = imageName || 'drawing';
a.click();
});
};
var strUrl = location.search;
var getPara, ParaVal;
var vaule = [];
if (strUrl.indexOf("?") != -1) {
var getSearch = strUrl.split("?");
getPara = getSearch[1].split("&");
for (i = 0; i < getPara.length; i++) {
ParaVal = getPara[i].split(" ");
vaule.push(ParaVal[0]);
vaule[ParaVal[0]] = ParaVal[1];
}
}
if (!location.hash) {
location.hash =vaule.toString(16);
}
const roomHash = location.hash.substring(1);
// TODO: Replace with your own channel ID
const drone = new ScaleDrone('yiS12Ts5RdNhebyM');
// Room name needs to be prefixed with 'observable-'
const roomName = 'observable-' + roomHash;
const configuration = {
iceServers: [{
urls: 'stun:stun.l.google.com:19302'
}]
};
let room;
let pc;
function onSuccess() {};
function onError(error) {
console.error(error);
};
drone.on('open', error => {
if (error) {
return console.error(error);
}
room = drone.subscribe(roomName);
room.on('open', error => {
if (error) {
onError(error);
}
});
// We're connected to the room and received an array of 'members'
// connected to the room (including us). Signaling server is ready.
room.on('members', members => {
console.log('MEMBERS', members);
// If we are the second user to connect to the room we will be creating the offer
const isOfferer = members.length === 2;
startWebRTC(isOfferer);
});
});
// Send signaling data via Scaledrone
function sendMessage(message) {
drone.publish({
room: roomName,
message
});
}
function startWebRTC(isOfferer) {
pc = new RTCPeerConnection(configuration);
// 'onicecandidate' notifies us whenever an ICE agent needs to deliver a
// message to the other peer through the signaling server
pc.onicecandidate = event => {
if (event.candidate) {
sendMessage({'candidate': event.candidate});
}
};
// If user is offerer let the 'negotiationneeded' event create the offer
if (isOfferer) {
pc.onnegotiationneeded = () => {
pc.createOffer().then(localDescCreated).catch(onError);
}
}
const stream = canvas.captureStream();
remoteCanvas.srcObject = stream;
stream.getTracks().forEach(track => pc.addTrack(track, stream));
// When a remote stream arrives display it in the #remoteVideo element
pc.ontrack = event => {
const stream = event.streams[0];
if (!remoteVideo.srcObject || remoteVideo.srcObject.id !== stream.id) {
remoteVideo.srcObject = stream;
}
};
navigator.mediaDevices.getUserMedia({
audio: true,
video: true,
}).then(stream => {
// Display your local video in #localVideo element
localVideo.srcObject = stream;
// Add your stream to be sent to the conneting peer
stream.getTracks().forEach(track => pc.addTrack(track, stream));
}, onError);
// Listen to signaling data from Scaledrone
room.on('data', (message, client) => {
// Message was sent by us
if (client.id === drone.clientId) {
return;
}
if (message.sdp) {
// This is called after receiving an offer or answer from another peer
pc.setRemoteDescription(new RTCSessionDescription(message.sdp), () => {
// When receiving an offer lets answer it
if (pc.remoteDescription.type === 'offer') {
pc.createAnswer().then(localDescCreated).catch(onError);
}
}, onError);
} else if (message.candidate) {
// Add the new ICE candidate to our connections remote description
pc.addIceCandidate(
new RTCIceCandidate(message.candidate), onSuccess, onError
);
}
});
}
function localDescCreated(desc) {
pc.setLocalDescription(
desc,
() => sendMessage({'sdp': pc.localDescription}),
onError
);
}
而這段是主要的部分
remoteCanvas是video標籤,用來顯示canvas的畫面
const stream = canvas.captureStream();
remoteCanvas.srcObject = stream;
stream.getTracks().forEach(track => pc.addTrack(track, stream));
希望大家可以給我一點提示
非常謝謝 !