Skip to main content
Daily’s input settings API lets you apply real-time processing to audio and video tracks — noise cancellation, background blur, background replacement, and face detection — as well as supply custom MediaStreamTrack objects in place of the default camera and microphone. Send settings control encoding quality and simulcast behavior; receive settings control which simulcast layer remote streams are decoded at.

Input settings

updateInputSettings() and getInputSettings()

// Apply settings
const { inputSettings } = await call.updateInputSettings({
  audio: { processor: { type: 'noise-cancellation' } },
  video: { processor: { type: 'background-blur', config: { strength: 0.5 } } },
});

// Read current settings
const current = await call.getInputSettings();
Both operate on a DailyInputSettings object:
interface DailyInputSettings {
  audio?: DailyInputAudioSettings;
  video?: DailyInputVideoSettings;
}
You can also pass inputSettings to join() or startCamera() to apply settings before the first frame is captured.

Audio input settings

interface DailyInputAudioSettings {
  processor?: DailyInputAudioProcessorSettings;
  settings?: MediaTrackConstraints | DailyCustomTrackSettings;
}

interface DailyInputAudioProcessorSettings {
  type: 'none' | 'noise-cancellation';
}
processor.type
string
  • 'none' — no audio processing
  • 'noise-cancellation' — applies Daily’s built-in noise cancellation model
settings
MediaTrackConstraints | DailyCustomTrackSettings
Pass standard MediaTrackConstraints to configure the microphone (e.g. echoCancellation, sampleRate), or a DailyCustomTrackSettings to supply your own track:
interface DailyCustomTrackSettings {
  customTrack: MediaStreamTrack;
}

Video input settings

interface DailyInputVideoSettings {
  processor?: DailyInputVideoProcessorSettings;
  settings?: MediaTrackConstraints | DailyCustomTrackSettings;
}
DailyInputVideoProcessorSettings is a union of four processor types:
Disables any active video processor:
await call.updateInputSettings({
  video: { processor: { type: 'none' } },
});

input-settings-updated event

Fires whenever input settings change (locally or remotely triggered):
call.on('input-settings-updated', ({ inputSettings }) => {
  console.log('New input settings:', inputSettings);
});

Example: noise cancellation and background blur

// Enable both noise cancellation and background blur at join time
await call.join({
  url: roomUrl,
  inputSettings: {
    audio: {
      processor: { type: 'noise-cancellation' },
    },
    video: {
      processor: {
        type: 'background-blur',
        config: { strength: 0.5 },
      },
    },
  },
});

// Toggle noise cancellation later
async function toggleNoiseCancellation(enabled: boolean) {
  await call.updateInputSettings({
    audio: {
      processor: { type: enabled ? 'noise-cancellation' : 'none' },
    },
  });
}
Video processors require browser support for OffscreenCanvas and WebGL. Check Daily.supportedBrowser().supportsVideoProcessing before enabling them.

Send settings

Send settings control how the local participant’s video is encoded and transmitted.

updateSendSettings() and getSendSettings()

const updated = await call.updateSendSettings({
  video: 'bandwidth-optimized',
});

const current = call.getSendSettings(); // DailySendSettings | null
interface DailySendSettings {
  video?: DailyCamVideoSendSettings | DailyVideoSendSettingsPreset;
  screenVideo?: DailyVideoSendSettings | DailyScreenVideoSendSettingsPreset;
  customVideoDefaults?: DailyVideoSendSettings | DailyVideoSendSettingsPreset;
  [customKey: string]: DailyVideoSendSettings | DailyCamVideoSendSettings
    | DailyVideoSendSettingsPreset | DailyScreenVideoSendSettingsPreset | undefined;
}

Video send settings presets

For camera video (video key):
PresetDescription
'default-video'Default encoding for camera video
'bandwidth-optimized'Lower bitrate, smaller resolution
'bandwidth-and-quality-balanced'Balanced tradeoff
'quality-optimized'Higher bitrate and resolution
'adaptive-2-layers'Simulcast with 2 quality layers
'adaptive-3-layers'Simulcast with 3 quality layers
For screen video (screenVideo key):
PresetDescription
'default-screen-video'Default screen share encoding
'detail-optimized'Prioritizes clarity (good for slides)
'motion-optimized'Prioritizes framerate (good for video)
'motion-and-detail-balanced'Balanced tradeoff

Custom encoding parameters

For fine-grained control, use DailyVideoSendSettings directly:
interface DailyVideoSendSettings {
  maxQuality?: 'low' | 'medium' | 'high';
  encodings?: {
    low: RTCRtpEncodingParameters;
    medium?: RTCRtpEncodingParameters;
    high?: RTCRtpEncodingParameters;
  };
}

// Camera video additionally supports adaptive layers
interface DailyCamVideoSendSettings extends DailyVideoSendSettings {
  allowAdaptiveLayers?: boolean;
}
await call.updateSendSettings({
  video: {
    allowAdaptiveLayers: true,
    maxQuality: 'high',
    encodings: {
      low: { maxBitrate: 80_000, scaleResolutionDownBy: 4 },
      medium: { maxBitrate: 300_000, scaleResolutionDownBy: 2 },
      high: { maxBitrate: 1_200_000, scaleResolutionDownBy: 1 },
    },
  },
});

send-settings-updated event

call.on('send-settings-updated', ({ sendSettings }) => {
  console.log('Send settings changed:', sendSettings);
});

Receive settings

Receive settings let you select which simulcast layer to decode for each remote participant’s video tracks. This is useful for saving bandwidth when you know certain participants’ video will be displayed at a smaller size.

updateReceiveSettings() and getReceiveSettings()

// Get settings for all participants
const allSettings = await call.getReceiveSettings();

// Get settings for a specific participant (with inherited values filled in)
const participantSettings = await call.getReceiveSettings(sessionId, {
  showInheritedValues: true,
});

// Update receive settings
const updated = await call.updateReceiveSettings({
  // Use the special '*' key to set a default for all participants
  '*': { video: { layer: 1 } },
  // Override for a specific participant (renders at full quality)
  [speakerSessionId]: { video: { layer: 2 } },
});
interface DailyReceiveSettings {
  [participantIdOrBase: string]: DailySingleParticipantReceiveSettings;
}

interface DailySingleParticipantReceiveSettings {
  video?: DailyVideoReceiveSettings;
  screenVideo?: DailyVideoReceiveSettings;
  [customKey: string]: DailyVideoReceiveSettings | undefined;
}

interface DailyVideoReceiveSettings {
  layer?: number; // 0 = lowest quality, higher = better quality
}
When updating, you can use 'inherit' to reset a participant back to the default:
await call.updateReceiveSettings({
  [sessionId]: 'inherit', // reset this participant to the '*' default
});

receive-settings-updated event

call.on('receive-settings-updated', ({ receiveSettings }) => {
  console.log('Receive settings updated:', receiveSettings);
});

Example: active speaker optimization

Set a low-quality default for all participants and bump up the active speaker:
// Set low layer as default
await call.updateReceiveSettings({ '*': { video: { layer: 0 } } });

let currentSpeakerId: string | null = null;

call.on('active-speaker-change', async ({ activeSpeaker }) => {
  const updates: Record<string, any> = {};

  // Reset the previous speaker
  if (currentSpeakerId) {
    updates[currentSpeakerId] = 'inherit';
  }

  // Promote the new speaker to high quality
  if (activeSpeaker.peerId) {
    updates[activeSpeaker.peerId] = { video: { layer: 2 } };
    currentSpeakerId = activeSpeaker.peerId;
  }

  await call.updateReceiveSettings(updates);
});