Saturday, October 15, 2022
HomeWeb DevelopmentConstructing a React stay streaming app with 100ms

Constructing a React stay streaming app with 100ms


Reside streaming is an effective way to interact with audiences ranging anyplace from one individual to thousands and thousands in real-time. In contrast to video conferences the place anybody can share their display screen or converse at any time, in stay streaming, viewers have restricted permissions. Implementing stay streaming from scratch could be time-consuming, however there are providers that we are able to use so as to add this function with only a few steps, considered one of which is 100ms.

On this tutorial, we’ll find out about 100ms by constructing a stay streaming app with an interactive function the place broadcasters and viewers can talk utilizing chat.

To observe together with this tutorial, you have to be aware of React and React Hooks. You must also have Node.js put in in your system.

The complete code for this tutorial is on the market on GitHub. Let’s get began!

Introduction to 100ms

100ms is a cloud platform that enables builders so as to add video and audio conferencing to internet, Android, and iOS purposes. It supplies REST APIs, SDKs, and a dashboard that makes it easy to seize, distribute, file, and render stay interactive audio and video.

Utilizing 100ms to construct a stay app is kind of easy, involving simply two main steps. The primary is creating and configuring a template within the dashboard with roles and settings for the app and its customers.

The template configuration will probably be completely different relying on what sort of app you’re constructing, video convention, digital occasion, or stay streaming. For instance, in a stay streaming app, streamers or broadcasters can share video, audio, or their display screen, whereas a viewer can’t do any of the above. We’ll set all this up within the template.

As an alternative of making a customized template, we are able to select from the out there starter kits that have already got the suitable configurations for several types of stay apps and simply add a little bit high-quality tuning. After organising the template, we’ll use the SDK with its intuitive strategies, hooks, and selectors on the shopper aspect to combine and work with 100ms.

Earlier than getting began, you have to be aware of the 100ms ideas under:

  • Room: Once we be a part of an audio or video name, the members are mentioned to be in a room
  • Peer: A participant within the audio or video name. You’re the native peer, whereas others are distant friends
  • Observe: There are two forms of tracks a peer can have, audio and video

Establishing 100ms

To arrange the stay streaming template, navigate to 100ms and arrange a person account within the browser. When logged in, click on Create Your First App on the dashboard and a modal will seem the place we are able to create a customized template or select one which has already been created:

100ms App Templates

As an alternative of making a brand new template, we’ll use the stay streaming app starter equipment. Hover on the Reside Streaming Starter Equipment template and click on on the Deploy now button that seems. You’ll see the next:

Deploy Live Streaming Starter Kit

Within the Select your Account Sort space, choose Private, then click on Subsequent, and also you’ll see the next:

Choose Personal Account Type

We have to enter a singular subdomain. For this, I’ll enter livestreamnow, however you should utilize some other identify. After that, click on Proceed. With this, a stay streaming starter equipment has been created, and also you’ll see it after we navigate to our dashboard:

Live Stream Starter Kit Created

To view the configuration of the starter template, hover on it and click on on the setting icon that seems. You’ll see the next display screen:

Discover that two roles appropriate for a stay streaming app have already been created, broadcaster and hls-viewer.

The broadcaster position represents a streamer that publishes their audio or video. They’ve all permissions turned on, permitting them to carry out all out there operations, like sharing audio and video, muting and unmuting any participant within the room, stopping and beginning the stay stream, and extra. We will edit the operations allowed for this position or some other position by simply toggling the change subsequent to the operation we need to disable or allow.

The hls-viewer position represents the viewers members that be a part of the stay stream and may work together utilizing messaging. None of their permissions are turned on, which is normally the case for the viewers in a stay stream.

We will create different roles by clicking on Add a Position on the fitting aspect of the display screen after which modifying the permissions to go well with our wants. Nevertheless, for the reason that required roles for our use case have already been created for us, we received’t try this.

Constructing a stay streaming app with 100ms

100ms consists of assist for HLS for stay streaming, which permits scaling to thousands and thousands of viewers, primarily because of its assist by OSes and CDNs. Nevertheless, in comparison with different protocols, stay streaming by way of HLS is slower and has a better latency.

On this part, we’ll use the 100ms SDK to construct the stay streaming app. Earlier than continuing, you have to be aware of the next:

  • hmsStore: Incorporates the entire state of the room at any given time, together with, for instance, participant particulars, messages, and monitor states
  • hmsActions: Used to carry out any motion like becoming a member of, muting, and sending a message

Establishing React

I’ve already created a starter template that we’ll use for this tutorial, so we are able to focus solely on utilizing 100ms. Clone the GitHub repo with the next instructions:

$ git clone -b starter https://github.com/Tammibriggs/LiveStreaming-100ms.git

$ cd LiveStreaming-100ms

$ npm set up

Now, after we begin the app utilizing the npm begin command, we’ll see the next web page:

Start 100ms Example App Homepage

On the web page above, we are able to enter a reputation and choose the position we need to use when becoming a member of the room.

At this level within the tutorial, after we click on on the Be a part of button, we received’t be taken to a special web page; we’ll work on that later. As an alternative, after clicking on the Be a part of button, the web page will appear like the next picture:

Join Live Stream App Example 100ms

Combine 100ms into our app

To combine 100ms into our React app, first, we’ll set up the SDK, which we’ll must construct the app. We’ll set up one further dependency, HLS.js, to assist us in displaying the HLS stream for browsers that don’t assist HLS natively:

$ npm i @100mslive/[email protected] hls.js

Subsequent, to initialize the SDK, we have to wrap our complete software with the <HMSRoomProvider /> element. Within the starter app, head over to the index.js file within the src listing and modify it to appear like the next code:

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/shopper';
import './index.css';
import App from './App';
import { HMSRoomProvider } from '@100mslive/react-sdk';

const root = ReactDOM.createRoot(doc.getElementById('root'));
root.render(
  <React.StrictMode>
    <HMSRoomProvider>
      <App />
    </HMSRoomProvider>
  </React.StrictMode>
);

Now, let’s go forward and retrieve the required credentials for constructing our app, room_id and token_endpoint. To get the room_id, navigate to your 100ms dashboard. Within the sidebar, click on on Rooms, and also you’ll be taken to the next web page:

Fetch 100ms Room Credentials

The 2 rooms above have already been created for us, which was completed when deployed the stay streaming starter equipment. To confirm that the rooms have the broadcaster and hls-viewer roles required for our app, click on on any of the IDs beneath the Room Id desk head to examine:

100ms Room ID Verification

Now, copy one of many IDs and paste it within the acceptable variable within the .env file of the starter app.

To get the token_endpoint on the sidebar, first click on on Developer. On the subsequent web page, copy the token_endpoint and paste it within the acceptable variable within the .env file:

100ms Token Endpoint Credentials

Becoming a member of a room

Now, we’ll work on the web page under:

Joining Chat Room 100ms

Earlier than we are able to start streaming by way of HLS, we first want to hitch a room utilizing the be a part of technique on hmsActions, which requires us to go a config object. The config object will need to have the next fields:

  • userName: The identify of the person that will probably be seen to everybody related to the room
  • authToken: A client-side token that we’ll use to authenticate the person

If we have been constructing a video convention, digital assembly, or some other video name app, we may publish our video by becoming a member of the room, which might be seen by different friends or members within the room. Nevertheless, since we’ll be stay streaming by way of HLS, the method is completely different.

Head over to src/JoinRoom.js and add the next import:

// src/JoinRoom.js
import { useHMSActions } from "@100mslive/react-sdk";

Subsequent, add the next traces of code after the selectedRole state:

// src/JoinRoom.js
const hmsActions = useHMSActions()

Subsequent, let’s create the perform for producing the authToken and be a part of the room. Add the next traces of code after the hmsActions variable:

// src/JoinRoom.js
const handleSubmit = async (e) => {
  e.preventDefault()
  const response = await fetch(`${ENDPOINT}api/token`, {
    technique: "POST",
    physique: JSON.stringify({
      user_id: `${Date.now()}`,
      position: selectedRole, //broadcaster, hls-viewer
      sort: "app",
      room_id: ROOM_ID,
    }),
  })
  const { token } = await response.json()
  // Becoming a member of the room
  hmsActions.be a part of({
    userName: username,
    authToken: token,
  })
}

Within the code above, we’re sending a request to generate the authentication token utilizing the endpoint we provided in our .env file. The request takes the chosen position and room ID as parameters. After producing the token, we use it together with the username entered within the enter discipline to hitch the room utilizing the be a part of technique.

To name this perform when the shape is submitted, modify the opening type tag <type> to appear like the next code:

// src/JoinRoom.js
<type className="be a part of" onSubmit={handleSubmit}>

Proper now, after we navigate to http://localhost:3000/ in our browser, enter a username, and click on on the Be a part of button, we’ll be a part of the room. Nevertheless, there received’t be any adjustments within the UI but. To repair this, we’d like a solution to know the connection state of the room and to cover the shape after we’ve related. We will accomplish that utilizing the selectIsConnectedToRoom selector and the useHMSStore Hook.

Head over to src/App.js and add the next import:

// src/App.js
import { useHMSStore, selectIsConnectedToRoom } from '@100mslive/react-sdk';

Subsequent, add the next traces of code within the App element:

// src/App.js  
const isConnected = useHMSStore(selectIsConnectedToRoom)

Subsequent, modify the return assertion within the App element to appear like the next:

// src/App.js
return (
  <div className="App wrapper"> 
    {isConnected
      ? <Room />
      : <JoinRoom />
    }
  </div>
);

With this, after becoming a member of the room, we’ll see the next web page:

100ms Page Join

Displaying video tiles

After becoming a member of the room, our video and audio will probably be revealed, that means different friends within the room can view it. Nevertheless, since we’re stay streaming by way of HLS, different viewers shouldn’t be capable of see this. For each broadcaster that joins the room, we wish solely a video tile of their revealed video to be exhibited to different broadcasters.

For this, we’ll use the useVideo Hook, which takes in a video monitor ID and returns a videoRef to be handed to a video factor. To get the video monitor ID, we first must get the record of friends within the room. We will accomplish that utilizing the useHMSStore Hook and selectPeers selector.

Modify the Stream.js file within the src listing to appear like the next code:

// src/Stream.js
import VideoTile from "./VideoTile";
import HlsView from "./HlsView";
import { selectLocalPeer, selectPeers, useHMSStore } from "@100mslive/react-sdk";

perform Stream() {
  const friends = useHMSStore(selectPeers)
  const localPeer = useHMSStore(selectLocalPeer)

  return (
    <div className="stream">
      {localPeer.roleName === 'broadcaster' &&
        friends.filter((peer) => peer.roleName === 'broadcaster')
        .map((peer) => (
          <VideoTile key={peer.id} peer={peer} friends={friends} />
        )) 
      }
    </div>
  )
}

export default Stream

Within the code above, we’re getting the record of friends within the room in addition to the native peer, which is you. We’re conditionally rendering the VideoTile element solely when the roleName discipline of localPeer equals broadcaster.

Doing so will make the video tiles seen solely to broadcasters as a result of we haven’t began streaming but. After that, utilizing the filter technique, we are able to create a brand new array containing solely friends who’re broadcasters, then mapping via it and passing every peer to the VideoTile element.

Now, head over to the src/VideoTile.js file. Let’s use useVideo to start out displaying the revealed video of broadcasters within the room. Modify the VideoTile.js file to appear like the next code:

// src/VideoTile.js
import { useVideo } from "@100mslive/react-sdk";

perform VideoTile({ peer, friends }) {
  const { videoRef } = useVideo({
    trackId: peer.videoTrack
  })

  const numberOfBroadCasters = () => {
    const broadcasters = friends.filter((peer) => {
      return peer.roleName === 'broadcaster'
    })
    return broadcasters.size
  }

  return (
    <video
      ref={videoRef}
      className={numberOfBroadCasters() >= 2 ? 'video' : ''}
      autoPlay
      muted
      playsInline
    />
  )
}

export default VideoTile

With this, after we be a part of the room as a broadcaster, we should always see our revealed video and the movies of different broadcasters within the room.

Reside stream by way of HLS and show stream to viewers

To begin streaming by way of HLS, we simply must name the startHLSStreaming in hmsActions. To cease the stream, we are able to name the stopHLSStreaming technique, and to get the HLS state, we are able to use the selectHLSState selector. It’s that easy.

Head over to src/Controls.js and add the next imports:

// src/Controls.js
import { selectHLSState, useHMSActions, useHMSStore } from '@100mslive/react-sdk'

Subsequent, add the next traces of code within the Controls element:

// src/Controls.js
const hmsActions = useHMSActions()
const hlsState = useHMSStore(selectHLSState)

Subsequent, add the next capabilities after the hlsState variable for beginning and stopping the stay stream:

// src/Controls.js
const startHLSStreaming = async () => {
  attempt {
    await hmsActions.startHLSStreaming()
  } catch (err) {
      alert(`failed to start out hls ${err}`)
  }
}

const stopHLSStreaming = async () => { 
  attempt {
    await hmsActions.stopHLSStreaming()
  } catch (err) {
      alert(`didn't cease hls ${err}`)
  }
}

To name the capabilities above, change the button element beneath the {/* HLS stream button */} remark within the return assertion with the next code:

// src/Controls.js
{hlsState.working
  ? <Button 
      variant="contained" 
      disableElevation
      className="go away"
      onClick={stopHLSStreaming}
    >
      <StopCircleOutlined /> Cease Streaming
    </Button>
  : <Button 
      variant="contained"
      disableElevation
      onClick={startHLSStreaming}
    >
      <PodcastsOutlined /> Go Reside 
    </Button>
}

Now, to show the HLS stream to viewers, we’ll use HLS.js, which we put in earlier. For extra UI customizations, you may take a look at Video.js, which makes use of HLS.js internally.

When utilizing HLS.js in displaying the stream, we have to go the stream URL to its loadSource technique and likewise go a video factor to it utilizing the attachMedia technique. We will get the stream URL from the hls state, which we are able to retrieve utilizing the selectHLSState selector.


Extra nice articles from LogRocket:


Head over to src/Stream.js and add the next code earlier than the closing tag </> of the div with stream because the className:

// src/Stream.js
{localPeer.roleName === 'hls-viewer' &&
  <HlsView/>
}

Subsequent, head over to src/HlsView and modify the file to appear like the next code:

// src/HlsView
import { selectHLSState, useHMSStore } from '@100mslive/react-sdk'
import Hls from 'hls.js'
import { useEffect, useRef } from 'react'

perform HlsView() {
    const videoRef = useRef(null)
    const hlsState = useHMSStore(selectHLSState)
    const hlsUrl = hlsState.variants[0]?.url
    useEffect(() => {
        if (videoRef.present && hlsUrl) {
            const browserHasNativeHLSSupport = videoRef.present.canPlayType(
                'software/vnd.apple.mpegurl'
            );
            if (Hls.isSupported()) {
                let hls = new Hls()
                hls.loadSource(hlsUrl)
                hls.attachMedia(videoRef.present)
            }
            else if (browserHasNativeHLSSupport) {
                videoRef.present.src = hlsUrl
            }
        }
    }, [hlsUrl])
    return <video ref={videoRef} autoPlay controls></video>;
}

export default HlsView

With this, viewers will now be capable of see the stream from broadcasters.

Including room management functionalities

Let’s add performance to mute and unmute audio and video and to go away the room. Head over to src/Controls.js and add the next imports:

// src/Controls.js
import { selectIsLocalAudioEnabled, selectIsLocalVideoEnabled, selectLocalPeer } from '@100mslive/react-sdk'

Subsequent, add the next traces of code after the hlsState variable:

// src/Controls.js
const audioEnabled = useHMSStore(selectIsLocalAudioEnabled)
const videoEnabled = useHMSStore(selectIsLocalVideoEnabled)
const localPeer = useHMSStore(selectLocalPeer)

We use the selectIsLocalAudioEnabled and selectIsLocalVideoEnabled selectors to get the respective boolean states of the audio and video and decide whether or not they’re presently muted or unmuted. We’ll then toggle the present state and present the suitable icon within the UI. We additionally get localPeer utilizing the selectLocalPeer selector.

To mute and unmute audio and video, we are able to use setLocalVideoEnabled and setLocalAudioEnabled in hmsActions, which receives a boolean as parameter. Within the Controls element, add the next capabilities after the stopHLSStreaming perform:

// src/Controls.js
const toggleAudio = async () => {
  await hmsActions.setLocalAudioEnabled(!audioEnabled);
}

const toggleVideo = async () => {
  await hmsActions.setLocalVideoEnabled(!videoEnabled);
}

Now, to name the perform above, discover the next traces of code within the return assertion:

<IconButton>
  <MicOffOutlined />
</IconButton>
<IconButton>
  <VideocamOffOutlined />
</IconButton>

Modify the code above to the next code:

// src/Controls.js
<IconButton onClick={toggleAudio}>
  {audioEnabled
    ? <MicNoneOutlined />
    : <MicOffOutlined />
  }
</IconButton>
<IconButton onClick={toggleVideo}>
  {videoEnabled
    ? <VideocamOutlined />
    : <VideocamOffOutlined />
  }
</IconButton>

To depart the room, we have to name the go away() technique in hmsActions. After the toggleVideo perform, we have to add the next traces of code:

// src/Controls.js
const leaveRoom = async () => {
  if(localPeer.roleName === 'broadcaster'){
    hmsActions.go away()
    await hmsActions.stopHLSStreaming()
  }else{
    hmsActions.go away()
  }
}

Within the code above, if the roleName discipline of the localPeer equals broadcaster, together with leaving the room, we’re additionally ending the HLS stream in case it’s ongoing.

To name the perform above within the return assertion, we’ll see the next traces of code:

<Button 
  variant="contained" 
  disableElevation
  className="go away"
>
  <LogoutOutlined /> Go away Room
</Button> 

Modify it to the next:

// src/Controls.js
&lt;Button 
  variant="contained" 
  disableElevation
  className="go away"
  onClick={leaveRoom}
>
  <LogoutOutlined /> Go away Room
</Button>

With this, the mute, unmute, and go away performance ought to be working high-quality.

Nevertheless, you’ll discover that even after we be a part of the room as a viewer, all of the UI elements meant to be seen or used solely by the broadcaster will probably be seen, which shouldn’t be so. Viewers ought to solely be capable of see the go away button.

To repair this, modify the return assertion of the Controls element to appear like the next:

// src/Controls.js
return (
  <div className="controls">
    {localPeer.roleName === 'broadcaster'
      ? <>
          <IconButton onClick={toggleAudio}>
            {audioEnabled
              ? <MicNoneOutlined />
              : <MicOffOutlined />
            }
          </IconButton>
          <IconButton onClick={toggleVideo}>
            {videoEnabled
              ? <VideocamOutlined />
              : <VideocamOffOutlined />
            }
          </IconButton>
          <Button 
            variant="contained" 
            disableElevation
            className="go away"
            onClick={leaveRoom}
          >
            <LogoutOutlined /> Go away Room
          </Button>
          {hlsState.working
            ? <Button 
                variant="contained" 
                disableElevation
                className="go away"
                onClick={stopHLSStreaming}
              >
                <StopCircleOutlined /> Cease Streaming
              </Button>
            : <Button 
                variant="contained"
                disableElevation
                onClick={startHLSStreaming}
              >
                <PodcastsOutlined /> Go Reside 
              </Button>
          }
        </>
      : <Button 
          variant="contained" 
          disableElevation
          className="go away"
          onClick={leaveRoom}
        >
          <LogoutOutlined /> Go away Room
        </Button>
    }
  </div>
)

Add chat performance and show all members

There are three completely different strategies out there to ship chat messages which have completely different use instances.

  • sendBroadcastMessage('message'): For messages that will probably be obtained by everybody within the room
  • sendGroupMessage('message', ['role1']): For messages that will probably be obtained by each peer who’s a part of the passed-in roles
  • sendDirectMessage('message', peer.id): For messages that will probably be obtained solely by the peer whose ID was handed

In our app, we’ll solely use sendBroadcastMessage(), however you may add options for the remaining if you happen to like.

Head over to src/ChatNdParticipants.js and add the next traces of code:

// src/ChatNdParticipants.js
import { selectHMSMessages, useHMSActions, useHMSStore } from "@100mslive/react-sdk"

Subsequent, add the next traces of code after the message state:

// src/ChatNdParticipants.js
const messages = useHMSStore(selectHMSMessages)
const hmsActions = useHMSActions()

const handleSubmit = (e) => {
  e.preventDefault();
  hmsActions.sendBroadcastMessage(message)
  setMessage('')
}

We’ve created a handleSubmit, which can ship the messages. We’re additionally retrieving all of the despatched messages utilizing the selectHMSMessages selector.

When the send-message type is submitted, we have to name handleSubmit and loop via the retrieved messages and show them. To name handleSubmit, modify the open tag <type> of the shape with a reputation of send-message to the code under:

// src/ChatNdParticipants.js
<type identify="send-messge" onSubmit={handleSubmit}>

Subsequent, change the Message element beneath the {/* Messages */} remark with the next:

// src/ChatNdParticipants.js
{messages.map((msg) => (
  <Message key={msg.id} message={msg} />
))}

Subsequent, modify the Message.js file within the src listing to appear like the next code:

// src/ChatNdParticipants.js
import { selectLocalPeer, useHMSStore } from '@100mslive/react-sdk'

perform Message({message}) {
  const localPeer = useHMSStore(selectLocalPeer)

  return (
    <div 
      className={`message ${message.senderUserId === localPeer.customerUserId && 'myMessage'}`}
    >
      <span>{message.senderName}</span>
      <p>{message.message}</p>
    </div>
  )
}

export default Message

Now, the chat performance ought to be working. To show the members, we’ll use the selectPeers selector to get all of the friends within the room, loop over them, and show their identify and position.

Within the ChatNdParticipants.js, add the next import:

// src/ChatNdParticipants.js
import { selectPeers } from "@100mslive/react-sdk"

Subsequent, add the next line of code after the hmsActions variable:

// src/ChatNdParticipants.js
const friends = useHMSStore(selectPeers)

Now, add the next traces of code after the {/* Contributors */} remark:

// src/ChatNdParticipants.js
{friends.map((peer) => (
  <div className="rightBox__participant">
    {peer.identify}
    <p>{peer.roleName}</p>
  </div>
))}

With this, we’re completed constructing our stay streaming app.

Conclusion

On this tutorial, we discovered learn how to construct a stay streaming app utilizing 100ms. Other than the options coated on this tutorial, there are rather a lot others we are able to add, like streaming on YouTube, Twitch, Fb, and so forth utilizing RTMP streaming, displaying notifications for actions taking place within the room, and extra.

I hope you loved this tutorial, and you’ll want to go away a remark when you have any questions. Glad coding!

Full visibility into manufacturing React apps

Debugging React purposes might be troublesome, particularly when customers expertise points which can be laborious to breed. In case you’re eager about monitoring and monitoring Redux state, routinely surfacing JavaScript errors, and monitoring sluggish community requests and element load time, attempt LogRocket.

LogRocket is sort of a DVR for internet and cellular apps, recording actually every thing that occurs in your React app. As an alternative of guessing why issues occur, you may mixture and report on what state your software was in when a problem occurred. LogRocket additionally displays your app’s efficiency, reporting with metrics like shopper CPU load, shopper reminiscence utilization, and extra.

The LogRocket Redux middleware package deal provides an additional layer of visibility into your person classes. LogRocket logs all actions and state out of your Redux shops.

Modernize the way you debug your React apps — .

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments