← All @molecule/* packages · App templates
@molecule/api-video-roomsCore interface · video-rooms · API (Node) · v1.0.1 · Apache-2.0
Real-time video rooms core interface — room lifecycle, signed meeting tokens, and cloud recordings — with swappable provider bonds (Daily.co default; LiveKit, Twilio Video, Agora alternates). Used by virtual-classroom, telemedicine, video-conferencing, and screen-sharing apps.
npm install @molecule/api-video-rooms@molecule/api-video-rooms is the video-rooms core interface on the API (Node) side: the API your app calls, with no vendor inside.
Choose the implementation by bonding one of its 2 providers: @molecule/api-video-rooms-daily-co, @molecule/api-video-rooms-livekit.
import {
setProvider,
createRoom,
createMeetingToken,
listRecordings,
} from '@molecule/api-video-rooms'
import { createProvider } from '@molecule/api-video-rooms-daily-co'
// Bond a provider at startup (reads DAILY_CO_API_KEY when config is omitted)
setProvider(createProvider())
// Create a room
const room = await createRoom({
name: 'class-101',
privacy: 'private',
maxParticipants: 30,
recording: true,
})
// Issue a join token for a student
const token = await createMeetingToken(room.name, {
userName: 'Ada',
expiresAt: new Date(Date.now() + 60 * 60_000),
})
// After the meeting, list recordings
const recordings = await listRecordings(room.name)Providers (2): @molecule/api-video-rooms-daily-co, @molecule/api-video-rooms-livekit
Works with: @molecule/api-bond, @molecule/api-i18n
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Video rooms core interface for molecule.dev.
Defines the standard interface for real-time video room providers (Daily.co, LiveKit, Twilio Video, Agora, etc.). Used by apps such as virtual classrooms, telemedicine, video conferencing, and screen sharing.
import {
setProvider,
createRoom,
createMeetingToken,
listRecordings,
} from '@molecule/api-video-rooms'
import { createProvider } from '@molecule/api-video-rooms-daily-co'
// Bond a provider at startup (reads DAILY_CO_API_KEY when config is omitted)
setProvider(createProvider())
// Create a room
const room = await createRoom({
name: 'class-101',
privacy: 'private',
maxParticipants: 30,
recording: true,
})
// Issue a join token for a student
const token = await createMeetingToken(room.name, {
userName: 'Ada',
expiresAt: new Date(Date.now() + 60 * 60_000),
})
// After the meeting, list recordings
const recordings = await listRecordings(room.name)
core
npm install @molecule/api-video-rooms @molecule/api-bond @molecule/api-i18n
CreateMeetingTokenOptionsOptions for issuing a meeting token (signed join credential).
interface CreateMeetingTokenOptions {
/** Whether the token grants owner / moderator privileges. */
isOwner?: boolean
/** Display name to use for the participant when joining the room. */
userName?: string
/** Token expiry. After this point the token cannot be used to join. */
expiresAt?: Date
}
CreateRoomOptionsOptions for creating a new video room.
interface CreateRoomOptions {
/** Room name. If omitted, the provider may auto-generate a unique name. */
name?: string
/** When the room should expire and stop accepting joins. */
expiresAt?: Date
/** Maximum simultaneous participants (provider-dependent cap may apply). */
maxParticipants?: number
/** Whether cloud recording should be enabled for this room. */
recording?: boolean
/** Visibility/privacy of the room. Defaults to `public` when omitted. */
privacy?: RoomPrivacy
}
RecordingA normalised description of a cloud recording produced by a room.
interface Recording {
/** Provider-stable recording identifier. */
id: string
/** Name of the room the recording belongs to. */
roomName: string
/** When the recording started. */
startedAt?: Date
/** Recording duration in seconds, when known. */
duration?: number
/** Provider's reported processing/availability status. */
status?: 'processing' | 'ready' | 'failed' | 'deleted'
/** Time-limited download URL for the recording, when available. */
downloadUrl?: string
}
RoomA normalised description of an existing room as returned by a provider.
interface Room {
/** Provider-stable room name / identifier. */
name: string
/** Joinable URL for the room. */
url: string
/** When the room expires, if a TTL is configured. */
expiresAt?: Date
/** Maximum simultaneous participants, if configured. */
maxParticipants?: number
/** Whether cloud recording is enabled on this room. */
recording?: boolean
/** Visibility/privacy of the room. */
privacy?: RoomPrivacy
}
RoomCreatedResult of creating a new video room.
Extends {@link Room} with an optional pre-issued owner meeting token so callers can hand a single payload to clients without a follow-up call.
interface RoomCreated extends Room {
/** Optional meeting token for the room creator (owner privileges). */
token?: string
}
VideoRoomsProviderVideo rooms provider interface.
All video-rooms providers must implement this interface to provide a normalised surface for room lifecycle, signed join tokens and cloud recordings.
interface VideoRoomsProvider {
/**
* Creates a new video room.
*
* @param options - Room creation options.
* @returns The created room, including its joinable URL.
*/
createRoom(options: CreateRoomOptions): Promise<RoomCreated>
/**
* Deletes an existing room by name. Idempotent: deleting a non-existent
* room must not throw.
*
* @param name - The room name / identifier.
*/
deleteRoom(name: string): Promise<void>
/**
* Retrieves an existing room by name.
*
* @param name - The room name / identifier.
* @returns The room if it exists, otherwise `null`.
*/
getRoom(name: string): Promise<Room | null>
/**
* Issues a signed meeting token (join credential) for a room.
*
* @param roomName - The room the token is scoped to.
* @param options - Token options (owner flag, display name, expiry).
* @returns The signed token string.
*/
createMeetingToken(roomName: string, options?: CreateMeetingTokenOptions): Promise<string>
/**
* Lists cloud recordings produced by a room.
*
* @param roomName - The room to list recordings for.
* @returns The list of recordings, possibly empty.
*/
listRecordings(roomName: string): Promise<Recording[]>
}
RoomPrivacyPrivacy level for a video room.
public — anyone with the room URL can join.private — joiners must present a meeting token issued by
{@link VideoRoomsProvider.createMeetingToken}.type RoomPrivacy = 'public' | 'private'
createMeetingToken(roomName, options)Issues a signed meeting token (join credential) for a room using the bonded provider.
function createMeetingToken(roomName: string, options?: CreateMeetingTokenOptions): Promise<string>
roomName — The room the token is scoped to.options — Token options (owner flag, display name, expiry).Returns: The signed token string.
createRoom(options)Creates a new video room using the bonded provider.
function createRoom(options?: CreateRoomOptions): Promise<RoomCreated>
options — Room creation options.Returns: The created room, including its joinable URL.
deleteRoom(name)Deletes an existing room by name using the bonded provider.
function deleteRoom(name: string): Promise<void>
name — The room name / identifier.getProvider()Retrieves the bonded video rooms provider, throwing if none is configured.
function getProvider(): VideoRoomsProvider
Returns: The bonded video rooms provider.
getRoom(name)Retrieves an existing room by name using the bonded provider.
function getRoom(name: string): Promise<Room | null>
name — The room name / identifier.Returns: The room if it exists, otherwise null.
hasProvider()Checks whether a video rooms provider is currently bonded.
function hasProvider(): boolean
Returns: true if a video rooms provider is bonded.
listRecordings(roomName)Lists cloud recordings produced by a room using the bonded provider.
function listRecordings(roomName: string): Promise<Recording[]>
roomName — The room to list recordings for.Returns: The list of recordings, possibly empty.
setProvider(provider)Registers a video rooms provider as the active singleton. Called by bond packages during application startup.
function setProvider(provider: VideoRoomsProvider): void
provider — The video rooms provider implementation to bond.| Provider | Package |
|---|---|
| Video Rooms | @molecule/api-video-rooms-daily-co |
| Video Rooms | @molecule/api-video-rooms-livekit |
Peer dependencies:
@molecule/api-bond ^1.0.1@molecule/api-i18n ^1.0.1@molecule/api-bond
@molecule/api-i18n
Rooms are PUBLIC by default. privacy defaults to 'public' when omitted — anyone
with the room URL can join. For anything user-scoped, create the room with
privacy: 'private' and mint short-lived per-user join tokens via
createMeetingToken(roomName, { userName, expiresAt }).
Server-side only. The provider API key (for the bundled Daily.co bond:
DAILY_CO_API_KEY) stays in the API's env. The browser receives ONLY the join token /
room URL your endpoint returns — never the key, and never direct provider API calls.
Recording.downloadUrl is time-limited — download/persist promptly (e.g. via the
uploads package); a stored URL will dead-link later.
Ad-hoc rooms ≠ scheduled meetings: for calendar-style events with a start time and a
stable invite link use @molecule/api-video-meetings instead.
Integration checklist — drive the real UI (live preview, no mocks), adapt each item to this app's actual screens/flows, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip. CAVEAT: the live A/V call and the in-room video UI run inside the provider's client and CANNOT be driven in the sandbox — verify the room LIFECYCLE and the per-participant join TOKENS you mint server-side, never the media itself:
createRoom(...) yields a
RoomCreated with a stable name and a joinable url, and the app persists
that name on its own record — not a throwaway URL it can never resolve again.createMeetingToken(room.name, { userName, expiresAt, isOwner }) per user, so
two joiners receive two DISTINCT, short-lived credentials — never one static
shared secret reused for everyone.isOwner: true) differs from a plain-participant token, each is scoped to the
single room.name it was minted for (it admits no other room), and it carries
the requested expiresAt — inspect the minted token's claims; don't assume it,
and don't hand an owner token to an ordinary participant.getRoom(name) reflects real state: a created room resolves with its
configured privacy/maxParticipants/recording, and after deleteRoom(name)
it returns null — ending a room actually removes it, so its old URL/tokens no
longer admit a join. (Live participant count is NOT in the core Room type —
don't assert on it.)maxParticipants, the created room
carries that cap (the provider enforces it at join) — it isn't silently dropped.DAILY_CO_API_KEY) stays server-side;
the browser only ever receives a token/URL your endpoint returned, never the key
or a direct provider call. Private rooms are un-guessable: only an authorized
user's request mints a token, and no unauthenticated caller joins a private
room by guessing its name/URL without one.