Build an Angular Room Lifecycle
Build an Angular room with mediasfu-angular 2.3.1: request a room through
your backend, join an approved session, show participants, prepare and publish
media, receive participant media, share a screen, and let a participant leave.
Before you start
- Install
mediasfu-angular@2.3.1in an Angular application. - Put room creation and joining behind authenticated application endpoints.
- Test camera, microphone, and screen capture in a secure browser context.
- Start with a prebuilt room surface while you prove the room policy and media lifecycle for your users.
1. Keep room authority on your backend
Send room intent to your application backend. The backend authenticates the application user, applies host and participant policy, and owns any long-lived MediaSFU account credentials. Return only the handoff your Angular app needs.
import type {
CreateJoinRoomError,
CreateJoinRoomResponse,
CreateMediaSFURoomOptions,
CreateRoomOnMediaSFUType,
JoinMediaSFURoomOptions,
JoinRoomOnMediaSFUType,
} from 'mediasfu-angular';
type RoomResult = {
data: CreateJoinRoomResponse | CreateJoinRoomError | null;
success: boolean;
};
async function postRoomIntent(url: string, payload: unknown): Promise<RoomResult> {
const response = await fetch(url, {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
if (!response.ok) throw new Error(`Room request failed: ${response.status}`);
return response.json() as Promise<RoomResult>;
}
export const createMediaSFURoom: CreateRoomOnMediaSFUType = ({ payload }) =>
postRoomIntent('/api/mediasfu/create-room', payload);
export const joinMediaSFURoom: JoinRoomOnMediaSFUType = ({ payload }) =>
postRoomIntent('/api/mediasfu/join-room', payload);
Do not add an account key to an Angular component, a template, browser storage, or an API request from the browser. Treat 401 and 403 as policy failures and 429 as a backoff signal.
Use the current prebuilt entry carefully
The prebuilt Angular entry accepts createMediaSFURoom and
joinMediaSFURoom callbacks, and its cloud pre-join flow validates the
credentials input before invoking them. Use syntactically valid client
placeholders and inject both callbacks. Each callback must ignore its
credential arguments and send only the room payload to your authenticated
backend. The backend authenticates the app user and substitutes the real
MediaSFU credentials.
The placeholders are not a browser-held account key and grant no authority. Do not fabricate the operation contracts or insert real account credentials in client code. Verify create and join separately so neither path falls back to the default request.
readonly clientPlaceholderCredentials = {
apiUserName: 'client00',
apiKey: '0'.repeat(64),
};
readonly createMediaSFURoom = createMediaSFURoom;
readonly joinMediaSFURoom = joinMediaSFURoom;
<app-mediasfu-generic
[credentials]="clientPlaceholderCredentials"
[createMediaSFURoom]="createMediaSFURoom"
[joinMediaSFURoom]="joinMediaSFURoom"
[connectMediaSFU]="true"
[returnUI]="true"
/>
2. Wire the supported room operations
These are the Angular 2.3.1 public symbols for the first room lifecycle.
import {
AllMembers,
ClickAudio,
ClickScreenShare,
ClickVideo,
CreateDeviceClient,
JoinRoomClient,
LaunchConfirmExit,
ProcessConsumerTransports,
type ClickAudioOptions,
type ClickScreenShareOptions,
type ClickVideoOptions,
type CreateDeviceClientOptions,
type JoinRoomClientOptions,
type ProcessConsumerTransportsOptions,
} from 'mediasfu-angular';
export class RoomActions {
constructor(
private readonly joinClient: JoinRoomClient,
private readonly device: CreateDeviceClient,
private readonly members: AllMembers,
private readonly audio: ClickAudio,
private readonly video: ClickVideo,
private readonly consumers: ProcessConsumerTransports,
private readonly screen: ClickScreenShare,
private readonly exit: LaunchConfirmExit,
) {}
join(options: JoinRoomClientOptions) {
return this.joinClient.joinRoomClient(options);
}
prepareMedia(options: CreateDeviceClientOptions) {
return this.device.createDeviceClient(options);
}
refreshParticipants(options: Parameters<AllMembers['allMembers']>[0]) {
return this.members.allMembers(options);
}
toggleMicrophone(options: ClickAudioOptions) {
return this.audio.clickAudio(options);
}
toggleCamera(options: ClickVideoOptions) {
return this.video.clickVideo(options);
}
receiveMedia(options: ProcessConsumerTransportsOptions) {
return this.consumers.processConsumerTransports(options);
}
toggleScreenShare(options: ClickScreenShareOptions) {
return this.screen.clickScreenShare(options);
}
confirmLeave(visible: boolean, updateVisible: (next: boolean) => void) {
this.exit.launchConfirmExit({
isConfirmExitModalVisible: visible,
updateIsConfirmExitModalVisible: updateVisible,
});
}
}
Keep the service options together as one session-owned state object. The services coordinate transports, permissions, stream state, and UI callbacks; calling one with a partial object can leave media and UI out of sync.
Know what success looks like
| Operation | Observable success | Recovery and cleanup |
|---|---|---|
| Secure create | Your backend accepts a host request and returns an approved handoff. | Show a policy or retry message. Never fall back to a browser account key. |
| Join | JoinRoomClient completes for an already-authorized room session. | Explain expired or denied access without showing upstream details. |
| Participants | AllMembers updates the participant state used by your UI. | An empty list is valid; clear app-held participant state on exit. |
| Media readiness | CreateDeviceClient returns a device after the room has supplied RTP capabilities. | Handle permission denial, no device, unsupported browser, and device loss separately. |
| Microphone and camera | ClickAudio and ClickVideo update producer state after permission and transport checks. | Stop or disconnect owned producers when toggled off or when leaving. |
| Receive media | ProcessConsumerTransports completes and your render state receives remote streams. | Distinguish no producer, paused media, transport failure, and autoplay policy. |
| Screen share | ClickScreenShare starts or stops the screen-share lifecycle. | Treat capture-picker cancellation as normal; stop the display track and producer together. |
| Leave | LaunchConfirmExit opens the supplied confirmation flow. | Only complete leave after user confirmation; remove listeners and stop owned tracks. |
For a headless host surface, MediasfuHeadlessService exposes the same three
semantic outcomes:
import { MediasfuHeadlessService } from 'mediasfu-angular';
constructor(public readonly room: MediasfuHeadlessService) {}
leaveParticipantOrEndAsHost() {
return this.room.controls.leave(false, true);
}
leaveAsHostAndKeepRoomOpen() {
return this.room.controls.leave(false, false);
}
The Boolean defaults to true. Use false only for a button explicitly
labelled Leave and keep room open, await its result, and then run the normal
authorized join flow when the host returns. See leave, end, and rejoin.
Release checklist
- Verify your backend rejects unauthenticated create and join requests.
- Test host and participant flows in separate browser contexts.
- Approve and deny microphone, camera, and display capture permissions.
- Confirm remote audio, video, and screen media render for another user.
- Confirm a participant leave updates the host view and cleans local tracks.
- Confirm your backend's room and temporary-authority cleanup policy.
Build and test your Angular application, then run the checklist in a real two-user room before release. A successful application build does not replace camera, microphone, screen-share, or remote-playback acceptance.