Overview
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.
-
First, you need to get all the peers in the room. You can use the
selectPeers
selector for this. -
Next, you'll need to have a reference to a video element. You must add the attributes as present below.
<video autoplay muted playsinline />
- 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
We need to re-attach video when it's in view after every:
- Unmute(when track.enable is true)
- Plugin is added/removed(for example, enable/disable virtual background)
- 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);