From fd76f7c302abd64805b4fa0ff341092bdec3ecfb Mon Sep 17 00:00:00 2001 From: Andrey Babushkin <55714097+reyand43@users.noreply.github.com> Date: Thu, 27 Feb 2025 10:12:27 +0100 Subject: [PATCH] Migrate to webrtc (#3051) * resolved conflicts * resolved conflicts * translated comments * changed console.log message lang * changed console to logs * implementing conference call * add isAgent flag * add webrtc handlers * add conference call * removed conference calls * fix lint error --------- Co-authored-by: Andrey Babushkin --- .../Assist/ChatWindow/ChatWindow.tsx | 7 +- .../AssistActions/AssistActions.tsx | 28 +- .../VideoContainer/VideoContainer.tsx | 25 +- .../LivePlayer/LivePlayerBlockHeader.tsx | 2 +- frontend/app/player/web/WebLivePlayer.ts | 1 + .../app/player/web/assist/AssistManager.ts | 25 +- frontend/app/player/web/assist/Call.ts | 479 +- .../app/player/web/assist/CanvasReceiver.ts | 124 +- frontend/package.json | 1 - frontend/yarn.lock | 3375 ++--- tracker/tracker-assist/.yarn/install-state.gz | Bin 549988 -> 515844 bytes tracker/tracker-assist/layout/index-chat.html | 933 +- tracker/tracker-assist/layout/index.html | 5 +- tracker/tracker-assist/package.json | 1 - tracker/tracker-assist/src/Assist.ts | 599 +- tracker/tracker-assist/src/CallWindow.ts | 7 +- tracker/tracker-assist/src/RemoteControl.ts | 10 +- tracker/tracker-redux/.pnp.cjs | 10418 ++++++++++++++++ tracker/tracker-redux/.pnp.loader.mjs | 2126 ++++ tracker/tracker-redux/.yarn/install-state.gz | Bin 0 -> 195852 bytes tracker/tracker-redux/package.json | 12 +- 21 files changed, 15646 insertions(+), 2532 deletions(-) create mode 100755 tracker/tracker-redux/.pnp.cjs create mode 100644 tracker/tracker-redux/.pnp.loader.mjs create mode 100644 tracker/tracker-redux/.yarn/install-state.gz diff --git a/frontend/app/components/Assist/ChatWindow/ChatWindow.tsx b/frontend/app/components/Assist/ChatWindow/ChatWindow.tsx index 29e4826cc..e9e5b8ea2 100644 --- a/frontend/app/components/Assist/ChatWindow/ChatWindow.tsx +++ b/frontend/app/components/Assist/ChatWindow/ChatWindow.tsx @@ -9,7 +9,7 @@ import type { LocalStream } from 'Player'; import { PlayerContext } from 'App/components/Session/playerContext'; export interface Props { - incomeStream: MediaStream[] | null; + incomeStream: { stream: MediaStream, isAgent: boolean }[] | null; localStream: LocalStream | null; userId: string; isPrestart?: boolean; @@ -50,8 +50,8 @@ function ChatWindow({ userId, incomeStream, localStream, endCall, isPrestart }: > {incomeStream ? ( incomeStream.map((stream) => ( - - + + )) ) : ( @@ -62,6 +62,7 @@ function ChatWindow({ userId, incomeStream, localStream, endCall, isPrestart }: stream={localStream ? localStream.stream : null} muted height={anyRemoteEnabled ? 50 : 'unset'} + local /> diff --git a/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx b/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx index 40281b8a9..88317ac79 100644 --- a/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx +++ b/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx @@ -80,7 +80,7 @@ function AssistActions({ } = store.get(); const [isPrestart, setPrestart] = useState(false); - const [incomeStream, setIncomeStream] = useState([]); + const [incomeStream, setIncomeStream] = useState<{ stream: MediaStream; isAgent: boolean }[] | null>([]); const [localStream, setLocalStream] = useState(null); const [callObject, setCallObject] = useState<{ end: () => void } | null>(null); @@ -131,18 +131,25 @@ function AssistActions({ } }, [peerConnectionStatus]); - const addIncomeStream = (stream: MediaStream) => { + const addIncomeStream = (stream: MediaStream, isAgent: boolean) => { setIncomeStream((oldState) => { - if (oldState === null) return [stream]; - if (!oldState.find((existingStream) => existingStream.id === stream.id)) { + if (oldState === null) return [{ stream, isAgent }]; + if (!oldState.find((existingStream) => existingStream.stream.id === stream.id)) { audioContextManager.mergeAudioStreams(stream); - return [...oldState, stream]; + return [...oldState, { stream, isAgent }]; } return oldState; }); }; - function call(additionalAgentIds?: string[]) { + const removeIncomeStream = (stream: MediaStream) => { + setIncomeStream((prevState) => { + if (!prevState) return []; + return prevState.filter((existingStream) => existingStream.stream.id !== stream.id); + }); + }; + + function call() { RequestLocalStream() .then((lStream) => { setLocalStream(lStream); @@ -152,15 +159,16 @@ function AssistActions({ addIncomeStream, () => { player.assistManager.ping(AssistActionsPing.call.end, agentId) - lStream.stop.bind(lStream); + lStream.stop.apply(lStream); + removeIncomeStream(lStream.stream); }, onReject, onError ); setCallObject(callPeer()); - if (additionalAgentIds) { - callPeer(additionalAgentIds); - } + // if (additionalAgentIds) { + // callPeer(additionalAgentIds); + // } }) .catch(onError); } diff --git a/frontend/app/components/Assist/components/VideoContainer/VideoContainer.tsx b/frontend/app/components/Assist/components/VideoContainer/VideoContainer.tsx index 97b8c9f9e..4d8b9ece4 100644 --- a/frontend/app/components/Assist/components/VideoContainer/VideoContainer.tsx +++ b/frontend/app/components/Assist/components/VideoContainer/VideoContainer.tsx @@ -5,9 +5,18 @@ interface Props { muted?: boolean; height?: number | string; setRemoteEnabled?: (isEnabled: boolean) => void; + local?: boolean; + isAgent?: boolean; } -function VideoContainer({ stream, muted = false, height = 280, setRemoteEnabled }: Props) { +function VideoContainer({ + stream, + muted = false, + height = 280, + setRemoteEnabled, + local, + isAgent, +}: Props) { const ref = useRef(null); const [isEnabled, setEnabled] = React.useState(false); @@ -15,14 +24,14 @@ function VideoContainer({ stream, muted = false, height = 280, setRemoteEnabled if (ref.current) { ref.current.srcObject = stream; } - }, [ref.current, stream, stream.getVideoTracks()[0]?.getSettings().width]); + }, [ref.current, stream, stream?.getVideoTracks()[0]?.getSettings().width]); useEffect(() => { if (!stream) { return; } const iid = setInterval(() => { - const track = stream.getVideoTracks()[0] + const track = stream.getVideoTracks()[0]; const settings = track?.getSettings(); const isDummyVideoTrack = settings ? settings.width === 2 || @@ -47,9 +56,19 @@ function VideoContainer({ stream, muted = false, height = 280, setRemoteEnabled width: isEnabled ? undefined : '0px!important', height: isEnabled ? undefined : '0px!important', border: '1px solid grey', + transform: local ? 'scaleX(-1)' : undefined, }} >