These events fire when media tracks start or stop, when screen sharing changes, and when audio level and face detection information is available. Support varies per event — see the badge on each section.
track-started
Fires when a participant’s media track begins. Use this to attach the track to a media element or update your UI when a new audio, video, or screen share track becomes available.
The ID of the call client instance that emitted this event.
The participant whose track started. See participants() for the full shape.
The track type. One of 'audio', 'video', 'screenAudio', 'screenVideo', or a custom track name.
// Example event object
{
"action": "track-started",
"callClientId": "17225364729060.9442072768918943",
"participant": {
"session_id": "f2190c86-169a-464f-c0a4-ee1d5c00af58",
"user_id": "f2190c86-169a-464f-c0a4-ee1d5c00af58",
"user_name": "",
"local": true,
"owner": false,
"record": false,
"networkQualityState": "good",
"tracks": {
"audio": { "state": "playable", "subscribed": true },
"video": { "state": "playable", "subscribed": true },
"screenVideo": { "state": "off", "subscribed": false },
"screenAudio": { "state": "off", "subscribed": false }
},
"joined_at": "2024-06-01T12:00:00.000Z",
"will_eject_at": "2024-06-01T13:00:00.000Z"
},
"track": {
"contentHint": "",
"enabled": true,
"id": "60d47b9f-6b07-4039-930a-8b752c6dbd26",
"kind": "video",
"label": "FaceTime HD Camera (Built-in) (05ac:8514)",
"muted": false,
"onended": null,
"onmute": null,
"onunmute": null,
"readyState": "live",
"managedByDaily": true
},
"type": "video"
}
call.on('track-started', ({ participant, track, type }) => {
if (type === 'video' && !participant.local) {
const videoEl = document.createElement('video');
videoEl.srcObject = new MediaStream([track]);
videoEl.autoplay = true;
document.getElementById('remote-videos').appendChild(videoEl);
}
});
track-stopped
Fires when a participant’s media track stops. Use this to remove a media element or update your UI when a track is no longer active.
The ID of the call client instance that emitted this event.
The participant whose track stopped. See participants() for the full shape.
The track type. One of 'audio', 'video', 'screenAudio', 'screenVideo', or a custom track name.
// Example event object
{
"action": "track-stopped",
"callClientId": "17225364729060.9442072768918943",
"participant": {
"session_id": "f2190c86-169a-464f-c0a4-ee1d5c00af58",
"user_id": "f2190c86-169a-464f-c0a4-ee1d5c00af58",
"user_name": "",
"local": true,
"owner": false,
"record": false,
"networkQualityState": "good",
"tracks": {
"audio": { "state": "playable", "subscribed": true },
"video": { "state": "off", "subscribed": false },
"screenVideo": { "state": "off", "subscribed": false },
"screenAudio": { "state": "off", "subscribed": false }
},
"joined_at": "2024-06-01T12:00:00.000Z",
"will_eject_at": "2024-06-01T13:00:00.000Z"
},
"track": {
"contentHint": "",
"enabled": true,
"id": "60d47b9f-6b07-4039-930a-8b752c6dbd26",
"kind": "video",
"label": "FaceTime HD Camera (Built-in) (05ac:8514)",
"muted": false,
"onended": null,
"onmute": null,
"onunmute": null,
"readyState": "ended",
"managedByDaily": true
},
"type": "video"
}
call.on('track-stopped', ({ participant, track, type }) => {
if (type === 'video' && !participant.local) {
const videoEl = document.getElementById(`video-${participant.session_id}`);
if (videoEl) videoEl.remove();
}
});
local-screen-share-started
Fires when the local participant’s screen share has started. Use this to update your UI to reflect that sharing is active.
Always "local-screen-share-started".
The ID of the call client instance that emitted this event.
// Example event object
{
"action": "local-screen-share-started",
"callClientId": "17225364729060.9442072768918943"
}
call.on('local-screen-share-started', () => {
document.getElementById('share-btn').textContent = 'Stop sharing';
document.getElementById('share-indicator').classList.remove('hidden');
});
local-screen-share-stopped
Fires when the local participant’s screen share has stopped. Use this to reset any screen-share UI state.
Always "local-screen-share-stopped".
The ID of the call client instance that emitted this event.
// Example event object
{
"action": "local-screen-share-stopped",
"callClientId": "17225364729060.9442072768918943"
}
call.on('local-screen-share-stopped', () => {
document.getElementById('share-btn').textContent = 'Share screen';
document.getElementById('share-indicator').classList.add('hidden');
});
local-screen-share-canceled
Fires when the user dismisses the browser’s screen picker before ever starting a screen share.
Detection of this user action only works in Chrome. On Safari and Firefox, this action is reported as the user blocking the permission and a nonfatal screen-share-error event is sent instead.
Always "local-screen-share-canceled".
The ID of the call client instance that emitted this event.
// Example event object
{
"action": "local-screen-share-canceled",
"callClientId": "17225364729060.9442072768918943"
}
call.on('local-screen-share-canceled', () => {
// User closed the picker — reset the button back to its idle state.
document.getElementById('share-btn').disabled = false;
document.getElementById('share-btn').textContent = 'Share screen';
});
local-audio-level
Fires at the frequency specified when starting the local audio level observer, providing the local participant’s current audio level. Use this to drive a volume indicator in your UI.
Always "local-audio-level".
The ID of the call client instance that emitted this event.
The local participant’s current audio level, from 0.0 (silent) to 1.0 (maximum).
// Example event object
{
"action": "local-audio-level",
"callClientId": "17225364729060.9442072768918943",
"audioLevel": 0.149356
}
call.on('local-audio-level', ({ audioLevel }) => {
const bar = document.getElementById('local-volume-bar');
bar.style.width = `${Math.round(audioLevel * 100)}%`;
});
remote-participants-audio-level
Fires at the frequency specified when starting the remote participants audio level observer, providing audio levels for all remote participants. Use this to drive per-participant volume indicators or highlight the active speaker.
Always "remote-participants-audio-level".
The ID of the call client instance that emitted this event.
A map of participant session_id to audio level (0.0–1.0). Only remote participants are included.
// Example event object
{
"action": "remote-participants-audio-level",
"callClientId": "17225364729060.9442072768918943",
"participantsAudioLevel": {
"24ebb6ed-315f-40c3-acb7-a917c4ea6202": 0.1,
"cc3d2760-442e-4cfa-afc1-4fd387253f72": 0.0223872113856834
}
}
call.on('remote-participants-audio-level', ({ participantsAudioLevel }) => {
let activeSpeakerId = null;
let maxLevel = 0;
for (const [sessionId, level] of Object.entries(participantsAudioLevel)) {
const bar = document.getElementById(`volume-${sessionId}`);
if (bar) bar.style.width = `${Math.round(level * 100)}%`;
if (level > maxLevel) {
maxLevel = level;
activeSpeakerId = sessionId;
}
}
if (activeSpeakerId) {
highlightActiveSpeaker(activeSpeakerId);
}
});
face-counts-updated
Fires when the face count in the local camera view has changed. Use this to identify how many people are visible in frame at a given time.
This event is only emitted while the face-detection video processor is active. See updateInputSettings() for details on enabling it.
Always "face-counts-updated".
The ID of the call client instance that emitted this event.
The number of faces currently detected in the local camera view.
// Example event object
{
"action": "face-counts-updated",
"callClientId": "17225364729060.9442072768918943",
"faceCounts": 1
}
call.on('face-counts-updated', ({ faceCounts }) => {
const label = document.getElementById('face-count-label');
label.textContent = `${faceCounts} ${faceCounts === 1 ? 'person' : 'people'} in frame`;
});
See also