Supported Providers
Check a camera’scan_stream_live_video capability flag before you offer live video for it. The flag is true only for cameras whose provider supports live video and that are currently online. Ring cameras and doorbells report false.
How It Works
All three/cameras/live_views endpoints accept only a client session token. Your API key never reaches the browser.
Before You Begin
To stream live video, you need:- A workspace with live video turned on.
- A connected account with a Tapo or Arlo camera whose
can_stream_live_videoistrue. - A backend that can create client sessions with your API key.
- A browser that supports WebRTC (
RTCPeerConnection).
Step 1: Create a Client Session
On your backend, create a client session that has access to the camera’s connected account, and send its token to the browser. The live view can’t outlast the client session, so give the session a short lifetime.Live video only works with client sessions created from
connected_account_ids, connect_webview_ids, user_identifier_key, or user_identity_id. Client sessions created with customer_key can’t open a live view.can_stream_live_video is true:
false while the camera is offline, so check it again right before you open a live view.
Step 2: Create a Live View Session
In the browser, call/cameras/live_views/create with the client session token in the seam-client-session-token header. A live view session reserves the camera for this viewer.
Request:
- The session ends at
expires_at:duration_secondsafter creation, or when the client session expires, whichever is sooner. - The response’s
tokenauthorizes the offer and stop calls for this session only. Keep it in memory, and don’t log it. - Seam sends
Cache-Control: no-storeon all live view responses. - See the camera live view objects for the complete
camera_live_view_sessionandcamera_live_view_answerreference.
Step 3: Send a WebRTC Offer
Create anRTCPeerConnection, add a receive-only video transceiver, and create an offer. Send the offer’s SDP to /cameras/live_views/offer, along with the session ID and token.
JavaScript
camera_live_view_answer.sdp_answer is Seam’s WebRTC SDP answer, at most 64 KiB.
Seam connects to the camera while handling this request, so the response can take several seconds.
- One offer per session. Once you send an offer, you can’t send another one on the same session. To reconnect, create a new live view session.
- Send the offer promptly. If the stream hasn’t started within 30 seconds of creating the session, Seam closes the session.
- Match audio to
include_audio. Ifinclude_audioisfalse, the offer must not contain an audio section, so add only a video transceiver. If it’strue, also callpeerConnection.addTransceiver('audio', { direction: 'recvonly' }). - No ICE trickling. Seam ignores the ICE candidates in your offer and puts its own candidates in the answer. You don’t need to wait for ICE gathering, and there’s no endpoint for sending more candidates.
- Size limit.
sdp_offercan be at most 64 KiB.
Step 4: Play the Stream
Apply the answer, then attach the incoming track to a<video> element.
JavaScript
ontrack before calling setRemoteDescription. Add autoplay, muted, and playsinline to the <video> element so that browsers start playback without a click. Unmute after a user gesture if you requested audio.
Step 5: Stop the Stream
When the user closes the viewer, close the peer connection and call/cameras/live_views/stop. This frees the camera for the next viewer right away. Otherwise, Seam frees it when it notices the connection has closed or when the session expires.
JavaScript
keepalive: true lets the request finish when it’s sent from a pagehide handler. Stopping a session that has already ended succeeds and returns {}.
Limits and Session Lifetime
Seam keeps checking that the viewer still has access while the stream is open. A live view ends when any of the following happens:
- The session reaches
expires_at. - You call
/cameras/live_views/stop. - The browser closes the peer connection.
- The client session expires or is revoked, or it loses access to the camera.
- The camera is removed from Seam, or its connected account is deleted.
expires_at, create a new live view session and connect a new peer connection before the old one ends. Watch peerConnection.connectionState for failed or closed to detect the end of a stream.
Errors
For
409 and 503, wait a few seconds and create a new live view session. Retry with backoff, and stop after a few attempts.
Complete Example
This example serves a web page that plays one camera’s live feed. It uses Node.js 18 or later and theseam package.
- Run
npm install seam. - Set
SEAM_API_KEY,SEAM_CONNECTED_ACCOUNT_ID, andSEAM_DEVICE_IDto your API key, the camera’s connected account, and the camera’s device ID. - Save both files in the same directory and run
node server.mjs. - Open
http://localhost:3000and click Start.
server.mjs
server.mjs
JavaScript
index.html
index.html
HTML
Next Steps
- Camera Live Views reference: Full request and response reference for
/cameras/live_views/create,/cameras/live_views/offer, and/cameras/live_views/stop. - Retrieve event media: Get the clip and thumbnail for motion and doorbell events.
- Client session tokens: Scope client sessions to each user’s devices.
- Seam Bridge: Set up the Bridge that Tapo cameras need.