Coder Social home page Coder Social logo

jitsi-meet-react-sdk's Introduction

Jitsi Meet React SDK

The Jitsi Meet React SDK provides the same user experience as the Jitsi Meet app, in a customizable way which you can embed in your apps.

Install

npm install @jitsi/react-sdk

Modules

This library exposes two components with similar properties, intended for different use-cases.

JitsiMeeting

To be used with custom domains as-it-is in React projects:

<JitsiMeeting
    domain = { YOUR_DOMAIN }
    roomName = { YOUR_ROOM_NAME }
/>
Properties specific to the JitsiMeeting component
domain

Optional. Field used to retrieve the external_api.js file that initializes the IFrame. If omitted, defaults to meet.jit.si.

JaaSMeeting

To be used with the 8x8.vc domain as-it-is in React projects:

<JaaSMeeting
    appId = { YOUR_APP_ID }
    roomName = { YOUR_ROOM_NAME }
/>

...or with the stage.8x8.vc domain:

<JaaSMeeting
    appId = { YOUR_APP_ID }
    roomName = { YOUR_ROOM_NAME }
    useStaging = { true }
/>
Properties specific to the JaasMeeting component
appId

Required. Provides an isolated context and prefixes the room name.

useStaging

Optional. Tells whether to use the staging environment or not.

Common properties
roomName

Required. String used when joining the meeting.

getIFrameRef

Optional. Callback to retrieve the parent node of the IFrame for more control (e.g. styling).

<JitsiMeeting
    ...
    getIFrameRef = { iframeRef => { iframeRef.style.height = '700px'; } }
/>
onApiReady

Optional. Callback triggered when the external API is loaded to expose it for events and commands.

<JitsiMeeting
    ...
    onApiReady = { externalApi => console.log('Jitsi Meet External API', externalApi) }
/>
onReadyToClose

Optional. Callback triggered when the meeting is ready to be closed.

<JitsiMeeting
    ...
    onReadyToClose = { () => console.log('Jitsi Meet is ready to be closed') }
/>
configOverwrite

Optional. Object used for options overrides.

interfaceConfigOverwrite

Optional. Object used for more options overrides.

jwt

Optional. Token for authentication.

invitees

Optional. Participants list.

devices

Optional. Information regarding the devices used during the call.

userInfo

Optional. Details about the participant that started the meeting.

lang

Optional. The default meeting language.

release

Optional. Information regarding the stage.8x8.vc or 8x8.vc release version. Expects the following format: release-1234.

spinner

Optional. Custom loading view while the IFrame is loading.

Sample

Install and run the project from the example directory to see the JitsiMeeting module in action.

npm run demo

jitsi-meet-react-sdk's People

Contributors

alganzory avatar federico-ntr avatar mihhu avatar robertpin avatar saghul avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jitsi-meet-react-sdk's Issues

JWT error: Kid claim is missing

Details
I have an application with having Django backend and React Webapp frontend and a React native mobile app (react native). Earlier I was using an unofficial Jitsi package on Webapp to host video calls. The package I used was jutsu

Recently with the release of the official Jitsi React native SDK, I decided to upgrade my packages on web app and mobile app to the official Jitsi. So I added the React native SDK on mobile and React SDK on webapp.

I also have a self-hosted video server with auth_type set to JWT.

I followed the steps mentioned in the Jitsi SDK documentation and the mobile upgrade of Jitsi is working as expected but I am getting issues related to JWT.

  1. The first issue I got in the console was related to invalid nbf value which I tackled by adding of value to my JWT token.
    image
  2. After this was fixed I got another error in the console related to JWT error: kid claim missing. From the PyJWT documentation I got to know that it is a key ID that needs to pass as a header. Though I am unsure how it is generated but I tried to add a random key and passed it in the header while generating the token. Here is the payload that I am using to generate JWT
    image
  3. After I passed the kid value I got the below error.
    image
  4. I am able to start the video if I directly open my video server URL by adding the generated JWT token to my video server URL in this format - https://<my-video-server-url>/<room-id>?jwt=<jwt-token>. With this I can say that the token is valid token and there is some issue with the Jitsi package as with the unofficial package I was using earlier this issue is not coming.

Is anyone aware of this issue?

startRecording not working

I'm trying to automatically start the recording for the meeting as soon as the user joins. So far I have tried both of the following:

onApiReady={(externalApi) => {
  externalApi.executeCommand("startRecording", {
    mode: "file",
  });
}}

and

onApiReady={(externalApi) => {

  externalApi.startRecording({
    mode: "file",
  });
}}

but neither approach has worked for me. I have jibri setup (the jitsi server is self hosted using jitsi-docker). Starting and stopping the recording manually works as expected. Any help to do this programmatically would be appreciated!

Accessing redux store features/base/tracks

Hi,

I'm trying to access the remote audio stream (incoming) of a conferene. I'm doing this to record the incoming audio stream to a wav file.

Based on information given here, the incoming (remote) audio stream is available at the redux store features/base/tracks.

Is it possible to access the redux store features/base/tracks from jitsi-meet-react-sdk? Any hint on achieving this would be really great.

Thank you.

Vue Package?

Hey we will very likely be using JaaS with our Vue frontend. A Vue wrapper would be highly appreciated.

How to experience the whiteboard feature๏ผŸ

I learned that jitsi has added the whiteboard function,
but after using the react-sdk 1.3.0 version on my app,
there is still no whiteboard button on the web side,
what should I do?

react-sdk version : 1.3.0
Thanks

ClockSync net::ERR_NAME_NOT_RESOLVED

Hello.

I am trying to use the very basics and I am facing a weird issue. In short terms: sometimes jitsi react sdk works without any problem and sometimes it doesn't.

I think the below image provides most of the details you'll need:
image

Code:

const configOverwrite = {
    startWithAudioMuted: true,
    hiddenPremeetingButtons: ['microphone'],
  };

const userInfo = {
    displayName: auth.user.username,
    email: auth.user.email,
  };

const handleExitMeeting = () => {
    navigator('/');
  };

<JitsiMeeting
              roomName={searchParams.get('roomName')}
              getIFrameRef={(node) => (node.style.height = conferenceHeight)}
              onReadyToClose={() => handleExitMeeting()}
              configOverwrite={configOverwrite}
              userInfo={userInfo}
              spinner={() => {
                return <Spinner animation="border" />;
              }}
            />

We need a method to modify UI of notifications in jitsi to add a dial in button.

Problem Statement:
In meeting users face many different kind of problems like network issue microphone or video issue, so we get its relative error notifications, so we need a way from which we can add a dial in button beside OK button in notification message and on click of it user will be able to add his phone number and join the call from phone.


jitsinotif

The configOverwrite participantsPane option doesn't work

Hello, here is my React JitsiMeeting component :

<JitsiMeeting
configOverwrite={{
...
"participantsPane": {
"hideModeratorSettingsTab": true,
"hideMoreActionsButton": true,
"hideMuteAllButton": true
},
...
}}
/>

Despite the true values in participantsPane, I have the โ€˜Mute microphoneโ€™ button in participants pane:

jitsi

I also tested by creating a custom-config.js file :

config.participantsPane = {
hideModeratorSettingsTab: true,
hideMoreActionsButton: true,
hideMuteAllButton: true
}

But this has no effect.

Could you please help me?

Thanks.

Error with Jest Test

Hi all !

I'm trying to test my app with Jest and using the sdk. However, as soon as I try to test a component using JitsiMeeting, impossible.
Just in case it was my setup, I started from scratch with a blank CRA project, I just installed the SDK, it does the same.

Help :/

` โ— Test suite failed to run

Jest encountered an unexpected token

Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

By default "node_modules" folder is ignored by transformers.

Here's what you can do:
 โ€ข If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
 โ€ข If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
 โ€ข To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
 โ€ข If you need a custom transformation specify a "transform" option in your config.
 โ€ข If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation

Details:

/Users/nathanpanchout/Documents/Societeฬ/dossier sans titre/jitsi-test/node_modules/@jitsi/react-sdk/lib/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export * from './components';
                                                                                  ^^^^^^

SyntaxError: Unexpected token 'export'

  1 | import * as React from 'react';
> 2 | import {JitsiMeeting} from "@jitsi/react-sdk";
    | ^
  3 |
  4 | export interface VideoMeetingProps {
  5 | }

  at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1728:14)
  at Object.<anonymous> (src/components/VideoMeeting/VideoMeeting.tsx:2:1)
  at Object.<anonymous> (src/components/VideoMeeting/VideoMeeting.test.tsx:3:1)`

After ending call, the space occupied by the JaaSMeeting component becomes blank

I am using JaaSMeeting component in my React application. I have it in right side of my app. When I end the meeting the space is empty and it does not look good. Is there a way to show something like "Meeting has ended" or relaunch the meeting.

Current Code:

<JaaSMeeting
         appId={"my-app-id"}
         roomName="DoctorRoomForPatients"
         configOverwrite={{
           disableThirdPartyRequests: true,
           disableLocalVideoFlip: true,
           backgroundAlpha: 0.5,
           startWithAudioMuted: true,
           startWithVideoMuted: true,
           enableNoAudioDetection: true,
           enableNoisyMicDetection: true,
           startAudioMuted: 10,
           startVideoMuted: 10,
         }}
         getIFrameRef={(iframeRef) => {
           iframeRef.style.height = "100vh";
         }}
       />

Adding Screenshots for the current behaviour.
Screenshot from 2024-04-16 15-02-41
After ending the call:
Screenshot from 2024-04-16 15-02-54

Or is there any other way to mitigate this?

Unexpected token 'export'

image

Throws the error below when working with Astro + Vite
`[vite] Error when evaluating SSR module /src/components/meeting.jsx: failed to import "@jitsi/react-sdk"

node_modules@jitsi\react-sdk\lib\index.js:1

export * from './components';

^^^^^^`

interfaceConfigOverwrite being ignored

version 1.3.0

The following gets completly ignored.

...
interfaceConfigOverwrite={{
  MOBILE_APP_PROMO: false,
  SHOW_JITSI_WATERMARK: false,
  DISABLE_JOIN_LEAVE_NOTIFICATIONS: true,
  SHOW_BRAND_WATERMARK: false,
  SHOW_POWERED_BY: false,
  SHOW_PROMOTIONAL_CLOSE_PAGE: false,
  JITSI_WATERMARK_LINK: '',
}}
...

When inspecting the iframe I can see the parameters are passed:

#jitsi_meet_external_api_id=3
&config.startWithAudioMuted=true
&config.disableModeratorIndicator=false
&config.enableEmailInStats=true
&interfaceConfig.MOBILE_APP_PROMO=false
&interfaceConfig.SHOW_JITSI_WATERMARK=false
&interfaceConfig.DISABLE_JOIN_LEAVE_NOTIFICATIONS=true
&interfaceConfig.SHOW_BRAND_WATERMARK=false
&interfaceConfig.SHOW_POWERED_BY=false
&interfaceConfig.SHOW_PROMOTIONAL_CLOSE_PAGE=false
&interfaceConfig.JITSI_WATERMARK_LINK=%22%22

But seem to be ignored, We're hosting ourselves, is there additional config needed to make that work?

I get the same issue when pointing to meet.jit.si instead of our server

I found this comment jitsi/jitsi-meet#7354 (comment)
Which mentions modifying a file directly, I assume this to be a file from the iframe code hosted on our server.
How do we do this is we have deployed by forking https://github.com/jitsi/docker-jitsi-meet ?

How to change the language file of Jitsi JAAS?

I'm using your package and utilizing JAAS. When switching to Japanese language, there are many untranslated keys. How can I modify? Can I add keys or edit some of the existing Japanese sentences?

Thanks

error - SyntaxError: Unexpected token 'export' - NEXT.JS

i got this error on my Next.js app > "error - SyntaxError: Unexpected token 'export' "
IS THIS @jitsi/react-sdk ONLY SUPPORTS IN REACT (create-react-app) ??

here is my code >>

`import { JitsiMeeting } from "@jitsi/react-sdk";
import type { NextPage } from "next";

const Home: NextPage = () => {
return (


<JitsiMeeting
roomName={"nihal"}
configOverwrite={{
startWithAudioMuted: true,
disableModeratorIndicator: true,
startScreenSharing: true,
enableEmailInStats: false,
}}
interfaceConfigOverwrite={{
DISABLE_JOIN_LEAVE_NOTIFICATIONS: true,
}}
userInfo={{
displayName: "YOUR_USERNAME",
email: "[email protected]",
}}
// onApiReady={(externalApi) => handleApiReady(externalApi)}
// onReadyToClose={handleReadyToClose}
// getIFrameRef={handleJitsiIFrameRef1}
/>

);
};

export default Home;
`

problem with loading iframe after the spinner

i've encountred a problem between the spinner unmount and the loading of the iframe. in the video bellow on slow internet, the user doesn't know if the iframe is loaded successfully or not. i want to unmount the spinner component just after the iframe is fully loaded.

jitsiMeeting.spinner.webm

How to use jibri to a recording meeting with JitsiMeeting component.

I'm new to using jitsi and would like help integrating a way to record my meetings, I did some research and found a service called jibri but I don't know how to use and configure it. I accept any suggestion

my stupid code.

'use client'

import { JitsiMeeting } from '@jitsi/react-sdk'
import { ReactElement, ReactNode, useRef, useState } from 'react'

interface Payload {
  muted?: boolean
  isOpen?: boolean
  unreadCount?: number
  participant?: Participant
}

interface Participant {
  id: string
  name: string
}

export default function Page() {
  const apiRef = useRef<any>(null)
  const [logItems, updateLog] = useState<string[]>([])
  const [showNew, toggleShowNew] = useState<boolean>(false)
  const [knockingParticipants, updateKnockingParticipants] = useState<Participant[]>([])
  const [recording, setRecording] = useState(null)

  const handleRecordingAvailable = (newRecording: any) => {
    setRecording(newRecording)
  }

  const printEventOutput = (payload: Payload) => {
    updateLog((items) => [...items, JSON.stringify(payload)])
  }

  const handleAudioStatusChange = (payload: Payload, feature: string) => {
    if (payload.muted) {
      updateLog((items) => [...items, `${feature} off`])
    } else {
      updateLog((items) => [...items, `${feature} on`])
    }
  }

  const handleChatUpdates = (payload: Payload) => {
    if (payload.isOpen || !payload.unreadCount) {
      return
    }
    apiRef.current.executeCommand('toggleChat')
    updateLog((items) => [...items, `you have ${payload.unreadCount} unread messages`])
  }

  const handleKnockingParticipant = (payload: Payload) => {
    updateLog((items) => [...items, JSON.stringify(payload)])
    if (payload.participant) {
      updateKnockingParticipants((participants) => [...participants, payload.participant] as any)
    }
  }

  const resolveKnockingParticipants = (condition: (participant: Participant) => boolean) => {
    knockingParticipants.forEach((participant) => {
      apiRef.current.executeCommand('answerKnockingParticipant', participant.id, condition(participant))
      updateKnockingParticipants((participants) => participants.filter((item) => item.id === participant.id))
    })
  }

  const handleJitsiIFrameRef1 = (iframeRef: HTMLIFrameElement) => {
    iframeRef.style.border = '10px solid #3d3d3d'
    iframeRef.style.background = '#3d3d3d'
    iframeRef.style.height = '400px'
    iframeRef.style.marginBottom = '20px'
  }

  const handleJitsiIFrameRef2 = (iframeRef: HTMLIFrameElement) => {
    iframeRef.style.marginTop = '10px'
    iframeRef.style.border = '10px dashed #df486f'
    iframeRef.style.padding = '5px'
    iframeRef.style.height = '400px'
  }

  const handleJaaSIFrameRef = (iframeRef: HTMLIFrameElement) => {
    iframeRef.style.border = '10px solid #3d3d3d'
    iframeRef.style.background = '#3d3d3d'
    iframeRef.style.height = '400px'
    iframeRef.style.marginBottom = '20px'
  }

  const handleApiReady = (apiObj: any) => {
    apiRef.current = apiObj
    apiRef.current.on('knockingParticipant', handleKnockingParticipant)
    apiRef.current.on('audioMuteStatusChanged', (payload) => handleAudioStatusChange(payload, 'audio'))
    apiRef.current.on('videoMuteStatusChanged', (payload) => handleAudioStatusChange(payload, 'video'))
    apiRef.current.on('raiseHandUpdated', printEventOutput)
    apiRef.current.on('titleViewChanged', printEventOutput)
    apiRef.current.on('chatUpdated', handleChatUpdates)
    apiRef.current.on('knockingParticipant', handleKnockingParticipant)
    apiRef.current.executeCommand('startRecording', { mode: 'file' })
  }

  const handleReadyToClose = () => {
    alert('Ready to close...')
  }

  const generateRoomName = () => `JitsiMeetRoomNo${Math.random() * 100}-${Date.now()}`

  const renderNewInstance = (): ReactNode => {
    if (!showNew) {
      return null
    }

    return <JitsiMeeting roomName={generateRoomName()} getIFrameRef={handleJitsiIFrameRef2 as any} />
  }

  const renderButtons = (): ReactElement => {
    return (
      <div style={{ margin: '15px 0' }}>
        <div
          style={{
            display: 'flex',
            justifyContent: 'center',
          }}
        >
          <button
            type="text"
            title="Click to execute toggle raise hand command"
            style={{
              border: 0,
              borderRadius: '6px',
              fontSize: '14px',
              background: '#f8ae1a',
              color: '#040404',
              padding: '12px 46px',
              margin: '2px 2px',
            }}
            onClick={() => {
              console.log('toggleRaiseHand')
              apiRef.current.executeCommand('toggleRaiseHand')
            }}
          >
            Raise hand
          </button>
          <button
            type="text"
            title="Click to approve/reject knocking participant"
            style={{
              border: 0,
              borderRadius: '6px',
              fontSize: '14px',
              background: '#0056E0',
              color: 'white',
              padding: '12px 46px',
              margin: '2px 2px',
            }}
            onClick={() => {
              console.log('resolveKnockingParticipants')
              resolveKnockingParticipants(({ name }) => !name.includes('test'))
            }}
          >
            Resolve lobby
          </button>
          <button
            type="text"
            title="Click to execute subject command"
            style={{
              border: 0,
              borderRadius: '6px',
              fontSize: '14px',
              background: '#df486f',
              color: 'white',
              padding: '12px 46px',
              margin: '2px 2px',
            }}
            onClick={() => {
              console.log('subject')
              apiRef.current.executeCommand('subject', 'New Subject')
            }}
          >
            Change subject
          </button>
          <button
            type="text"
            title="Click to create a new JitsiMeeting instance"
            style={{
              border: 0,
              borderRadius: '6px',
              fontSize: '14px',
              background: '#3D3D3D',
              color: 'white',
              padding: '12px 46px',
              margin: '2px 2px',
            }}
            onClick={() => toggleShowNew(!showNew)}
          >
            Toggle new instance
          </button>
        </div>
      </div>
    )
  }

  const renderLog = () =>
    logItems.map((item, index) => (
      <div
        style={{
          fontFamily: 'monospace',
          padding: '5px',
        }}
        key={index}
      >
        {item}
      </div>
    ))

  const renderSpinner = () => (
    <div
      style={{
        fontFamily: 'sans-serif',
        textAlign: 'center',
      }}
    >
      Loading..
    </div>
  )

  return (
    <>
      <h1
        style={{
          fontFamily: 'sans-serif',
          textAlign: 'center',
        }}
      >
        Phd GRAVAS
      </h1>
      <JitsiMeeting
        roomName={generateRoomName()}
        spinner={renderSpinner}
        configOverwrite={{
          subject: 'lalalala',
          hideConferenceSubject: false,
        }}
        onApiReady={(externalApi: any) => handleApiReady(externalApi)}
        onReadyToClose={handleReadyToClose}
        getIFrameRef={handleJitsiIFrameRef1 as any}
      />
      {renderButtons()}
      {renderNewInstance()}
      {renderLog()}
    </>
  )
}

Object returned by getIFrameRef is not reactive

I have a boolean variable which should control some of the styles of Jitsi.

<JitsiMeeting
  domain={content.domain}
  roomName={content.roomName}
  onApiReady={handleApiReady}
  getIFrameRef={(iframeRef) => {
    iframeRef.style.height = "calc(100% - 35px)";
    iframeRef.style.pointerEvents = minimized ? "none" : "unset"
  }}
/>

I expect the style attribute of the iframe to change when the value of minimized changes but it doesn't.

not minimized

minimized

It may be that it's completely impossible to do this thing and I'm missing some fundamental concept of how this works.

npm install fails on react 17.0.2

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! 
npm ERR! While resolving: [email protected]
npm ERR! Found: [email protected]
npm ERR! node_modules/react
npm ERR!   react@"^17.0.2" from the root project
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^16.8.0" from @jitsi/[email protected]
npm ERR! node_modules/@jitsi/web-sdk
npm ERR!   @jitsi/web-sdk@"*" from the root project
npm ERR! 
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR! 
...

I think the react peerDependency needs to be updated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.