Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
8af1d58
add v4 beta docs (WIP)
niravcodes Apr 6, 2026
1037b4f
Merge branch 'main' into nko/browser-sdk-docs
niravcodes Apr 15, 2026
179565e
update component code
niravcodes Apr 16, 2026
9f69143
Merge branch 'main' into nko/browser-sdk-docs
niravcodes Apr 23, 2026
8157b36
Merge branch 'main' into nko/browser-sdk-docs
niravcodes Apr 28, 2026
9b63762
try granular files for class-methods
niravcodes Apr 28, 2026
e391d96
updated docs
niravcodes Apr 29, 2026
42fea6a
update web component docs
niravcodes Apr 29, 2026
b199ef5
regroup
niravcodes Apr 29, 2026
56da397
update
niravcodes Apr 29, 2026
e7c5428
Merge branch 'main' into nko/browser-sdk-docs
niravcodes May 5, 2026
867fff8
update sidebar
niravcodes May 5, 2026
3d9248d
regex pass
niravcodes May 5, 2026
4fefe8d
first haiku pass
niravcodes May 6, 2026
0a7c545
cleanup reference and fix code link
niravcodes May 13, 2026
8a9ee28
update primer
niravcodes May 13, 2026
88a49f0
normalize frontmatter
niravcodes May 13, 2026
4a6d4be
heading normalization paramfield normalization
niravcodes May 13, 2026
7722442
update links
niravcodes May 13, 2026
b6e6e04
remove non-essential
niravcodes May 13, 2026
52f3d95
try removing internal things
niravcodes May 13, 2026
0757496
use paramfield
niravcodes May 13, 2026
c5552ba
fix address
niravcodes May 13, 2026
c94e64c
add examples
niravcodes May 13, 2026
0fe8938
Merge branch 'main' into nko/browser-sdk-docs
niravcodes May 13, 2026
035c5b5
fix redir
niravcodes May 13, 2026
49b42fb
remove rote litelement reference
niravcodes May 13, 2026
65fa2df
add guide stubs
niravcodes May 14, 2026
d8099c2
reorder
niravcodes May 14, 2026
129c50b
add click to call tab
niravcodes May 14, 2026
fa1a539
add overview
niravcodes May 14, 2026
b36c64d
add migration guide
niravcodes May 15, 2026
70836ad
Merge branch 'main' into nko/browser-sdk-docs
Devon-White May 15, 2026
a58b90f
change subscriber to user
niravcodes May 17, 2026
a6feac6
scaffold
niravcodes May 18, 2026
7b01b39
link to refernces
niravcodes May 18, 2026
343a750
fix overview
niravcodes May 18, 2026
1875afb
add type linking
niravcodes May 19, 2026
c201801
Merge branch 'main' into nko/browser-sdk-docs
Devon-White May 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ dist
.serena
.claude
.vscode
.docs-review
.env
.env.*
!.env.example
Expand Down
13 changes: 12 additions & 1 deletion fern/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ products:
icon: fa-regular fa-browser
subtitle: Build voice, video and chat applications for the browser
versions:
- display-name: v4
path: products/browser-sdk/versions/v4.yml
availability: beta
slug: v4
- display-name: v3
path: products/browser-sdk/versions/latest.yml
availability: stable
Expand Down Expand Up @@ -170,7 +174,6 @@ css:
- brand-overrides.css
- styles.css


redirects:
- source: /docs/agents-sdk
destination: /docs/server-sdks
Expand All @@ -180,6 +183,14 @@ redirects:
destination: /docs/server-sdks
- source: /docs/server-sdk/:slug*
destination: /docs/server-sdks
- source: /docs/browser-sdk/js
destination: /docs/browser-sdk/v3/js
- source: /docs/browser-sdk/js/:slug*
destination: /docs/browser-sdk/v3/js/:slug*
- source: /docs/browser-sdk/click-to-call
destination: /docs/browser-sdk/v3/click-to-call
- source: /docs/browser-sdk/click-to-call/:slug*
destination: /docs/browser-sdk/v3/click-to-call/:slug*

# SWML methods reorganized into calling/ and messaging/ subsections.
# The old methods overview lived at /docs/swml/reference, which was
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
---
title: "Live Streaming"
slug: /guides/live-streaming
sidebar-title: "Live Streaming"
position: 7
max-toc-depth: 3
---

Live streaming on the SignalWire platform pushes a room's mixed feed
to one or more RTMP destinations (YouTube Live, Twitch, a custom
ingest server). It's a server-side feature — like
[recording](/docs/browser-sdk/v4/guides/recording), the SDK's role is to observe
streaming state on the active call.

<Warning>
**Client-side `startStreaming()` is not yet implemented in v4.** The
SDK ships an `async startStreaming()` stub on `Call` that throws
`UnimplementedError`. Trigger streams server-side (REST or SWML); use
`streaming$` to reflect status in your UI.
</Warning>

## What you can do today

- **Observe** whether streaming is active: `call.streaming$`.
- **Render a "LIVE" indicator** driven by that observable.
- **Start / stop streams** via:
- The REST API.
- A SWML script on the Resource.
- The SignalWire Dashboard.

## Observing streaming state

`streaming$` is a boolean BehaviorSubject — `true` whenever any
stream is active on the call's session, `false` otherwise.

```js
call.streaming$.subscribe((isStreaming) => {
liveBadge.classList.toggle("visible", isStreaming);
liveBadge.textContent = isStreaming ? "● LIVE" : "";
});
```

The badge updates instantly when streaming starts or stops, regardless
of which client started it.

## Starting a stream: server-side

### From the REST API

Issue a request against the call's session ID with the RTMP target:

```bash
curl -X POST "https://yourspace.signalwire.com/api/video/room_sessions/{id}/streams" \
-u "PROJECT_ID:API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "rtmps://a.rtmps.youtube.com/live2/STREAM_KEY"
}'
```

The full set of stream endpoints (create, list, stop, etc.) is in
the [REST API reference](/docs/apis).

### From SWML

A `stream` verb in the room's SWML automatically starts a stream when
the session begins:

```yaml
sections:
main:
- stream:
url: rtmps://a.rtmps.youtube.com/live2/STREAM_KEY
```

### From the Dashboard

For ad-hoc stream targets, configure the Resource's streaming
settings and toggle on join.

## Multiple destinations

The session can run multiple streams concurrently — useful for
simulcasting to YouTube and Twitch at the same time. Each is created
through a separate REST call (or a separate `stream` verb in SWML).
The `streaming$` observable reports a single boolean: `true` if any
of them are active.

If you need to enumerate the individual stream targets, read them
from `call.signalingEvent$` payloads (the room session state
includes the current `streams` list):

```js
call.signalingEvent$.subscribe((event) => {
if (event.event_type === "call.updated") {
console.log("streams:", event.params?.room_session?.streams);
}
});
```

## Capability flag

`call.self.capabilities` does not include a streaming-specific flag
in v4 — streaming is a session-level operation governed by
server-side policy. Anyone in the room sees `streaming$` flip, but
only authorized callers (typically your backend) can start or stop
streams via the REST API.

## Roadmap

[`Call.startStreaming()`] and `Call.stopStreaming()` are planned.
Until they land, the SDK contract is:

- **Read**: `streaming$` / `streaming` (works today).
- **Write**: server-side only (works today, via REST / SWML /
Dashboard).

For per-call recording, see [Recording](/docs/browser-sdk/v4/guides/recording). The
two features behave similarly today — observe-only on the SDK,
write-only on the platform.

## Viewer-side: interactive live streams

If your app is *consuming* a stream (rather than producing one), the
playback flow is plain HTTP — point an HLS player at the URL the
platform publishes, no SDK involved. The Browser SDK is only relevant
when the viewer needs to *participate* in the room (chat, raise hand,
join as a video participant). For that flow, treat them as a normal
inbound or outbound call against the Resource Address; the platform
mixes their media into the same session that's being streamed.

## Reference

- [`Call.streaming$`] — reactive streaming state
- [`Call.startStreaming()`] — server-side mutator (not yet implemented in v4)

[`Call.streaming$`]: /docs/browser-sdk/v4/reference/webrtc-call/streaming$
[`Call.startStreaming()`]: /docs/browser-sdk/v4/reference/webrtc-call/start-streaming
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
---
title: "Recording"
slug: /guides/recording
sidebar-title: "Recording"
position: 6
max-toc-depth: 3
---

Recording on the SignalWire platform is a server-side capability —
the media mix is recorded in the cloud, not in the browser. The
Browser SDK's role today is to **observe** recording state on the
active call. It surfaces a `recording$` boolean observable; the
recording itself is started, stopped, and downloaded through the
platform (Dashboard, REST API, or SWML).

<Warning>
**Client-side `startRecording()` is not yet implemented in v4.** The
SDK ships an `async startRecording()` stub on `Call` that throws
`UnimplementedError`. Until it lands, trigger recording through one
of the server-side paths below and use the observables to reflect
status in your UI.
</Warning>

## What you can do today

- **Observe** whether a recording is active: `call.recording$`.
- **Render a "REC" badge** in your UI driven by that observable.
- **Trigger recording** server-side via:
- Configuring the Resource (room, SWML script) to auto-record on
join.
- The SignalWire REST API.
- A SWML script that runs on the call leg.

## Observing recording state

`recording$` emits a boolean — `true` whenever any recording is
active on the call's session, `false` otherwise. It's a
BehaviorSubject, so late subscribers get the current state
synchronously.

```js
call.recording$.subscribe((isRecording) => {
recordingBadge.classList.toggle("visible", isRecording);
recordingBadge.textContent = isRecording ? "● REC" : "";
});
```

That's all most apps need — a visible indicator so participants know
the session is being recorded.

## Pulling more detail

The full recording state (file IDs, current duration, format, paused
status, etc.) is sent by the server inside `call.joined` and
`call.updated` events. The SDK exposes the resulting state via
`call.signalingEvent$` if you need to inspect the raw payload:

```js
call.signalingEvent$.subscribe((event) => {
if (event.event_type === "call.updated") {
// event.params.room_session.recordings has the list
console.log("recordings:", event.params?.room_session?.recordings);
}
});
```

This is escape-hatch territory — most apps shouldn't need it. When
the `start/stop/pause` mutator methods land on the SDK, you'll get a
cleaner API for the same data.

## Starting a recording: server-side options

### From a SWML script on the Resource

Use the `record` verb in the room's SWML to begin recording as soon
as the call connects:

```yaml
sections:
main:
- record:
stereo: true
format: mp4
```

### From the REST API

Issue a request against the call's session ID. The platform
identifies the active room session and starts recording.

```bash
curl -X POST "https://yourspace.signalwire.com/api/video/room_sessions/{id}/recordings" \
-u "PROJECT_ID:API_TOKEN" \
-H "Content-Type: application/json"
```

Refer to the [REST API reference](/docs/apis) for the full set of
recording endpoints (start, stop, list, download).

### From the Dashboard

For ad-hoc recording on a specific Resource, toggle "Record on join"
in the Resource configuration. Useful for support / sales workflows
where every call should be archived.

## Capability flag

`call.self.capabilities` does **not** currently include a `record`
flag — recording isn't a per-participant capability in v4. Anyone in
a room may know about a recording in progress (via the `recording$`
observable), but starting / stopping is governed entirely by
server-side policy.

## What about stopping?

When recording is started server-side, the same channel stops it. The
SDK will see `recording$` flip to `false` and your "REC" badge will
clear. Don't try to call `call.startRecording()` / no equivalent
client-side stop is reachable today.

## Roadmap

[`Call.startRecording()`] / `Call.stopRecording()` / pause/resume are
planned. Until they ship, the contract is:

- **Read**: `recording$` / `recording` (works today).
- **Write**: server-side only (works today, via REST / SWML /
Dashboard).

When the SDK methods become available, this guide will grow examples
for starting and stopping inline. Watch the [changelog](/docs/browser-sdk/v4/changelog)
or the JS reference for the introduction of the methods.

For livestreaming an active call (which behaves similarly), see
[Live Streaming](/docs/browser-sdk/v4/guides/live-streaming).

## Reference

- [`Call.recording$`] — reactive recording state
- [`Call.startRecording()`] — server-side mutator (not yet implemented in v4)

[`Call.recording$`]: /docs/browser-sdk/v4/reference/webrtc-call/recording$
[`Call.startRecording()`]: /docs/browser-sdk/v4/reference/webrtc-call/start-recording
Loading
Loading