Add remote video overlay
Fix remote audio not working when viewing another conversation.
Add a remote video overlay when in a call, but viewing a different page.
New components:
- VideoOverlay
- RemoteVideoOverlay: Video overlay for the remote stream when in a
different page. Clicking it will redirect to the current call page.
- VideoStream: renders a video from a MediaStream and can
output audio to the device with id `audioOutDeviceId`
Misc changes:
- Can click local video to make bigger
Change-Id: If1bb0b10c137944c405d540f041ebfe8005f9251
diff --git a/client/src/components/VideoStream.tsx b/client/src/components/VideoStream.tsx
new file mode 100644
index 0000000..4740e81
--- /dev/null
+++ b/client/src/components/VideoStream.tsx
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+import { forwardRef, useEffect, useRef, VideoHTMLAttributes } from 'react';
+
+import { VideoElementWithSinkId } from '../utils/utils';
+
+export type VideoStreamProps = Partial<VideoHTMLAttributes<VideoElementWithSinkId>> & {
+ stream: MediaStream | undefined;
+ audioOutDeviceId?: string;
+};
+
+const VideoStream = forwardRef<VideoElementWithSinkId, VideoStreamProps>(
+ ({ stream, audioOutDeviceId, ...props }, ref) => {
+ const videoRef = useRef<VideoElementWithSinkId | null>(null);
+
+ useEffect(() => {
+ if (!ref) {
+ return;
+ }
+
+ if (typeof ref === 'function') {
+ ref(videoRef.current);
+ } else {
+ ref.current = videoRef.current;
+ }
+ }, [ref]);
+
+ useEffect(() => {
+ if (stream && videoRef.current) {
+ videoRef.current.srcObject = stream;
+ }
+ }, [stream, videoRef]);
+
+ useEffect(() => {
+ if (!audioOutDeviceId) {
+ return;
+ }
+
+ if (videoRef.current?.setSinkId) {
+ // This only work on chrome and other browsers that support `setSinkId`
+ // https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkId#browser_compatibility
+ videoRef.current.setSinkId(audioOutDeviceId);
+ }
+ }, [audioOutDeviceId, videoRef]);
+
+ return <video ref={videoRef} autoPlay {...props} />;
+ }
+);
+export default VideoStream;