The video does not appear when the user comes to the page

I try start livestream video on open page, follow doc for setup and create token, init, join, start video. Session is started, users are join on session, but video doesn’t show. I try with canvas and video tags.

on first render get error in console:
canvas is falsy
on click start button get error:
You must pass a <video> element to start video capture for Chromium browser, Android browser, and Chrome without SharedArrayBuffer support.

zoom/videosdk:1.1.7,

import React, {
    FC,
    useCallback,
    useContext,
    useEffect,
    useRef,
    useState,
    useMemo
} from 'react';
import ZoomContext from 'core/components/ZoomClientContext';
import { KJUR } from 'jsrsasign';
import { ChatClient, MediaStream } from "./index-types";
import ZoomVideo, { ConnectionState } from "@zoom/videosdk";
import style from './index.module.scss';
import LivestreamUI from './LivestreamUI/livestreamui';

export const LivestreamVideoComp = (props: any) => {
    const client: any = useContext(ZoomContext);
    const canvasRef = useRef<HTMLCanvasElement | null>(null);
    const videoRef = useRef<HTMLVideoElement | null>(null);

    useEffect(() => {
        const init = async () => {
            const token = generateVideoToken(
                "test",
                "password"
            );
            console.log('token', token);
            await client.init();
            try {
                await client.join(
                    "test",
                    token,
                    "userIdd",
                    "password",
                )
                const stream = await client.getMediaStream();
                await stream.startVideo();
                 changeHandler()

            } catch (e: any) {
                setIsLoading(false);
                console.log(e.reason);
            }
        };
        init();
    }, []);

    const changeHandler = async () => {
        client.on('peer-video-state-change', async (payload: { action: any; userId: any; }) => {
            console.log('payload', payload);
            const {
                action,
                userId
            } = payload;
            if (action === 'Start') {
                await stream.renderVideo(videoRef.current, userId, 1280, 720, 0, 0, 3);
            } else if (action === 'Stop') {
                await stream.stopRenderVideo();
            }
        })
    }

    const stop = async () => {
        const stream = await client.getMediaStream();
        await stream.stopVideo();
        await stream.renderVideo();
    }

    const start = async () => {
        const stream = await client.getMediaStream();
        await stream.startVideo();
        changeHandler()
    }

    function generateVideoToken(topic: any, password = "") {
        let signature = "";
        // try {
        const iat = Math.round(new Date().getTime() / 1000);
        const exp = iat + 60 * 60 * 2;

        // Header
        const oHeader = { alg: "HS256", typ: "JWT" };
        // Payload
        const oPayload = {
            app_key: sdkKey,
            iat,
            exp,
            tpc: topic,
            pwd: password,
            user_identity: userIdd,
            version: 1
        };
        // Sign JWT
        const sHeader = JSON.stringify(oHeader);
        const sPayload = JSON.stringify(oPayload);
        signature = KJUR.jws.JWS.sign("HS256", sHeader, sPayload, sdkSecret);
        return signature;
    }

    return (
                <div className={style.videoBox}>
                    <div style={{ display: 'flex', justifyContent: 'center', position: 'absolute', zIndex: 4 }}>
                        <button style={{ width: 100, height: 30 }} onClick={() => stop()}>stop</button>
                        <button style={{ width: 100, height: 30 }} onClick={() => start()}>start</button>
                    </div>
                    <video
                        className={style.videoCanvas}
                        //id="video-canvas"
                        // width="1600"
                        // height="900"
                        ref={videoRef}
                    />
                    {/* <canvas
                        id={SELF_VIDEO_ID}
                        className={style.previewVideo}
                        ref={canvasRef}
                        width="1600"
                        height="900"
                    /> */}
                </div>
    );
};

  • Device: Macbook Pro M1
  • OS: [e.g. macOS 11]
  • Browser: Chrome, Firefox
  • Browser Version 96.0.4664.110 (Official Build) (arm64)

Hey @reactdev

Thanks for your feedback.

Could you provide the result of following expression?

console.log(window.crossOriginIsolated)

If the result is false, maybe you are not using the Cross-Origin Isolating, refer to Improve Performance in Chrome for detail. Or you can follow the prompts on the console, pass a VideoElement parameter when invoking the media.startVideo method.

Thanks
Vic

Thanks Vic,

can we put HTMLCanvasElement into media.startVideo?
When i start video don’t see video in current, from second tab i see video of first tab.
Chrome don’t ask me for camera access and i can’t strat video from chrome, when start video from firefox video is seen in chrome.

    useEffect(() => {
        const init = async () => {
            const token = generateVideoToken(
                "test",
                "password"
            );

            console.log('token', token);
            setTok(token);
            await client.init();
            try {
                await client.join(
                    "test",
                    token,
                    "userIdd",
                    "password",
                )
                //await client.makeHost(userIdd);
                const videoElement = await document.querySelector(
                    `#${SELF_VIDEO_ID}`,
                ) as HTMLVideoElement;
                const stream = await client.getMediaStream();
                await stream.startVideo({ videoElement });
                await renderHandler()
            } catch (e: any) {
                console.log(e.reason);
            }
        };
        init();
    }, []);

    const renderHandler = async () => {
        const videoElement = document.querySelector(
            `#${SELF_VIDEO_ID}`,
        ) as HTMLVideoElement;
        const stream = await client.getMediaStream();
        await client.on('peer-video-state-change', async (payload: any) => {
            const {
                action,
                userId
            } = payload;
            if (action === 'Start') {
                await stream.renderVideo(videoElement, userId, 1280, 720, 0, 0, 3);
            } else if (action === 'Stop') {
                await stream.stopRenderVideo(videoElement);
            }
        })
    }

    const stop = async () => {
        const stream = await client.getMediaStream();
        await stream.stopVideo();
        await renderHandler();
    }

    const start = async () => {
        const videoElement = document.querySelector(
            `#${SELF_VIDEO_ID}`,
        ) as HTMLVideoElement;
        const stream = await client.getMediaStream();
        await stream.startVideo({ videoElement });
        await renderHandler();
    }

                        <canvas
                        id={SELF_VIDEO_ID}
                        className={style.previewVideo}
                        width="1600"
                        height="900"
                    />

Hey @reactdev

If the value of the expression window.crossOriginIsolated is false, an VideoElement is required.
Maybe our react-sample-app is a useful reference for your cases.

Thanks
Vic