It all comes down to this. All the setup so far has been done so that we can show live streaming video in our beautiful apps.

  1. First, you need to get all the peers in the room. You can use the selectPeers selector for this.

  2. Next, you'll need to have a reference to a video element. You must add the attributes as present below.

<video autoplay muted playsinline />
  1. You can then iterate over all the peers, and call the attachVideo function in hmsActions to render the video.
hmsActions.attachVideo(videoTrack.id, videoElement);

The videos will now be rendered & start playing on your screen. 🥳

In case you want to render local peer and remote peers separately, you can use the selectors - selectLocalPeer and selectRemotePeers.

Detach video to conserve bandwidth and cleanup elements

You can call detachVideo on the hmsActions to unsubscribe a track and not fetch it's data. This can be done for example when a video goes out of view. This should also be called when the component is going to be unmounted for proper cleanups of the video elements.

hmsActions.detachVideo(videoTrack.id, videoElement);

When to attach/detach videos

Starting from this release, sdk handles the subsequent attach/detach automatically.

  • attach needs to be called only the first time the video element is available. subsequent calls will be ignored.
  • detach needs to be called only when the element is removed from the dom while the track is still available. For the majority of cases, calling detach won't be needed.

To disable the auto handling by sdk, pass autoManageVideo: false in join or preview config object. Then you will have to follow the below snippet to handle video rendering on your end.

We need to re-attach video when it's in view after every:

  1. Unmute(when track.enable is true)
  2. Plugin is added/removed(for example, enable/disable virtual background)
  3. Camera/device change(track.deviceId is changed)

You can achieve all this by using the selectVideoTrackByID selector and the aforementioned hmsActions.attachVideo and hmsActions.detachVideo functions.

// assuming you have peer object and video element // complete code snippet below hmsStore.subscribe((track) => { if (!track) { return; } if (track?.enabled) { hmsActions.attachVideo(track.id, videoElement); } else { hmsActions.detachVideo(track.id, videoElement); } }, selectVideoTrackByID(peer.videoTrack));

Note that if you're using the useVideo hook from react-sdk this is already being taken care of.

Example Snippet

import { hmsActions } from './hms'; const peersContainer = document.getElementById('peers-container'); // store peer IDs already rendered to avoid re-render on mute/unmute const renderedPeerIDs = new Set(); // render a single peer video tile function renderPeer(peer) { const peerTileDiv = document.createElement('div'); // you can either get an existing video element or create a new one. const videoElement = document.createElement('video'); const peerTileName = document.createElement('div'); videoElement.autoplay = true; videoElement.muted = true; videoElement.playsinline = true; peerTileName.textContent = peer.name; hmsStore.subscribe((track) => { if (!track) { return; } if (track.enabled) { hmsActions.attachVideo(track.id, videoElement); } else { hmsActions.detachVideo(track.id, videoElement); } }, selectVideoTrackByID(peer.videoTrack)); peerTileDiv.append(videoElement); peerTileDiv.append(peerTileName); renderedPeerIDs.add(peer.id); return peerTileDiv; } // display a tile for each peer in the peer list function renderPeers(peers) { peersContainer = document.getElementById('peers-container'); peers.forEach((peer) => { if (!renderedPeerIDs.has(peer.id) && peer.videoTrack) { console.log( `rendering video for peer - ${peer.name}, roleName - ${peer.roleName}, isLocal- ${peer.isLocal}` ); peersContainer.append(renderVideo(peer)); } }); } // subscribe to the peers, so render is called whenever there is a change like peer join and leave hmsStore.subscribe(renderPeers, selectPeers);

Mirror video

To mirror local peer's video, apply the following CSS style to the video element.

/** enable mirror with -1 */ transform: scaleX(-1);

The 100ms sample app already does this by default. To turn it off, you can override this styling in code or disable the "Mirror Local Tile" from layout settings.

Have a suggestion? Recommend changes ->

Was this helpful?