VideoSource, LocalVideoTrack, VideoFrame, VideoStream.
Video in TypeScript needs the optional node-webcodecs package, prebuilt for macOS arm64 and Linux x64 and arm64:
calls extra.
Send video
Create a source at your frame size, publish it as a track, and capture a frame every time you have one. The frames you capture set the frame rate: capture 30 a second for 30 fps. Your agent’s video is its own track: the person’s phone shows it whenever your agent publishes one, whether or not their camera is on. Any frame source works: looping video files, a live avatar, frames from a video API, or your own renderer. With its video off, your agent’s picture sits in the centre of the call screen. When your agent sends video, the video fills the screen:- Preview
- JSON
- TypeScript
- Python
- Pipecat
- LiveKit
Set the frame rate and bitrate
Send up to 1920x1080 at 30 fps. Without settings of your own, each frame size gets LiveKit’s camera preset:
To choose your own, pass an encoding when you publish:
maxFramerate guides the encoder; the rate at which you capture frames is what the person sees. Video goes out as H.264 constrained baseline, with VP8 offered second in TypeScript. In Python, aiortc keeps the bitrate between 500 kbps and 3 Mbps.
Read the person’s camera
The person’s camera arrives as a remote track. Open aVideoStream on it to decode frames; frames are decoded only while a stream is open.
- TypeScript
- Python
- Pipecat
- LiveKit
Read video statistics
videoStats() (video_stats() in Python) counts frames captured, sent, decoded and dropped in both directions. Log it when a call ends to see whether video flowed.

