parent
46390a3ba9
commit
894d4c84b3
2 changed files with 79 additions and 28 deletions
|
|
@ -2,21 +2,7 @@ import logger from '@/logger';
|
||||||
import { VElement } from 'Player/web/managers/DOM/VirtualDOM';
|
import { VElement } from 'Player/web/managers/DOM/VirtualDOM';
|
||||||
import MessageManager from 'Player/web/MessageManager';
|
import MessageManager from 'Player/web/MessageManager';
|
||||||
import { Socket } from 'socket.io-client';
|
import { Socket } from 'socket.io-client';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
let frameCounter = 0;
|
|
||||||
|
|
||||||
function draw(
|
|
||||||
video: HTMLVideoElement,
|
|
||||||
canvas: HTMLCanvasElement,
|
|
||||||
canvasCtx: CanvasRenderingContext2D,
|
|
||||||
) {
|
|
||||||
if (frameCounter % 4 === 0) {
|
|
||||||
canvasCtx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
||||||
}
|
|
||||||
frameCounter++;
|
|
||||||
requestAnimationFrame(() => draw(video, canvas, canvasCtx));
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class CanvasReceiver {
|
export default class CanvasReceiver {
|
||||||
private streams: Map<string, MediaStream> = new Map();
|
private streams: Map<string, MediaStream> = new Map();
|
||||||
|
|
||||||
|
|
@ -25,6 +11,16 @@ export default class CanvasReceiver {
|
||||||
|
|
||||||
private cId: string;
|
private cId: string;
|
||||||
|
|
||||||
|
private frameCounter = 0;
|
||||||
|
private canvasesData = new Map<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
video: HTMLVideoElement;
|
||||||
|
canvas: HTMLCanvasElement;
|
||||||
|
canvasCtx: CanvasRenderingContext2D;
|
||||||
|
}
|
||||||
|
>(new Map());
|
||||||
|
|
||||||
// sendSignal – for sending signals (offer/answer/ICE)
|
// sendSignal – for sending signals (offer/answer/ICE)
|
||||||
constructor(
|
constructor(
|
||||||
private readonly peerIdPrefix: string,
|
private readonly peerIdPrefix: string,
|
||||||
|
|
@ -56,6 +52,14 @@ export default class CanvasReceiver {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.socket.on('webrtc_canvas_stop', (data: { id: string }) => {
|
||||||
|
const { id } = data;
|
||||||
|
const canvasId = getCanvasId(id);
|
||||||
|
this.connections.delete(id);
|
||||||
|
this.streams.delete(id);
|
||||||
|
this.canvasesData.delete(canvasId);
|
||||||
|
});
|
||||||
|
|
||||||
this.socket.on('webrtc_canvas_restart', () => {
|
this.socket.on('webrtc_canvas_restart', () => {
|
||||||
this.clear();
|
this.clear();
|
||||||
});
|
});
|
||||||
|
|
@ -85,7 +89,7 @@ export default class CanvasReceiver {
|
||||||
const stream = event.streams[0];
|
const stream = event.streams[0];
|
||||||
if (stream) {
|
if (stream) {
|
||||||
// Detect canvasId from remote peer id
|
// Detect canvasId from remote peer id
|
||||||
const canvasId = id.split('-')[4];
|
const canvasId = getCanvasId(id);
|
||||||
this.streams.set(canvasId, stream);
|
this.streams.set(canvasId, stream);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const node = this.getNode(parseInt(canvasId, 10));
|
const node = this.getNode(parseInt(canvasId, 10));
|
||||||
|
|
@ -93,14 +97,15 @@ export default class CanvasReceiver {
|
||||||
stream.clone() as MediaStream,
|
stream.clone() as MediaStream,
|
||||||
node as VElement,
|
node as VElement,
|
||||||
);
|
);
|
||||||
if (node) {
|
if (node && videoEl) {
|
||||||
draw(
|
this.canvasesData.set(canvasId, {
|
||||||
videoEl,
|
video: videoEl,
|
||||||
node.node as HTMLCanvasElement,
|
canvas: node.node as HTMLCanvasElement,
|
||||||
(node.node as HTMLCanvasElement).getContext(
|
canvasCtx: (node.node as HTMLCanvasElement)?.getContext(
|
||||||
'2d',
|
'2d',
|
||||||
) as CanvasRenderingContext2D,
|
) as CanvasRenderingContext2D,
|
||||||
);
|
});
|
||||||
|
this.draw();
|
||||||
} else {
|
} else {
|
||||||
logger.log('NODE', canvasId, 'IS NOT FOUND');
|
logger.log('NODE', canvasId, 'IS NOT FOUND');
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +141,27 @@ export default class CanvasReceiver {
|
||||||
});
|
});
|
||||||
this.connections.clear();
|
this.connections.clear();
|
||||||
this.streams.clear();
|
this.streams.clear();
|
||||||
|
this.canvasesData.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
draw = () => {
|
||||||
|
if (this.frameCounter % 4 === 0) {
|
||||||
|
if (this.canvasesData.size === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.canvasesData.forEach((canvasData, id) => {
|
||||||
|
const { video, canvas, canvasCtx } = canvasData;
|
||||||
|
const node = this.getNode(parseInt(id, 10));
|
||||||
|
if (node) {
|
||||||
|
canvasCtx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
||||||
|
} else {
|
||||||
|
this.canvasesData.delete(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.frameCounter++;
|
||||||
|
requestAnimationFrame(() => this.draw());
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function spawnVideo(stream: MediaStream, node: VElement) {
|
function spawnVideo(stream: MediaStream, node: VElement) {
|
||||||
|
|
@ -152,6 +177,10 @@ function spawnVideo(stream: MediaStream, node: VElement) {
|
||||||
.play()
|
.play()
|
||||||
.then(() => true)
|
.then(() => true)
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
toast.error('Click to unpause canvas stream', {
|
||||||
|
autoClose: false,
|
||||||
|
toastId: 'canvas-stream',
|
||||||
|
});
|
||||||
// we allow that if user just reloaded the page
|
// we allow that if user just reloaded the page
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -164,6 +193,10 @@ function spawnVideo(stream: MediaStream, node: VElement) {
|
||||||
const startStream = () => {
|
const startStream = () => {
|
||||||
videoEl
|
videoEl
|
||||||
.play()
|
.play()
|
||||||
|
.then(() => {
|
||||||
|
toast.dismiss('canvas-stream');
|
||||||
|
clearListeners();
|
||||||
|
})
|
||||||
.then(() => console.log('unpaused'))
|
.then(() => console.log('unpaused'))
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
// we allow that if user just reloaded the page
|
// we allow that if user just reloaded the page
|
||||||
|
|
@ -179,6 +212,10 @@ function checkId(id: string, cId: string): boolean {
|
||||||
return id.includes(cId);
|
return id.includes(cId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCanvasId(id: string): string {
|
||||||
|
return id.split('-')[4];
|
||||||
|
}
|
||||||
|
|
||||||
/** simple peer example
|
/** simple peer example
|
||||||
* // @ts-ignore
|
* // @ts-ignore
|
||||||
* const peer = new SLPeer({ initiator: false })
|
* const peer = new SLPeer({ initiator: false })
|
||||||
|
|
|
||||||
|
|
@ -934,12 +934,7 @@ export default class Assist {
|
||||||
const int = setInterval(() => {
|
const int = setInterval(() => {
|
||||||
const isPresent = node.ownerDocument.defaultView && node.isConnected;
|
const isPresent = node.ownerDocument.defaultView && node.isConnected;
|
||||||
if (!isPresent) {
|
if (!isPresent) {
|
||||||
canvasHandler.stop();
|
this.stopCanvasStream(id);
|
||||||
this.canvasMap.delete(id);
|
|
||||||
if (this.canvasPeers[id]) {
|
|
||||||
this.canvasPeers[id]?.close();
|
|
||||||
this.canvasPeers[id] = null;
|
|
||||||
}
|
|
||||||
clearInterval(int);
|
clearInterval(int);
|
||||||
}
|
}
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
|
@ -1000,6 +995,25 @@ export default class Assist {
|
||||||
this.socket?.emit("webrtc_canvas_restart");
|
this.socket?.emit("webrtc_canvas_restart");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private stopCanvasStream(id: number) {
|
||||||
|
for (const agent of Object.values(this.agents)) {
|
||||||
|
if (!agent.agentInfo) return;
|
||||||
|
|
||||||
|
const uniqueId = `${agent.agentInfo.peerId}-${agent.agentInfo.id}-canvas-${id}`;
|
||||||
|
this.socket?.emit("webrtc_canvas_stop", { id: uniqueId });
|
||||||
|
|
||||||
|
if (this.canvasPeers[uniqueId]) {
|
||||||
|
this.canvasPeers[uniqueId]?.close();
|
||||||
|
delete this.canvasPeers[uniqueId];
|
||||||
|
|
||||||
|
this.canvasMap.get(id)?.stop();
|
||||||
|
this.canvasMap.delete(id);
|
||||||
|
this.canvasNodeCheckers.get(id) && clearInterval(this.canvasNodeCheckers.get(id));
|
||||||
|
this.canvasNodeCheckers.delete(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private applyBufferedIceCandidates(from) {
|
private applyBufferedIceCandidates(from) {
|
||||||
const buffer = this.iceCandidatesBuffer.get(from);
|
const buffer = this.iceCandidatesBuffer.get(from);
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue