React Walkthrough

Building a React App with Huddle01

💡

We have upgraded our SDK to v2 (2.x.x). For the previous stable release, please visit here

Walkthrough

The following guide explains how you can integrate audio/video into your React web-app seamlessly using the Huddle01 React SDK in your Next.js App.

Install @huddle01/react in your react app

To power your React dApp with audio/video communication using Huddle01, install the following packages:

pnpm i @huddle01/react @huddle01/server-sdk

Initialization of project

Head over to API Keys Page and connect your wallet to get your project credentials:

  • API Key
  • projectId

Once done, initialize your project by creating an instance of HuddleClient and pass it in HuddleProvider. Make sure that you wrap HuddleProvider in your root i.e.

_app.tsx
import type { AppProps } from "next/app";
 
import { HuddleClient, HuddleProvider } from "@huddle01/react";
 
const huddleClient = new HuddleClient({
  projectId: process.env.NEXT_PUBLIC_PROJECT_ID!,
  options: {
    // `activeSpeakers` will be most active `n` number of peers, by default it's 8
    activeSpeakers: {
      size: 12,
    },
  },
});
 
export default function App({ Component, pageProps }: AppProps) {
  return (
    <HuddleProvider client={huddleClient}>
      <Component {...pageProps} />
    </HuddleProvider>
  );
}

Room Creation

You need a roomId for joining a room, which you can get by calling the Create Room API. Make sure that you are calling this API from server side. If you are using pages router you can create an API route or for app router you can easily create a server side component.

pages/api/create-room.ts
import axios from 'axios';
import type { NextApiRequest, NextApiResponse } from 'next';
 
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
  try {
    const { data } = await axios.post(
      'https://api.huddle01.com/api/v1/create-room',
      {
        title: 'Huddle01 Meet',
      },
      {
        headers: {
          'Content-Type': 'application/json',
          'x-api-key': process.env.API_KEY as string,
        },
      }
    );
 
    res.status(200).json(data);
  } catch (error) {
    res.status(500).json(error);
  }
};
 
export default handler;

Generating the Access Token

Once, roomId is generated you need to generate accessToken which is required to join room.

pages/api/getAccessToken.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { AccessToken, Role } from '@huddle01/server-sdk/auth';
 
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const { roomId } = req.query;
 
  if (!roomId) {
    return res.status(400).json({ error: 'roomId is required' });
  }
 
  const accessToken = new AccessToken({
    apiKey: process.env.API_KEY!,
    roomId: roomId as string,
    role: Role.HOST,
    permissions: {
      admin: true,
      canConsume: true,
      canProduce: true,
      canProduceSources: {
        cam: true,
        mic: true,
        screen: true,
      },
      canRecvData: true,
      canSendData: true,
      canUpdateMetadata: true,
    }
  });
 
  const token = await accessToken.toJwt();
 
  return res.status(200).json({ token });
}

Joining and leaving the room

You need roomId and accessToken to join room using joinRoom method from useRoom hook.

💡

It's recommended that you send roomId over a url like YOUR_URL/roomId.

app.tsx
import { useRoom } from '@huddle01/react/hooks';
 
const App = () => {
  const { joinRoom, leaveRoom } = useRoom({
    onJoin: () => {
      console.log('Joined the room');
    },
    onLeave: () => {
      console.log('Left the room');
    },
  });
  
  return (
    <div>
      <button onClick={() => {
        joinRoom({
          roomId: 'YOUR_ROOM_ID',
          token: 'YOUR_ACCESS_TOKEN'
        });
      }}>
        Join Room
      </button>      
      <button onClick={leaveRoom}>
        Leave Room
      </button> 
    </div>
  );
};

Sending media across participants

To produce video,audio, and screenShare streams, you can use useLocalVideo,useLocalAudio and useLocalScreenShare hook.

app.tsx
  import { useLocalVideo, useLocalAudio, useLocalScreenShare } from '@huddle01/react/hooks';
 
  const App = () => {
    const { stream, enableVideo, disableVideo, isVideoOn } = useLocalVideo();
    const { stream, enableAudio, disableAudio, isAudioOn } = useLocalAudio();
    const { startScreenShare, stopScreenShare, shareStream } = useLocalScreenShare();
 
    return (
      <div>
        {/* Webcam */} 
        <button 
          onClick={() => {
            isVideoOn ? disableVideo() : enableVideo()
          }}>
          Fetch and Produce Video Stream
        </button>
 
        {/* Mic */} 
       <button 
          onClick={() => {
            isAudioOn ? disableAudio() : enableAudio();
          }}>
          Fetch and Produce Audio Stream
        </button>
 
        {/* Screen Share */}
        <button 
          onClick={() => {
            shareStream ? stopScreenShare() : startScreenShare();
          }}>
          Fetch and Produce Screen Share Stream
        </button>
      </div>
    );
  };
 

Advanced: Using the useLocalMedia hook

app.tsx
  import { useLocalMedia } from '@huddle01/react/hooks';
 
  const App = () => {
    const { fetchStream } = useLocalMedia();
 
    return (
      <div>
        {/* Webcam */} 
        <button 
          onClick={() => fetchStream({ mediaDeviceKind: 'cam' })} >
          Fetch Cam Stream
        </button>
 
        {/* Mic */} 
       <button 
          onClick={() => fetchStream({ mediaDeviceKind: 'mic' })} >
          Fetch Mic Stream
        </button>
 
      </div>
    );
  };
 

Receiving the audio and video streams

We can use hooks such as useRemoteAudio, useRemoteVideo and useRemoteScreenShare for consuming audio, video and screen-share streams.

ShowPeers.tsx
import { 
  usePeerIds, 
  useRemoteVideo, 
  useRemoteAudio, 
  useRemoteScreenShare 
} from '@huddle01/react/hooks';
import { Audio, Video } from '@huddle01/react/components';
import { FC } from 'react';
 
interface RemotePeerProps {
  peerId: string;
}
 
const RemotePeer: FC<RemotePeerProps> = ({ peerId }) => {
  
  const { stream: videoStream } = useRemoteVideo({ peerId });
  const { stream: audioStream } = useRemoteAudio({ peerId });
  const { videoStream: screenVideoStream, audioStream: screenAudioStream } = useRemoteScreenShare({ peerId });
 
  return (
    <div>
      {videoStream && <Video stream={videoStream}>}
      {audioStream && <Audio stream={audioStream}>}
      {screenVideoStream && <Video stream={screenVideoStream}>}
      {screenAudioStream && <Audio stream={screenAudioStream}>}
    </div>
  ) 
}
 
const ShowPeers = () => {
  const { peerIds } = usePeerIds({ roles: [Role.HOST, Role.CO_HOST] }); // Get Hosts And Cohost's peerIds
 
  return (
    <div>
      {peerIds.map(peerId => {
        return <RemotePeer peerId={peerId}  />
      })}
    </div>
  )
}
 
export default ShowPeers;

You're all set! Happy Hacking! 🎉

For more information, please refer to the SDK Reference.

Audio/Video Infrastructure designed for the developers to empower them ship simple yet powerful Audio/Video Apps.
support
company
Copyright © 2024 Graphene 01, Inc. All Rights Reserved.