LocalVideoStream interface
extends VideoStream LOCAL
Your camera stream. Adds device control, settings updates, and one-shot frame capture on top of VideoStream. Access via room.localParticipant.video after publishVideo(). Frame processors are managed globally via VideoSDK.applyVideoProcessor() โ not on the stream.
Blueprint
Members added on top of VideoStream.
Properties (added)
Plus all properties inherited from VideoStream: id, codec, dimensions, frameRate, contentHint, isPlaying, isPaused, isEnded.
inputDevice
Currently selected camera as a CameraDeviceInfo (combines deviceId, groupId, label). Use me.video.inputDevice.label for "Camera: X" UI; me.video.inputDevice.deviceId for storage / comparison.
Methods (added)
Plus all methods inherited from VideoStream: attach / detach, createElement, getStats, getMediaStreamTrack.
setInputDevice async
Hot-swap to a different camera. The stream instance is preserved โ SDK swaps the underlying track and rebinds all attached <video> elements transparently. Strongly typed โ passing a MicrophoneDeviceInfo or SpeakerDeviceInfo is a compile-time error.
Resolves when the new device is acquired and publishing on the new track. Rejects on permission denied, device busy, or if the device is no longer present.
const cameras = await VideoSDK.getCameras();
const back = cameras.find(c => c.label.toLowerCase().includes('back'));
if (back) await me.video.setInputDevice(back);
// Attached <video> elements continue rendering โ no re-attach needed
updateSettings async
Change resolution and/or frame rate mid-stream without re-publishing. Internally calls applyConstraints() on the underlying track.
await me.video.updateSettings({ resolution: 'h1080', frameRate: 60 });
setContentHint
Encoder optimization hint. "motion" for high-motion content (gameplay, sports). "detail" for sharpness-critical static content (slide presentations, document cameras).
VideoSDK.applyVideoProcessor() to apply a frame transform. It survives publish, unpublish, re-publish, and setInputDevice swaps. No per-stream setProcessor method.getInputCapabilities async
Reports what the current device can do โ max resolution, frame rates, facingModes, etc. Wraps the browser's MediaStreamTrack.getCapabilities().
const caps = await me.video.getInputCapabilities();
console.log(`Max ${caps.width.max}ร${caps.height.max} @ ${caps.frameRate.max}fps`);
console.log('Facing modes:', caps.facingMode);
stop async PRE-CALL
Aborts a pre-call preview stream. Releases the underlying camera (MediaStreamTrack stopped) and clears the VideoSDK.videoStream singleton slot so the next createVideoStream succeeds. After stop(), all methods on this instance throw STREAM_STOPPED.
me.video, use me.unpublishVideo() instead โ it does full teardown (unpublish + release device).const preview = await VideoSDK.createVideoStream({ device: cameras[0] });
preview.attach(previewEl);
// User clicks "Cancel" instead of "Join"
await preview.stop();
// camera released, VideoSDK.videoStream is null again
Related open questions: Q18 โ Pre-call preview lifecycle (singleton vs render-only)
captureFrame async LOCAL ONLY
One-shot snapshot of the current frame as a Base64-encoded data URL. Useful for thumbnails, profile-photo capture, AI vision input, or sending a snapshot to a server.
Not available on remote streams โ to snapshot a remote video, use canvas.drawImage() on the user-attached <video> element.
opts.qualityโ0..1for JPEG only, default0.9. Ignored for PNG.opts.width/opts.heightโ optional override; defaults to the source frame size.
Resolves with a data URL string: "data:image/png;base64,..." โ assignable directly to img.src, postable to a server, or savable to disk.
const dataUrl = await me.video.captureFrame({ quality: 0.85 });
// Show as preview
document.querySelector('#preview').src = dataUrl;
// Upload
await fetch('/snapshot', { method: 'POST', body: JSON.stringify({ image: dataUrl }) });
// Download as file
const a = document.createElement('a');
a.href = dataUrl;
a.download = 'snapshot.jpg';
a.click();
Events
There are no publish/unpublish events on LocalParticipant โ the publishVideo Promise delivers the stream directly.
| Event | Payload | When |
|---|---|---|
ended | { timestamp: number } | Camera source ended โ device unplugged, OS revoked permission, browser tab lost device access. |
frozen / stuck) and routing transitions (paused / ended) live on the merged streamState + state-changed event of RemoteVideoStream. Local streams have no routing state โ they describe the local capture pipeline, not a receive-side decoder.See also: VideoStream LocalParticipant VideoFrameProcessor RemoteVideoStream