# Changelog archive: 2025
Source: https://docs.daily.co/changelog/2025
Archived Daily changelog entries from 2025: transcription webhooks, canReceive permissions, meeting-move-aware recording and streaming, SIP/PSTN join-time permissions, and React Native New Architecture support.
Archived changelog entries from 2025. For the latest updates, see the [changelog](/changelog).
SIP/PSTN join-time permissions, React Native New Architecture support, recording and telephony improvements.
## Overview
This month, we've shipped join-time permissions for SIP/PSTN users across our client SDKs. React Native developers can now build with the New Architecture enabled. We've also fixed some recording and telephony bugs.
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## daily-js
[View full release notes →](https://github.com/daily-co/daily-js/releases)
### 0.80.0
* Added support for setting permissions for SIP/PSTN users at join time.
* Removed the use of STUN from Xirsys.
* Updated dependencies to resolve security vulnerabilities.
***
## react-native-daily-js
[View full release notes →](https://github.com/daily-co/react-native-daily-js/releases)
### 0.77.0
* Added support for setting permissions for SIP/PSTN users at join time.
* Fixed a build issue when using React Native's New Architecture.
* Removed the use of STUN from Xirsys.
* Updated dependencies to resolve security vulnerabilities.
***
## daily-python
[View full release notes →](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
### 0.19.3
* Added an option to ignore audio level when creating a custom audio track.
### 0.19.2
* Fixed a segmentation fault that could occur on exit when a custom audio source was still writing data.
***
## Media Services
### Recording
* Fixed a bug where a failed session asset image URL could cause a recording composition to crash.
### Telephony
* Fixed a bug to correctly extract the `displayName` from custom SIP headers for dial-in participants.
Meeting move aware recording and streaming, new call transfer webhooks, improved telephony features, and platform-wide bug fixes.
## Overview
Mobile SDKs now support canReceive permissions and improved connection reliability. The Python SDK gets powerful custom audio track capabilities. Meeting move aware recording is enabled by default, we've added call transfer webhooks, and transcription saves are now more resilient.
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## daily-js
[View full release notes →](https://github.com/daily-co/daily-js/releases)
### 0.79.0
* Improved Krisp error handling.
* Removed a client-side limit on `max_live_streams`.
* Disabled Redux DevTools in production builds.
***
## react-native-daily-js
[View full release notes →](https://github.com/daily-co/react-native-daily-js/releases)
### 0.76.0
* Removed a client-side limit on `max_live_streams`.
* Disabled Redux DevTools in production builds.
***
## daily-android
[View full release notes →](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
### 0.31.0
* Added support for the `canReceive` permission to manage which media tracks remote participants can receive.
* Improved connection reliability by retrying signaling channel connections and using an alternate WebSocket URI format.
* Fixed a bug where custom ICE server configurations were not being applied.
***
## daily-ios
[View full release notes →](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
### 0.31.0
* Added support for the `canReceive` permission to manage which media tracks remote participants can receive.
* Improved connection reliability by retrying signaling channel connections and using an alternate WebSocket URI format.
***
## daily-python
[View full release notes →](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
### 0.19.1
* Fixed an audio renderer issue that caused garbled audio with remote stereo tracks.
* Added handling for meeting session ID changes that occur mid-call.
### 0.19.0
* Introduced `CustomAudioTrack` for use as an additional custom track or as the main microphone input.
* Added support for `displayName`, `userId`, `video`, `codecs`, and `permissions` in `start_dialout()`.
* Added `sample_rate` and `callback_interval_ms` arguments to `set_audio_renderer()` for more control over audio data.
* Updated `add_custom_audio_track()` and `update_custom_audio_track()` to accept a `CustomAudioTrack` instance.
* Switched to using system-level root certificates on all platforms.
* Fixed a bug where blocking virtual microphones could fail to send audio.
### 0.18.2
* Fixed an installation issue on macOS versions older than 15.0.
* Corrected type hints for `remove_custom_track()`.
### 0.18.1
* Improved connection reliability by retrying signaling channel connections and using an alternate WebSocket URI format.
* Fixed a bug with virtual microphone completion callbacks.
***
## Media Services
### Recording
* Meeting move aware recording and streaming is now enabled by default. This feature [(previously in pre-beta)](/changelog/2024#recording-and-streaming-recovery-during-meeting-moves-pre-beta) automatically resumes recordings and live streams when meetings are transferred between servers during maintenance or failovers, eliminating gaps in recorded content.
### Telephony
* Introduced new webhooks to track call transfer status: `calltransfer.triggered`, `calltransfer.initiated`, `calltransfer.answered`, and `calltransfer.complete`.
* Added support for passing custom SIP headers during pinless dial-in, which are now available in the `sipHeaders` object in the webhook payload.
* Added `canReceive` permission controls for dial-in and dial-out participants via the `startDialOut()` API and room properties.
* On-demand SIP dial-out endpoints are now the default behavior, improving resource efficiency.
### Transcription
* Transcripts are now saved to storage every two minutes by default, improving data resilience.
* The `/transcript` and `/transcripts` API endpoints now include `roomName`, `participantMinutes`, and `isVttAvailable` for more detailed information.
* Fixed a race condition that could cause duplicate transcription messages when participant settings were updated rapidly.
Stability fixes for ejection logic and network states, Python custom audio tracks, enhanced recording webhooks, improved telephony features, and performance diagnostics for slow joins.
## Overview
We've shipped stability improvements across the board this month. Key fixes include meeting ejection logic, network state calculations, and slow join diagnostics. The Python SDK now supports custom audio tracks, and raw tracks recordings now include instance IDs in webhooks.
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## daily-js
[View full release notes →](https://github.com/daily-co/daily-js/releases)
### 0.78.0
* Fixed ejection logic to prevent incorrect ejections or joins when a user's local clock is out of sync. ⚠️ **Note:** Participants can no longer join if `eject_after_elapsed` is set to a negative value.
* Fixed an `OverconstrainedError` on Chrome that occurred when providing an invalid audio `deviceId`.
* Fixed an issue where unhandled errors during Krisp initialization could cause problems when joining a call.
* Reverted a change that disabled background effects on Windows when software WebGL is in use. Instead, a `video-processor-warning` is now logged, as this scenario can significantly reduce video frame rates.
* Improved `networkState` calculations by removing `recvPacketLoss`, which could be misleading.
* Added `instanceId` to webhooks for raw tracks recordings.
* Added performance logging for `enumerateDevices()` to help identify slow join times, especially on Firefox when the tab is not in focus.
* Removed the beta feature warning from `testCallQuality()`.
***
## react-native-daily-js
[View full release notes →](https://github.com/daily-co/react-native-daily-js/releases)
### 0.75.0
* Fixed ejection logic to prevent issues caused by mismatched local clock times. ⚠️ **Note:** Participants can no longer join if `eject_after_elapsed` is set to a negative value.
* Improved `networkState` calculation by removing `recvPacketLoss` from the formula.
* Added `instanceId` to webhooks for raw tracks recordings.
* Added performance logging for `enumerateDevices()` to help diagnose slow join times.
***
## daily-python
[View full release notes →](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
### 0.18.0
* Introduced support for creating, updating, and removing custom audio tracks. You can now use `CallClient.add_custom_audio_track()`, `CallClient.update_custom_audio_track()`, and `CallClient.remove_custom_audio_track()` for advanced audio manipulation.
* Improved `canReceive` permission support to ensure track states (`"off"`, `offReasons`) update correctly when permissions are granted or revoked.
* Audio and video renderer callbacks (`set_audio_renderer()`, `set_video_renderer()`) now receive the audio or video source as the last argument.
* Reduced "no subscription for consumer" and "Failed to close consumer" log messages from error to debug, as these often occur during normal participant disconnections.
## Media Services
### Recording
* **Instance ID in Webhooks**: The `recording.ready-to-download` and `raw-tracks-recording-error` webhooks now include an `instance_id` to uniquely identify raw tracks recording sessions.
* Fixed an issue to ensure the `instanceId` is correctly propagated for raw tracks recordings from the initial API call through to the final webhook event.
### Telephony
* **`dialin.ready` Webhook**: Introduced the `dialin.ready` webhook event, which notifies you when a room's SIP endpoint is ready to receive an inbound call.
* **`origin` Field in Dial-Out Webhooks**: Dial-out webhook events now include an `origin` field, specifying the PSTN number or SIP URI that initiated the call.
* **Default SIP Codec**: Added a domain-level property to set default codecs for SIP/PSTN calls. Opus is now the default codec for all dial-in calls.
* **On-Demand SIP Endpoints**: SIP endpoints for dial-out are now created on-demand when `startDialOut()` is called, improving resource efficiency and room creation reliability.
* **Error Messaging**: Enhanced error messages for dial-in/out configurations during room creation.
New canReceive permission, dynamic track constraints, revamped network stats, enhanced telephony features (caller ID, SIP fixes), improved platform stability and compatibility (reconnection, ICE, and more), and security updates.
## Overview
As we close out the first quarter, recent updates across the Daily ecosystem deliver major new features and bug fixes. We've introduced the `canReceive` permission for fine-grained media control, revamped network statistics (networkState, networkStateReasons) while deprecating older metrics, enhanced telephony capabilities (caller ID, SIP stability, API improvements), refined recording composition, and fixed bugs across the platform.
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## daily-js
[View full release notes →](https://github.com/daily-co/daily-js/releases)
### 0.77.0
#### Introduced `canReceive` Permission
We extended the available permissions to include `canReceive`, which allows meeting owners to control the media tracks of others in the session. This feature enables use cases like "warm transfers" (e.g., ensuring a customer doesn't hear an agent before the handoff is complete) and other scenarios requiring selective visibility or audibility within a call. See the [participant permissions documentation](/reference/daily-js/instance-methods/participants#param-permissions) for details.
#### Improved Network Quality Statistics
We introduced two new fields in the object returned by [`getNetworkStats()`](/reference/daily-js/instance-methods/get-network-stats) to provide more accurate network quality data: `networkState` and `networkStateReasons`. These replace the deprecated `threshold` and `quality` fields, offering a more reliable assessment based on send/receive packet loss, round-trip time, and available outgoing bitrate.
#### Bug fixes and improvements
* Fixed `proxyUrl` support in `dailyConfig`.
* Optimized background effects on Windows by disabling them when hardware acceleration is unavailable.
* Updated internal dependencies to resolve security vulnerabilities.
* Simplified `recordings_bucket` response in `room()` method for enhanced security.
### 0.76.0
#### Bug fixes and performance improvements
* Updated Krisp noise cancellation library to v2.2.1.
* Fixed switching back from custom video track to device track via `setInputDevicesAsync()`.
* Fixed `iceTransportPolicy` configuration to correctly override domain defaults.
* Added `enable_dialout` to TypeScript definitions for `DailyRoomInfo`.
### 0.75.2
#### Bug fixes
* Fixed unnecessary video track re-acquisition during input settings updates.
### 0.75.1
#### Bug fixes
* Fixed video constraint preservation when changing devices.
* Removed console error for null `deviceId` in `setInputDevicesAsync`.
### 0.75.0
#### Enhanced Participant Type for Dial-in/out
The `participant` object now includes specific `participantType` values to identify telephony participants: `sip-dial-in`, `sip-dial-out`, `pstn-dial-in`, and `pstn-dial-out`. This allows for clearer identification of how participants joined via SIP or PSTN dial-in/out.
#### Dynamic Input Track Constraints
Introduced support for dynamically customizing media track constraints during a call using [`updateInputSettings()`](/reference/daily-js/instance-methods/update-input-settings). This allows changing camera resolution, frame rate, or switching between front and rear cameras without rejoining. The previous constraint-setting methods (`userMediaAudioConstraints`, `userMediaVideoConstraints`, and `setBandwidth` trackConstraints) are now deprecated.
#### Bug fixes and improvements
* Fixed track event reliability for rapid muting/unmuting and custom tracks.
* Fixed track event participant info on leave.
* Improved Krisp initialization error handling.
* Fixed `ondevicechange` undefined error on certain systems.
* Updated Banuba SDK to eliminate need for `'unsafe-eval'` CSP directive with `avoidEval: true`.
* Updated minimum supported version to 0.64.0.
***
## react-native-daily-js
[View full release notes →](https://github.com/daily-co/react-native-daily-js/releases)
### 0.74.0
#### Introduced `canReceive` Permission
Added support for the new `canReceive` permission for granular control over which media tracks participants receive. See the [participant permissions documentation](/reference/daily-js/instance-methods/participants#param-permissions) for details.
#### Improved Network Quality Statistics
Introduced `networkState` and `networkStateReasons` fields in [`getNetworkStats()`](/reference/react-native/instance-methods/get-network-stats), replacing deprecated `threshold` and `quality` metrics.
#### Bug fixes and improvements
* Added caller ID support for SIP PSTN transfers in `sipCallTransfer()`.
* Fixed `proxyUrl` support.
* Updated dependencies for security fixes.
* Simplified `recordings_bucket` response in `room()` method.
### 0.73.0
#### Bug fixes
* Fixed switching from custom video track back to device track.
* Fixed `iceTransportPolicy` configuration override.
* Added `enable_dialout` to TypeScript definitions.
### 0.72.1
#### Reverted Erroneous API Changes
Reverted unintended deprecation notices for `updateInputSettings()` and dynamic track constraints to maintain React Native's existing device handling APIs.
### 0.72.0
#### Enhanced Participant Type for Dial-in/out
Added specific `participantType` values for telephony participants: `sip-dial-in`, `sip-dial-out`, `pstn-dial-in`, and `pstn-dial-out`.
#### Added Audio-Only Raw Tracks Recording
Added `raw-tracks-audio-only` streaming config for audio-only recording support.
#### Bug fixes
* Fixed track event reliability for muting and custom tracks.
* Updated internal REST APIs to use native utilities.
* Added participant info to `track-stopped` events on leave.
### 0.71.0
#### Bug fixes and improvements
* Added `sessionId` to dial-in events.
***
## daily-android
[View full release notes →](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
### 0.30.0
#### Ignore Network Devices API
Introduced `CallClient.GlobalConfig.setIgnoredNetworkDevices()` to exclude specific network interfaces (VPNs, virtual adapters) during ICE candidate gathering for improved connection reliability.
#### Bug fixes
* Fixed ICE server configuration application via `CallClient.setIceConfig()`.
### 0.29.0
#### Automatic Cloud Recording Start
Added support for automatically starting cloud recording on join when `start_cloud_recording: true` is set in the meeting token.
#### Bug fixes and improvements
* Fixed reconnection with expired meeting tokens.
* Updated dependencies (ffmpeg, libav, libvpx) for security patches.
***
## daily-ios
[View full release notes →](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
### 0.30.0
#### Bug fixes
* Fixed ICE server configuration application via `setIceConfig()`.
### 0.29.0
#### Automatic Cloud Recording Start
Added support for automatically starting cloud recording on join when `start_cloud_recording: true` is set in the meeting token.
#### Bug fixes
* Fixed reconnection with expired meeting tokens.
***
## daily-python
[View full release notes →](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
### 0.17.0
#### Improved Linux Compatibility
Recompiled against glibc 2.28 for broader Linux distribution support.
### 0.16.1
#### Bug fixes
* Fixed virtual speaker device selection.
### 0.16.0
#### Update `canReceive` Permissions Support
Added support for modifying remote participant's `canReceive` permission via `update_remote_participants()`.
#### Bug fixes
* Fixed ICE server configuration application.
### 0.15.0
#### Automatic Cloud Recording Start
Added support for automatically starting cloud recording on join when `start_cloud_recording: true` is set in the meeting token.
#### Bug fixes
* Fixed reconnection with expired meeting tokens.
***
## Daily Prebuilt
#### Transcription Language Defaults
Transcription now defaults to the room/domain `lang` configuration when started via Closed Captions, falling back to English if not configured.
***
## Media Services
### Recording and Live Streaming
#### New Features
* **Scale Mode Overrides**: Added `videoSettings.split.scaleModeOverrides` for individual participant scaling in split layout compositions.
* **Background Color Support**: VCS render pipeline now supports custom background colors via `backgroundColor` parameter.
#### Bug fixes
* Fixed audio-only participant filtering in baseline compositions.
* Fixed instance ID handling for raw tracks recording.
### Telephony
#### Enhanced Caller ID Control
Added `callerId` support in `sipCallTransfer()` for PSTN transfers with improved default caller ID selection logic.
#### API Improvements
* Domain dial-in configs endpoint now supports filtering by multiple phone numbers.
* Purchased phone numbers endpoint now includes pagination support.
* Room creation API provides more specific telephony provisioning error messages.
#### Bug fixes and improvements
* Improved SIP INVITE handling to prevent signaling state errors.
* Enhanced error messages for invalid call transfers.
* Fixed layout updates for disconnected SIP participants.
* Added comprehensive [transfer guide documentation](/docs/guides/features/dial-in-dial-out/transfers).
### Transcription
#### Bug fixes
* Fixed race condition when stopping or updating transcription immediately after starting.
New transcription webhooks, better multi-instance recording support, improved telephony features, platform-wide bug fixes, and strengthened SDK reliability.
## Overview
Rounding out 2024 and kicking off 2025 with major improvements across Daily's platform components: bug fixes (Safari audio processing detection, call quality test error handling), expanded feature set (improved PSTN/SIP support, expanded multi-instance recording, new transcription webhooks), and strengthened infrastructure (SDK and media service reliability).
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## daily-js
### 0.74.0
#### Updated Krisp CSP Requirements
Added missing `blob:` source to the [CSP guide](/docs/guides/privacy-and-security/content-security-policy):
```js theme={null}
script-src 'self' https://unpkg.com/@daily-co/daily-js blob:;
```
#### Follow-up fix for Safari Audio Processing Detection
Fixed a logical error in Safari version comparison for audio processing support. We resolved an edge case where Safari versions above 18 were incorrectly flagged as unsupported. This completes the [Safari 17.4+ audio processing detection fix](/changelog/2024#fixed-audio-processing-detection-in-safari-17-0-17-3) from our previous release.
This change ensures accurate audio processing support detection across all Safari versions.
#### Fixed Call Quality Test Error Handling
Fixed error handling in `testCallQuality()` when rate limits are hit and improved promise rejection handling to avoid uncaught errors. Test failures now properly resolve with a FAILED result instead of throwing.
#### Added Session ID to Dial-in Events
Added sessionId field to all dial-in events: `dialin-connected`, `dialin-error`, `dialin-stopped`, and `dialin-warning`.
For example:
```js theme={null}
dialinConnected: { sessionId: 'abc-123', sipFrom: '+1234567890', ... }
```
#### Version Support Update
* The oldest supported version of `daily-js` is now 0.63.0.
***
## react-native-daily-js
### 0.71.0
This release also includes several core improvements shared with daily-js 0.74.0:
* Added sessionId to dial-in events
See the daily-js 0.74.0 section for full details on these changes.
***
## daily-android
### 0.28.0
#### Added support for Cloudflare TURN/STUN servers
Added support for using Cloudflare TURN/STUN servers for ICE connections. If you're interested in using this for your Daily domain, please contact [help@daily.co](mailto:help@daily.co)
#### Fixed Android Proguard Build Configuration
Fixed an issue where apps using R8/Proguard would fail to build due to missing Banuba video processor classes:
* Added proper Proguard configuration for optional Banuba SDK dependencies
* Ensured R8 optimization doesn't fail on missing video processor classes
* Maintained backwards compatibility with existing video processor integrations
This change prevents build failures in release builds when the video processor plugin is not included.
### 0.27.0
#### Fixed crash when creating and deleting `VideoTextureView`/`VideoTrackCapturerToSurface` without also creating a `CallClient`.
Fixed an issue where `daily-android` would crash when cleaning up video views without an active CallClient:
* Moved native library initialization to shared context to prevent premature loading
* Added safety checks to prevent cleanup of uninitialized native contexts
* Improved synchronization of client tracking in shared context
This change prevents crashes when creating and destroying video views without an active call client, improving stability for applications that conditionally initialize video components.
#### Enhanced Call Reliability during Meeting Moves
Improved call reliability during meeting moves by implementing increased retry attempts for meeting moves to handle longer backend processing times.
***
## daily-ios
### 0.28.0
#### Added support for Cloudflare TURN/STUN servers
Added support for using Cloudflare TURN/STUN servers for ICE connections. If you're interested in using this for your Daily domain, please contact [help@daily.co](mailto:help@daily.co)
### 0.27.0
#### Enhanced Call Reliability during Meeting Moves
Improved call reliability during meeting moves by implementing increased retry attempts for meeting moves to handle longer backend processing times.
***
## daily-python
### 0.14.2
#### Fixed type hints for CallClient.send\_app\_message()
Fixed type hints for `CallClient.send_app_message()` to match the expected payload structure.
### 0.14.1
#### Enhanced App Message Serialization
Added `serialize_none` option to `CallClient.send_app_message()` to control whether `None` values are serialized to JSON `null` or ignored. This enables more flexible data handling in application messages.
### 0.14.0
#### Added DTMF Support for Dial-out Calls
Added the ability to send DTMF tones in dial-out sessions using `CallClient.send_dtmf()`[docs](https://reference-python.daily.co/api_reference.html#daily.CallClient.send_dtmf):
* Send numeric tones (0-9), symbols (#, \*) and letters (A-D) to control interactive voice systems
* Control automated phone menus and voicemail systems during dial-out calls
* Specify session ID and tone sequences via simple settings object
This addition enables programmatic interaction with phone systems that require DTMF input during dial-out calls.
#### Added SIP REFER Support
Added support for transferring SIP calls to external endpoints via `CallClient.sip_refer()` ([docs](https://reference-python.daily.co/api_reference.html#daily.CallClient.send_dtmf)):
* Transfer ongoing SIP dial-in calls to external SIP endpoints
* Control transfers using session ID and destination endpoint
* Support for standard SIP REFER mechanism
This addition enables seamless call transfers between Daily and external SIP systems.
#### Added Daily-to-Daily SIP Call Transfer Support
Added support for transferring SIP/PSTN calls between Daily rooms via `CallClient.sip_call_transfer()` ([docs](https://reference-python.daily.co/api_reference.html#daily.CallClient.sip_call_transfer)):
* Transfer SIP dial-in calls between Daily rooms
* Transfer dial-out calls to other SIP/PSTN endpoints
* Control transfers using session ID and destination endpoint
This addition enables seamless call transfers within the Daily ecosystem and to external numbers.
#### Changed field name in Dial Events
Renamed `participantId` to `sessionId` in `DialoutEvent` and `DialinEvent` objects for consistency
#### Enhanced Call Reliability during Meeting Moves
Improved call reliability during meeting moves by implementing increased retry attempts for meeting moves to handle longer backend processing times.
***
## Daily Prebuilt
* Enhanced accessibility across Prebuilt with ARIA attributes, improved keyboard navigation, semantic HTML, updated labels and roles, and better screen reader support to meet WCAG standards.
* Fixed issue where GIFs with empty titles were not rendered in chat.
* Fixed a case where flickering in chat input height occurred while typing.
***
## Media Services
### Recording and Live Streaming
#### Support Multiple Recording Types with Multi-Instance Recording
Added support for running different recording types simultaneously using instance IDs:
```js theme={null}
// Start a cloud recording
await call.startRecording({
instanceId: '123e4567-e89b-12d3-a456-426614174000',
type: 'cloud',
layout: {
preset: 'default',
},
});
// Start raw-tracks recording in parallel
await call.startRecording({
instanceId: '987fdef0-c65b-11d1-b2e2-526614174000',
type: 'raw-tracks',
});
```
* New `type` parameter in `startRecording()` ([docs](/reference/daily-js/instance-methods/start-recording)) API accepts `'cloud'`, `'raw-tracks'`, or `'local'`
* Recording types must be enabled via `enable_recording` property on room/domain
* Each recording instance requires a unique UUID via `instanceId` parameter
You can now run cloud recordings and raw track captures simultaneously, enabling both processed and unprocessed recording workflows from a single call.
#### Added Audio-Only Support for Raw Tracks Recording
Added support for audio-only recording in raw-tracks recordings:
```typescript theme={null}
// Start a raw-tracks recording with audio only
await call.startRecording({
instanceId: '123e4567-e89b-12d3-a456-426614174000',
type: 'raw-tracks',
layout: {
preset: 'raw-tracks-audio-only',
},
});
```
* New `raw-tracks-audio-only` preset captures only audio tracks, reducing storage requirements and simplifying post-processing workflows
* Preset must be specified at recording start - cannot be changed via `updateRecording()`
* Compatible with existing `raw-tracks` processing tools for audio extraction and analysis
This addition makes raw-tracks recordings more flexible for audio-focused use cases where individual tracks are needed for post-processing like podcasting, voice analysis, and audio archival.
#### Added Raw Tracks Processing Tools
Released an open-source suite of tools for processing raw-tracks recordings:
* New [`raw-tracks-tools` CLI](https://github.com/daily-co/raw-tracks-tools) provides tools for analyzing, converting and compositing WebM files from raw-tracks recordings
* Supports track alignment, synchronization, and layout composition using Daily's VCS engine
* Complements existing GUI tools like CloudConvert and Handbrake with more precise control over WebM processing
This release makes raw-tracks recordings more accessible for post-processing workflows, especially for high-quality audio/video production.
#### Added Audio Recording Loss Detection
Added automatic detection of audio quality issues in recordings and streams. This fixes issues where audio quality issues where audio or video tracks were visible during the live call but not in the final recording/stream.
#### Improved Recording Reliability with Network Optimizations
Enhanced network reliability for all recording types (cloud, raw-tracks, live streaming) and phone integration:
* Increased UDP buffer sizes to prevent packet loss between servers
* Added server-to-server retransmission between SFU and media workers
* Reduces recording freezes and dropped tracks in environments with network congestion
#### Fixed Missing Tracks in Recordings
Fixed an issue where tracks could be missing from recordings when added during WebSocket reconnections between SFU and recording services. New tracks are now properly subscribed even during connection re-establishment.
### Telephony
#### Renamed Dialout Timeout Configuration Field
Renamed dialout configuration parameter from `max_alone_duration_sec` to `max_idle_timeout_sec` to better describe its purpose of controlling how long dialout participants remain in an idle room.
#### Added Participant Type Support in participants() for Phone Participants
Added distinct participant types for phone participants in [participants()](/reference/daily-js/instance-methods/participants) to enable better handling of SIP and PSTN users:
* New participant types: `sip-dial-in`, `sip-dial-out`, `pstn-dial-in`, `pstn-dial-out`
* Automatically set for all phone-based participants, including umbrella participants
This helps developers better identify and manage phone participants in their applications.
#### Fixed Dialout ICE Connection Reliability
Fixed an issue where SIP dialout calls could hang during ICE connection negotiation, improving the reliability of phone system integration.
#### Added `dialout_config` to Room Configuration
Added `dialout_config` ([docs](/reference/rest-api/rooms/get-room#response-config-dialout-config)) as a room-level configuration option to control dialout behavior:
* `dialout_config.allow_room_start`: Allow dialouts to start an empty room
* `dialout_config.max_idle_timeout_sec`: Control how long a dialout participant can remain in a room alone
* `dialout_config.dialout_geo`: Specify region for dialout sessions
### Transcription
#### Unified Transcription Configuration Across Live and Batch Processing
Aligned transcription configuration options between live transcription and batch processing for consistent API usage:
```js theme={null}
// Live transcription
await call.startTranscription({
language: 'fr-CA',
model: 'nova-2-general',
});
```
* All configuration options from [live transcription](/reference/daily-js/instance-methods/start-transcription) (language, model, punctuate, etc.) now supported in [batch processing](/reference/rest-api/batch-processor/reference/submit-job)
* Previous undocumented `params` field maintained for backward compatibility
* Added new `extra` field for additional Deepgram parameters in both APIs
Simplifies transcription configuration by providing a consistent interface across real-time and batch processing workflows.
#### Added Room Name in Transcription API
Enhanced transcription list and info endpoints with room name support:
```js theme={null}
// List transcripts with room name filter
GET /api/transcripts?room_name=my-room*
// Transcript info now includes room name
{
"transcriptId": "123",
"roomId": "456",
"roomName": "my-room",
// ...other fields
}
```
### Webhooks
#### New transcription webhook events
Added three new webhook events to track the full lifecycle of transcriptions:
* [`transcript.started`](/reference/rest-api/webhooks/events/transcript-started) indicates transcription has begun, including metadata like room ID, instance ID and initial status
* [`transcript.ready-to-download`](/reference/rest-api/webhooks/events/transcript-ready-to-download) fires when transcription completes, providing S3 location details for downloading the transcript
* [`transcript.error`](/reference/rest-api/webhooks/events/transcript-error) provides detailed error information and context if transcription fails during any stage
Monitor and automate transcription workflows with comprehensive status updates and error handling through webhooks.
## Other
### Added support for Cloudflare TURN/STUN servers
Added support for using Cloudflare TURN/STUN servers for TURN/STUN connections. If you're interested in using this for your Daily domain, please contact [help@daily.co](mailto:help@daily.co)
# Changelog
Source: https://docs.daily.co/changelog/index
The latest updates and improvements from the Daily engineering team.
Updates from the Daily engineering team across daily-js, Daily React, React Native, daily-python, telephony, and the REST API. Older entries live in the [yearly archives](#older-updates).
EU region transcription, SIP video dial-out quality parameters, cross-SDK domain failover, native SDK stability fixes, and SIP 488 codec negotiation responses.
## Overview
June brings automatic domain failover (`daily.co` → `dailywebrtc.com`/`.net`) across all client SDKs for improved connection resilience. daily-js 0.91.0 and react-native-daily-js 0.86.0 add support for specifying the EU region for transcription and new quality parameters (`fps`, `width`, `height`, `videoBitrate`) for SIP video dial-out. The native SDKs — daily-ios 0.38.0, daily-android 0.38.0, and daily-python 0.30.0 — ship important stability fixes, and daily-python adds custom screen-share audio tracks. On the server side, SIP interoperability improves with proper `488 Not Acceptable` responses for incompatible codecs and custom SIP header passthrough for the Daily provider.
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## daily-js
[View full release notes →](https://github.com/daily-co/daily-js/releases/tag/daily-js-2026-06-10-0.91.0)
### 0.91.0
* Added support for specifying the EU region for [transcription](/reference/daily-js/instance-methods/start-transcription).
* Added `fps`, `width`, `height`, and `videoBitrate` parameters to SIP video [dial-out](/reference/daily-js/instance-methods/start-dial-out).
* External-facing track names are now included in the list of reserved values that are disallowed as custom track names.
* Added automatic client domain failover (`daily.co` → `dailywebrtc.com`/`dailywebrtc.net`) for improved connection resilience.
* Updated dependencies to resolve vulnerabilities.
***
## react-native-daily-js
[View full release notes →](https://github.com/daily-co/react-native-daily-js/releases/tag/react-native-daily-js-2026-06-10-0.86.0)
### 0.86.0
* Added support for specifying the EU region for transcription.
* Added `fps`, `width`, `height`, and `videoBitrate` parameters to SIP video dial-out.
* Added support for AsyncStorage v2 and v3.
* External-facing track names are now included in the list of reserved values that are disallowed as custom track names.
* Added automatic client domain failover (`daily.co` → `dailywebrtc.com`/`dailywebrtc.net`) for improved connection resilience.
* Updated dependencies to resolve vulnerabilities.
***
## daily-ios
[View full release notes →](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
### 0.38.0
* Added `CallClient.initAsync()`, a static async factory that runs the blocking WebRTC/MediaSoup initialization off the main thread, keeping the UI responsive during `CallClient` creation.
* Added automatic fallback to `dailywebrtc.com` and `dailywebrtc.net` when `daily.co` authoritative nameservers are unreachable, improving connection resilience.
* Adaptive Bitrate (ABR) is now enabled by default for camera tracks. It can still be disabled by setting `allowAdaptiveLayers` to `false` in the camera `sendSettings`.
* Fixed an issue where SDK resources were not properly cleaned up when all `CallClient` instances were released.
* Fixed an intermittent crash when force-quitting and relaunching the app while the camera was active.
* Fixed support for the `cloud-audio-only` recording type.
* Improved connection performance with a new HTTP client featuring connection timeouts and TLS configuration reuse.
***
## daily-android
[View full release notes →](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
### 0.38.0
* Added automatic fallback to `dailywebrtc.com` and `dailywebrtc.net` when `daily.co` authoritative nameservers are unreachable, improving connection resilience.
* Adaptive Bitrate (ABR) is now enabled by default for camera tracks. It can still be disabled by setting `allowAdaptiveLayers` to `false` in the camera `sendSettings`.
* Fixed a segmentation fault that could occur when a `CallClient` was released (or garbage collected) while still in a call.
* Fixed support for the `cloud-audio-only` recording type.
* Improved connection performance with a new HTTP client featuring connection timeouts and TLS configuration reuse.
***
## daily-python
[View full release notes →](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
### 0.30.0
* Added automatic fallback to `dailywebrtc.com` and `dailywebrtc.net` when `daily.co` authoritative nameservers are unreachable, improving connection resilience.
* Fixed a use-after-free that could cause a segmentation fault in the audio playout thread if a `CallClient` was released while still in a call with participant audio renderers registered.
* Fixed a segmentation fault that could occur when a `CallClient` was released (or garbage collected) while still in a call.
### 0.29.1
* Fixed an issue where a room configured with `enable_recording` set to `cloud-audio-only` was ignored when starting a recording, causing the recording to also capture video.
* Fixed an issue where `StartRecordingProperties` none properties were serialized to `null`.
### 0.29.0
* Added support for `screenAudio` input, making it possible to send a custom screen-share audio track alongside or independently of `screenVideo`.
***
## Media Services
### Telephony
* Added server-side support for a new `startDialIn()` method to dynamically start a SIP dial-in endpoint. The client-side API will be included in an upcoming daily-js release.
* SIP calls with incompatible codecs now receive a proper `488 Not Acceptable` error response, and the `rtpmap` for the offered Opus codec has been fixed for better codec negotiation interoperability.
* Custom SIP headers are now passed through for calls using the Daily SIP provider.
* `dialout-error` events now include custom SIP headers.
* Fixed a crash that could occur when a SIP session timed out after the session had already been terminated.
### Recording
* The `recording-error` event now includes the `recordingId`, making it easier to correlate errors with specific recordings.
### Streaming
* Fixed a VCS composition issue where pinned tracks that dropped from an explicit pin list were not evicted from the layout.
### Other
* Oldest supported daily-js version bumped to 0.85.0, with 0.86.0 approaching end-of-support.
***
## REST API
* Added `created_at` and `updated_at` to [transcripts API](/reference/rest-api/transcripts) responses.
* Added an opt-in `include_sip_participants` query parameter to [`GET /meetings/:id`](/reference/rest-api/meetings/get-meeting).
Critical Firefox 149 fix, `provider` and `sipCallId` in telephony events, `mtgSessionId` in presence endpoints, and VCS simulator video mode.
## Overview
May brings daily-js 0.90.0 and react-native-daily-js 0.85.0 with a critical fix for a Firefox 149 regression that prevented remote participant media from playing, and new `provider` and `sipCallId` fields across all dial-in and dial-out events for improved telephony observability. On the server side, presence endpoints now include `mtgSessionId`, and the VCS simulator gains video mode support along with a layer pinning fix.
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## daily-js
[View full release notes →](https://github.com/daily-co/daily-js/releases/tag/daily-js-2026-05-13-0.90.0)
### 0.90.0
* Added `provider` and `sipCallId` fields to all `dialin-*` and `dialout-*` events, making it easier to correlate telephony events with specific calls and providers.
* ⚠️ Fixed a Firefox 149 regression that caused remote participant media not to play.
* Fixed a corner case in iOS user-agent detection.
* Updated dependencies to resolve vulnerabilities.
***
## react-native-daily-js
[View full release notes →](https://github.com/daily-co/react-native-daily-js/releases/tag/react-native-daily-js-2026-05-13-0.85.0)
### 0.85.0
* Added `provider` and `sipCallId` fields to all `dialin-*` and `dialout-*` events.
* Updated dependencies to resolve vulnerabilities.
***
## daily-python
[View full release notes →](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
### 0.28.1
* Fixed a segmentation fault that could occur after virtual microphone or speaker inputs or publishing updates.
***
## Media Services
### Streaming
* Added video mode to the VCS simulator, allowing developers to test video layouts directly in the simulator.
* Fixed a track add bug in VCS layer pinning.
***
## REST API
* Added `mtgSessionId` to the responses of [`GET /presence`](/reference/rest-api/presence/get-presence) and `GET /rooms/:name/presence`.
daily-react 0.25.0 with multi-instance recording and streaming, daily-python 0.28.0 with screen share custom tracks, and SIP telephony improvements.
## Overview
April brings daily-react 0.25.0 with support for multiple concurrent recording and live streaming instances, and daily-python 0.28.0 with screen share custom tracks and Adaptive Bitrate enabled by default for camera tracks. On the server side, SIP dial-in and dial-out events now include `sipCallId` and `provider` fields, Signalwire is selectable as a telephony provider, and VCS streaming gains a configurable label placement parameter along with a mic status indicator.
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## daily-react
[View full release notes →](https://github.com/daily-co/daily-react/releases)
### 0.25.0
* Added support for multiple concurrent recording and live streaming instances. `useRecording()` and `useLiveStreaming()` now accept an `instanceId` parameter for per-instance state. New `useRecordingInstances()` and `useLiveStreamingInstances()` hooks return all active instances, and new `RecordingInstanceState` and `LiveStreamingInstanceState` types are exported. Stopping or erroring one instance no longer clears state for others.
* Added `networkStatus` to the return value of `useNetwork()`.
* Added support for the `cloud-audio-only` recording type.
* The daily-react version is now reported through daily-js via the new `aboutClient` API, so it's included in call logs regardless of which library creates the call instance.
***
## daily-python
[View full release notes →](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
### 0.28.0
* Added support for `screenVideo` custom tracks. You can now send a custom screen share track by setting `inputs.screenVideo.settings.customTrack.id`.
* Adaptive Bitrate (ABR) is now enabled by default for camera tracks. It can still be disabled by setting `allow_adaptive_layers` to `False` in the camera `send_settings`.
* Fixed support for the `cloud-audio-only` recording type.
* Fixed panics in signalling reconnect paths when room lookup returns no worker.
***
## Daily Prebuilt
* Tightened the iOS user-agent match to reject spoofed iOS substrings.
* Fixed transcription language fallback so that an empty string falls back to the default language (switched from `??` to `||`).
***
## Media Services
### Telephony
* SIP dial-in and dial-out events now include `sipCallId` and `provider` fields, making it easier to correlate events with specific calls and providers.
* Signalwire and Daily can now be selected as a telephony provider for dial-in and dial-out.
* Standardized the `provider` value to lowercase `signalwire` in dial-in and dial-out events.
* Added `provider` as a valid parameter for the `startDialout` API.
* Added support for video track updates on SIP video calls.
* Fixed screen share track addition for SIP video.
* Added support for configuring a Cloudflare anycast IP address instead of the STUN server hostname.
### Recording
* Added a new `enable_raw_tracks_event_json` domain and room property to opt into JSON event output for raw-tracks recordings.
* Added more WAV settings for raw-tracks transcoded mode.
* Raw-tracks listings now verify S3 item `ContentType` to avoid including unexpected files.
### Streaming
* Added a new VCS parameter `videoSettings.grid.labelPlacement` for customizing participant label position in streaming layouts.
* Added a mic status indicator and a highlight border inset to VCS layouts.
* Fixed VCS participant label misindexing in audio-only layouts.
Smaller call-machine bundle (\~2MB less), VCS layout animations, configurable max API keys, and daily-js 0.81.0 minimum version bump.
## Overview
March includes significant performance improvements for daily-js and react-native-daily-js, with the initial call-machine bundle now \~2MB smaller through dynamic loading. Audio processor errors no longer automatically mute the microphone, and `testCallQuality()` reliability has been fixed. On the server side, VCS streaming layouts gain animation support, and a new `max_api_keys` domain property lets you limit API key creation per domain. The oldest supported daily-js version has been bumped to 0.81.0, with versions through 0.83.1 approaching end-of-support.
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## daily-js
[View full release notes →](https://github.com/daily-co/daily-js/releases)
### 0.89.1
* Fixed an issue causing all `testCallQuality()` tests to fail.
* Fixed remaining vulnerabilities in dependencies.
### 0.89.0
* Reduced initial call-machine bundle download size by \~2MB. Larger portions are now dynamically loaded as-needed.
* Audio processor errors no longer automatically mute the microphone.
* Removed the client-side 3-hour limit for raw-tracks recordings. Limits are now handled server-side.
* Fixed auto-syncing audio output device on Safari, where `setSinkId` requires a user gesture and was causing repeated errors.
* Improved system idle detection to avoid stale reconnect retries after 5 minutes of inactivity. Calls will now leave cleanly in idle scenarios.
* **Breaking:** If you self-host the call-machine-bundle using `callObjectBundleUrlOverride`, a new separate bundle is now required for Krisp noise cancellation. Contact [help@daily.co](mailto:help@daily.co) for upgrade instructions.
***
## react-native-daily-js
[View full release notes →](https://github.com/daily-co/react-native-daily-js/releases)
### 0.84.1
* Fixed remaining vulnerabilities in dependencies.
### 0.84.0
* Reduced initial call-machine bundle download size by \~2MB with dynamic loading.
* Added `digitDurationMs` option to `sendDTMF()` for configurable DTMF digit duration.
* Removed the client-side 3-hour limit for raw-tracks recordings.
* Improved system idle detection to avoid stale reconnect retries after 5 minutes of inactivity.
* **Breaking:** If you self-host the call-machine-bundle using `callObjectBundleUrlOverride`, a new separate bundle is now required for Krisp noise cancellation. Contact [help@daily.co](mailto:help@daily.co) for upgrade instructions.
***
## Dashboard
* Added a configurable `max_api_keys` domain property to set the maximum number of API keys allowed per domain.
***
## Media Services
### Telephony
* Fixed video not working with Linphone SIP client.
* Improved STUN server fallback during SDP negotiation retry.
* Fixed hung media workers caused by unresolved SIP transport promises.
* Improved handling of active SIP sessions during meeting moves.
* Broadcast app messages are no longer sent to participants in the knocking (waiting room) state.
* Oldest supported daily-js version bumped to 0.81.0. Versions through 0.83.1 are approaching end-of-support.
### Streaming
* The new VCS pipeline is now the default for new customers. In April, we are transitioning existing customers to the new pipeline; the legacy pipeline will be EOLed later this summer. In the meantime, you can switch between the new and legacy pipelines with the `enable_legacy_compositor` flag.
* Added a layout animation system for VCS (Video Compositing Service) streaming layouts.
* Fixed RTMP URL handling for streaming destinations.
* Improved jitter buffer latency and added video stall detection for RTMP streaming.
### Recording
* Added `event-json` as a valid `dataOutputs` option for recordings via the REST API. We’re considering making `event-json` the default output format and invite feedback from the community. Note that this would add an additional `event-json` file to the existing S3 folder and may break downstream workflows that assume only media files are present.
### REST API
* Added validation for the `cloud-audio-only` room and meeting token property.
* New `max_api_keys` domain property to configure the maximum number of API keys per domain.
DTMF tone support for SIP calls, raw-tracks recording improvements, Krisp SDK lazy loading, and webhook event ID timestamps.
## Overview
February brings DTMF tone support for SIP calls, improved raw-tracks recording reliability during meeting moves, and a Krisp SDK performance optimization that splits noise cancellation into a separate bundle for faster page loads. Audio processor errors no longer mute the microphone, and the 3-hour limitation for raw-tracks recordings has been removed.
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## Daily Prebuilt
* Audio processor error handling updated to no longer mute the microphone on Krisp errors.
* Fixed a mute state sync race condition on the first call of the day.
* Krisp SDK is now loaded as a separate bundle for faster initial page load.
* Added a user-facing notification when the Krisp SDK fails to load.
* Updated noise cancellation overload translations.
***
## Dashboard
* Improved dashboard loading speed.
* Removed references to the deprecated `owner_only_broadcast` property.
***
## Media Services
### Telephony
* Added DTMF (telephone-event) support for sending and receiving DTMF tones during SIP calls.
* Added a setting to keep rooms open without WebRTC participants (for SIP-only scenarios).
* Fixed the call transfer initiated event for SIP REFER.
* Fixed dial-in events to be preserved when no peer is in the room yet.
### Recording
* Removed the 3-hour limitation for raw-tracks recordings.
* Improved raw-tracks recording reliability during meeting moves when the SFU connection changes.
* Added `user_name` and `user_id` to raw-tracks recording events.
* Recording finished webhooks are now reliably sent from the upload finisher for improved delivery.
### Webhooks
* Webhook event IDs now include timestamps, matching the format shown in the documentation.
### Transcription
* Added model parameters to the transcription info field.
### REST API
* Fixed the `/domains/member` endpoint to return all non-revoked API tokens.
Recording dataOutputs for transcripts and chat, cloud-audio-only recording, laptop lid session handling, CPU load detection improvements, and Kamailio call transfer support.
## Overview
January is a feature-rich month with new recording capabilities including `dataOutputs` for recording-synchronized transcripts, chat messages, and event logs, plus a new `cloud-audio-only` recording type. We've also improved session handling for laptop lid closures, refined CPU load detection, and shipped call transfer support on our new telephony infrastructure.
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## daily-js
[View full release notes →](https://github.com/daily-co/daily-js/releases)
### 0.87.0
* Fixed an issue in Chrome where the Compute Pressure API did not work inside an iframe due to permissions policy restrictions.
### 0.86.0
* Introduced a new `dataOutputs` option in `startRecording()` to capture auxiliary data alongside the recording media. Three output types are supported:
* `event-json` — a JSON file describing recording session events (media file starts, track updates, etc.)
* `transcript-webvtt` — a WebVTT file with transcription events, timecode-aligned with the recording media (requires an active live transcription)
* `chat-webvtt` — a WebVTT file with chat messages, timecode-aligned with the recording media
Data output files are included in the recording download link and written to your custom S3 bucket when configured. Note: these outputs capture events, they do not start services.
* Added support for a new `cloud-audio-only` recording type. This produces m4a files with the `audio/mp4` content type. It can be used alongside other recording types and does not share an instance ID with RTMP/HLS streaming.
* Fixed an issue where sessions would attempt to reconnect after long periods of laptop lid closure. Sessions now automatically disconnect after 5 minutes of detected inactivity.
* Fixed uncaught errors in `join()` and `startCamera()` when no room URL is provided or the URL is invalid. These now properly throw an error and leave `meetingState()` in `"left-meeting"`.
* Improved the `cpu-load-change` event by requiring multiple consecutive high CPU readings before reporting high load and by refining global decode time calculation to exclude videos with empty frame metrics.
* Added [compute pressure state](https://developer.mozilla.org/en-US/docs/Web/API/Compute_Pressure_API) to the [`getCpuLoadStats()`](/reference/daily-js/instance-methods/get-cpu-load-stats) API when supported by the browser.
* Added `max_app_message_size` to `DailyRoomInfo` types.
***
## react-native-daily-js
[View full release notes →](https://github.com/daily-co/react-native-daily-js/releases)
### 0.83.0
* Introduced a new `dataOutputs` option in `startRecording()` to capture auxiliary data alongside the recording media. Supports `event-json`, `transcript-webvtt`, and `chat-webvtt` output types.
* Added support for the new `cloud-audio-only` recording type.
* Fixed an issue where sessions would attempt to reconnect after long periods of laptop lid closure.
* Fixed uncaught errors in `join()` and `startCamera()` when no room URL is provided or the URL is invalid.
* Improved the `cpu-load-change` event accuracy.
* Added `max_app_message_size` to `DailyRoomInfo` types.
* Added missing type definitions for streaming and recordings.
***
## Daily Prebuilt
* Removed automatic camera turn-off behavior on bad network conditions.
***
## Dashboard
* Updated Cloud recording storage tooltip.
* Removed HIPAA 30-day trial wording.
***
## Media Services
### Telephony
* Added call transfer support on the new Kamailio-based telephony infrastructure.
* Added support for numeric SIP usernames.
### Recording
* Added server-side support for `dataOutputs` recording option and the `cloud-audio-only` recording type.
* Fixed download link file extensions for recordings stored in custom S3 buckets.
Recording-synchronized transcripts, gapless audio for raw-tracks, CPU warning notifications, and Prebuilt session resume and background effects fixes.
## Overview
December brings recording-synchronized transcripts, a new gapless audio pipeline for raw-tracks recording, and configurable CPU warning notifications in Daily Prebuilt. We've also improved session resume reliability after laptop lid closures and added automatic detection to disable background effects on underpowered hardware.
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## Daily Prebuilt
* Added a new `enable_cpu_warning_notifications` domain and room property to control whether CPU warning notifications are shown to users.
* Background effects are now automatically disabled when a WebGL software renderer is detected, preventing poor performance on underpowered hardware.
* Fixed poor network state handling.
* Fixed session resume issues that could occur after closing and reopening laptop lids.
***
## Dashboard
* Added configuration for the new `enable_cpu_warning_notifications` property.
* Updated settings deletion copy.
***
## Media Services
### Recording
* Added support for recording-synchronized transcripts via `dataOutputs` in `startRecording()`.
* New transcoded gapless audio pipeline for raw-tracks recording, producing continuous audio files without gaps.
* Raw-tracks recording now works with the `force_audio_only_recording` flag.
* Fixed file extension for WAV files in transcoded gapless audio mode.
* Fixed a missing room state update during meeting move restore that could cause recording state inconsistencies.
### Transcription
* Deepgram model improvement program opt-out is now enabled by default for improved data privacy.
SIP codec negotiation, call transfer fixes, recording enhancements, and Prebuilt breakout room and screen sharing fixes.
## Overview
November is a server-focused release with telephony improvements including SIP codec negotiation and call transfer reliability fixes, recording enhancements, and Daily Prebuilt bug fixes for breakout rooms and screen sharing on Chrome.
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## Daily Prebuilt
* Fixed the "request for help" feature from the main room during breakout sessions.
* Improved handling of blocked-by-browser screen share errors in Chrome.
***
## Dashboard
* Removed Intercom chat widget from the dashboard. Contact us at `help@daily.co` for support.
***
## Media Services
### Telephony
* Added support for preferred codec negotiation based on the SIP invite SDP.
* Fixed room ID preservation during call transfers when a room is deleted mid-transfer.
* Fixed SIP username filtering for pinless dial-in configuration.
### Recording
* Fixed stop recording by instance ID to correctly detect the recording type.
* Optimized audio bitrate to 96kbps for audio-only recordings.
* The GET recordings API now includes `roomName` in the response.
### REST API
* Fixed 404 errors for presence queries on deleted rooms.
Narrower CSP for video backgrounds, audio-only recording property, dynamic SIP dial-in endpoints, and telephony and recording fixes.
## Overview
October brings a Content Security Policy improvement for video background processing, removing the need for the broad `unsafe-eval` directive. We've also added a new `force_audio_only_recording` domain property, dynamic SIP dial-in endpoint creation, and several telephony and recording reliability fixes across our platform.
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## daily-js
[View full release notes →](https://github.com/daily-co/daily-js/releases)
### 0.85.0
* You no longer need to specify the broad `unsafe-eval` in your Content Security Policy (CSP) when using video background processing (virtual backgrounds or background blur). You can now use the narrower `wasm-unsafe-eval` instead.
* Fixed an issue where the initial send settings were not being respected for cam video.
***
## react-native-daily-js
[View full release notes →](https://github.com/daily-co/react-native-daily-js/releases)
### 0.82.0
* Fixed an issue where the initial send settings were not being respected for cam video.
***
## Daily Prebuilt
* Added a Krisp system overload notification to inform users when audio processing is under heavy CPU load.
* Fixed recording handling when recording types are configured as comma-separated values.
* Fixed dynamic chunk loading issues that could cause failures in certain deployment configurations.
***
## Dashboard
* Removed Daily Bots dashboard links and unified domain handling.
***
## Media Services
### Telephony
* Added support for dynamically creating SIP dial-in endpoints.
* SIP participants are now properly ejected when a room is deleted.
* Fixed presence data for dial-out participants who are the first to join a room.
* Fixed pagination in the list phone numbers API.
* Fixed error handling in the list available numbers API.
### Recording and Transcription
* Added a new `force_audio_only_recording` domain property for audio-only recording.
* Meeting-move-aware transcription is now enabled by default.
* Fixed Deepgram extra metadata encoding for transcription sessions.
Phone extension support for dial-out, Android 16KB page size compatibility, auto-start recording reliability, and new Picture-in-Picture events.
## Overview
September adds phone extension support for dial-out operations across our client SDKs, Android 16KB page size compatibility for React Native, and improved reliability for auto-start recording and transcription. We've also added new Picture-in-Picture events for Daily Prebuilt and improved handling for unsupported browsers.
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## daily-js
[View full release notes →](https://github.com/daily-co/daily-js/releases)
### 0.84.0
* Added support for calling phone extensions during dial-out operations. You can now specify an extension number and wait time before dialing the extension after the main call connects.
* Added Prebuilt-specific `pip-started` and `pip-stopped` events.
* Improved reliability of handling auto-start recording and transcription options when joining a room.
* Improved handling for unsupported browsers. The Daily constructor will now throw an error of `WebRTC not supported or suppressed` if the browser cannot support a call.
***
## react-native-daily-js
[View full release notes →](https://github.com/daily-co/react-native-daily-js/releases)
### 0.81.0
* Added support for Android 16KB page size.
* Added support for calling phone extensions during dial-out operations. You can now specify an extension number and wait time before dialing the extension after the main call connects.
* Improved reliability of handling auto-start recording and transcription options when joining a room.
***
## Dashboard
* Added a cancel plan button to the billing interface.
Chrome 140 and Firefox 142 compatibility fixes, pre-join screen sharing, Krisp CPU overload handling, telephony improvements, and Prebuilt accessibility updates.
## Overview
August brings browser compatibility fixes for Chrome 140 and Firefox 142, new screen sharing capabilities before joining a call, and telephony improvements including dial-out extensions and cross-domain SIP transfers. We've also shipped Daily Prebuilt accessibility improvements, a high CPU usage notification, and stability fixes across our media services.
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## daily-js
[View full release notes →](https://github.com/daily-co/daily-js/releases)
### 0.83.1
* Updated mediasoup-client for compatibility with Chrome 140. Without this fix, joining or reconnecting to a call without an audio track would fail on Chrome 140.
* Added a workaround for a [Firefox 142 bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1981040) that caused `daily-js` to incorrectly report bad network conditions due to `roundTripTime`.
* Fixed a regression in 0.82.0 where `captureOptions` passed to `startScreenShare()` were ignored.
* Removed deprecated and unused `rtp-tracks` recording support.
### 0.82.0
* Added support for calling `startScreenShare()` prior to `join()`. A call to `preAuth()` or `startCamera()` is still required first to initialize state.
* Fixed and improved error handling for `setOutputDevicesAsync()`. The method now throws an error if the call fails.
* Updated dependencies to resolve security vulnerabilities.
* Bumped Krisp to the latest version with updated models. Added handling for CPU overload which can cause choppy voice output. This will temporarily and silently pause audio processing while the CPU recovers. If overload continues, `daily-js` will emit an [`audio-processor-error`](/reference/daily-js/events/error-events#audio-processor-error) with `errorMsg` of `"Krisp error: system overload"`, turn off the processor, and mute the microphone.
***
## react-native-daily-js
[View full release notes →](https://github.com/daily-co/react-native-daily-js/releases)
### 0.80.0
* Updated mediasoup-client dependency to latest.
* Removed deprecated and unused `rtp-tracks` recording support.
### 0.79.0
* Updated dependencies to resolve security vulnerabilities.
***
## Daily Prebuilt
* Fixed unblock instructions in embedded Prebuilt on Chrome on iOS.
* Added a high CPU usage notification snackbar.
* Improved accessibility throughout the Prebuilt interface.
***
## Media Services
### Telephony
* Added support for providing a phone extension in `startDialout()`.
* Enabled SIP call transfer to non-Daily domains.
* Improved handling of dial-in properties when creating rooms with dial-in configured.
* Added `roomName` to transcription webhook events.
### Recording
* Fixed a bug where audio tracks were not being added to recordings.
New network status callbacks, improved telephony error handling, and platform-wide stability fixes.
## Overview
This month's updates bring new network status callbacks to our native mobile SDKs, giving you more insight into connection health. We've shipped a new `dialin-error` type (`start-failed`) that triggers when SIP registration fails, a critical audio playback fix for Safari in Daily React, and numerous stability improvements across our backend services.
Complete release history for our client SDKs is available in our Github release notes:
* [daily-js](https://github.com/daily-co/daily-js/releases)
* [react-native-daily-js](https://github.com/daily-co/react-native-daily-js/releases)
* [daily-react](https://github.com/daily-co/daily-react/releases)
* [daily-ios](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
* [daily-android](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
* [daily-python](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
***
## daily-js
[View full release notes →](https://github.com/daily-co/daily-js/releases)
### 0.81.0
* Added `ignoreAudioLevel` parameter to `startCustomTrack()` to exclude a track from audio level calculations.
* Improved `enumerateDevices()` logging and reduced noisy error reporting.
***
## react-native-daily-js
[View full release notes →](https://github.com/daily-co/react-native-daily-js/releases)
### 0.78.0
* Added a new `dialin-error` type to `start-failed`.
* Fixed a potential null pointer exception during module initialization.
* Improved `enumerateDevices()` logging and reduced noisy error reporting.
***
## daily-react
[View full release notes →](https://github.com/daily-co/daily-react/releases)
### 0.23.1
* Fixed an issue that could prevent audio playback in Safari after a participant leaves.
* Added an optional `interval` parameter to the `useAudioLevelObserver()` hook.
* Updated the `useNetwork()` hook to return the new `networkState` and `networkStateReasons` properties.
* Added `user_name` and `rawResponse` to the `Transcription` type definition.
***
## daily-android
[View full release notes →](https://github.com/daily-co/daily-client-android/blob/main/CHANGELOG.md)
### 0.32.0
* Added a new `onNetworkConnectionStatusUpdated()` callback to monitor call-critical network connections.
* Added support for handling mid-call session ID changes.
* Fixed a potential null pointer exception during device list changes.
***
## daily-ios
[View full release notes →](https://github.com/daily-co/daily-client-ios/blob/main/CHANGELOG.md)
### 0.32.0
* Added a new delegate function (`networkConnectionStatusUpdated`) to monitor call-critical network connections.
* Added support for handling mid-call session ID changes.
* Fixed a bug where `userID` could be `nil` in the call configuration, even when present in the token.
***
## daily-python
[View full release notes →](https://github.com/daily-co/daily-python/blob/main/CHANGELOG.md)
### 0.19.4
* Added `set_log_level()` and a `log_level` init argument for controlling log verbosity.
***
## Media Services
### Telephony and Recording/Livestreaming
* Added a new `start-failed` error type to the `dialin-error` event. This fires when the SIP address on a room fails SIP registration with the SIP network.
* Improved handling of non-unique 'from' numbers in PSTN dial-in, allowing multiple participants to join from the same caller ID.
* Shipped numerous stability improvements for SIP registration, raw tracks recording, and connection reliability.
## Older updates
5 updates from 2025.
8 updates from 2024.
18 updates from 2023.
16 updates from 2022.
12 updates from 2021.
8 updates from 2020.
# Daily Client SDK for Android
Source: https://docs.daily.co/docs/android/index
Build real-time video and audio calling into your native Android applications.
The Daily Client SDK for Android is a native Kotlin/Java library built on WebRTC. It handles media negotiation, network traversal, and participant management so you can focus on building your UI.
Build a working video call app step by step
Add screen share to your Android app
Full Kotlin/Java API docs
## Hello, world
Add the SDK to your `build.gradle`, then join a call:
```groovy theme={null}
dependencies {
implementation 'co.daily:client:latest.release'
}
```
```kotlin theme={null}
import co.daily.CallClient
import co.daily.CallClientListener
import co.daily.model.Participant
val call = CallClient(applicationContext)
val videoViews = mutableMapOf()
call.addListener(object : CallClientListener {
override fun onParticipantJoined(participant: Participant) {
val videoView = VideoView(applicationContext)
videoViews[participant.id] = videoView
addVideoViewToMyUI(view = videoView)
videoView.track = participant.media?.camera?.track
}
override fun onParticipantUpdated(participant: Participant) {
videoViews[participant.id]?.track = participant.media?.camera?.track
}
})
call.join(url = "https://your-domain.daily.co/room-name") {
it.error?.apply { Log.e(TAG, "Error joining: $msg") }
it.success?.apply { Log.i(TAG, "Joined successfully") }
}
// Turn off camera
call.setInputsEnabled(camera = false)
// Leave and release when done
call.leave { }
call.release()
```
## API structure
The SDK is organized around the tasks involved in building a call. For each task you get methods to **update** state, methods to **get** current state, and **events** via `CallClientListener` to react to changes.
`join()`, `leave()`, `callState()`, `CallStateUpdated`
`participants()`, `ParticipantJoined`, `ParticipantUpdated`, `ParticipantLeft`
`updateInputs()`, `setInputsEnabled()`, `startScreenShare()`, `InputsUpdated`
`updatePublishing()`, `setIsPublishing()`, `PublishingUpdated`
`updateSubscriptions()`, `updateSubscriptionProfiles()`, `setSubscriptionState()`
`activeSpeaker()`, `ActiveSpeakerChanged`
## Resources
A complete working example on GitHub
Production-ready boilerplate from Daily's engineering team
## Requirements
* minSdkVersion >= 23 (Android 6.0)
* Kotlin 1.6 or later recommended
# Installing the Daily Client SDK for Android
Source: https://docs.daily.co/docs/android/installation
Learn how to get set up with the Daily Client SDK for Android.
## Minimum SDK version
The Daily Client SDK for Android requires a `minSdkVersion` of 21 or greater.
## Installing using Maven
In your top-level `build.gradle` file, add the Maven Central repository:
```groovy theme={null}
repositories {
// ...
mavenCentral()
}
```
In your app’s `build.gradle` file, add the Daily Client SDK dependency:
```groovy theme={null}
dependencies {
// ...
implementation 'co.daily:client:0.39.1'
}
```
Optionally, to use the camera video processor (for background blur and replacement), also add the following dependency:
```groovy theme={null}
dependencies {
// ...
implementation 'co.daily:client-videoprocessor-plugin:0.1.1'
}
```
## App setup
Make sure the following permissions are in your app’s `AndroidManifest.xml`:
```xml theme={null}
```
> The `foregroundServiceType` `phoneCall`, `camera` and `microphone` are needed in order to give your app the ability to continue running calls while in the background
> The `foregroundServiceType` `mediaProjection` is only needed if you wish to do screen sharing.
## Continuing calls in the background
In order to give your app the ability to continue running calls while in the background, you can start a foreground service that shows an in-call notification while your call is active.
You can read more about foreground services in the [Android documentation](https://developer.android.com/guide/components/foreground-services).
For an example of a foreground service that customizes and shows a notification, see [the one that is bundled with react-native-daily-js](https://github.com/daily-co/react-native-daily-js/blob/main/android/src/main/java/com/daily/reactlibrary/DailyOngoingMeetingForegroundService.java).
***
To learn more about building an app with the Daily Client SDK for Android, see our [Android Overview](/docs/android) and [Android demo app](https://github.com/daily-demos/daily-android-demo).
# Daily Android Mobile SDK Kotlin Quickstart
Source: https://docs.daily.co/docs/android/quickstart
Learn how to get started using the Daily Android Mobile SDK with Kotlin to create a video mobile application
In this quickstart, we will introduce you to [Daily's Client SDK for Android](/docs/android) by walking through the creation of a simple video call application. By the end of this walkthrough, you'll have a starting point for writing Daily-powered video apps for Android with Kotlin.
This walkthrough will implement the following features:
* Creating and joining a public Daily room
* Asking for required application permissions
* Displaying videos from local and remote room participants
* Managing local microphone and camera input
* Leaving the call
You can find the full codebase of this Android app [on GitHub](http://github.com/daily-demos/quickstart-android).
## Prerequisites
Before you get started, make sure you have a functioning Android development environment including [Android Studio](https://developer.android.com/studio). You will also need a [free Daily account](https://www.daily.co/signup).
If you plan to test your app on a hardware device, make sure you have [debugging enabled on the device](https://developer.android.com/studio/debug/dev-options).
If you plan to test your app on an emulator, make sure you [have a virtual device created](https://developer.android.com/studio/run/managing-avds). Note that by default, the emulator will use an emulated camera.
## Create a Daily room
Begin by navigating to Daily's developer dashboard and [creating a new Daily room](https://dashboard.daily.co/rooms/create).
Give your room a name and click the "Create room" button. All other options can be left at their defaults.
Make note of your Daily room URL. We'll be using it in the code shortly.
## Create a new Android project
Next, open Android Studio. From the Welcome screen, create a new project using the "Empty Views Activity" template.
Give your project a name and make sure the project language is set to Kotlin. Next, click the "Finish" button to have Android Studio set up your new project.
Note that if this is your first Kotlin project setup, it can take a few minutes for Android Studio to download relevant dependencies and initialize the project for the first time.
## Add a dependency on Daily's Client SDK for Android
With your new project created, you can add the Daily's Android SDK as a dependency. Android Studio uses [Gradle](https://gradle.org/) as its default build tool and dependency manager. Open the project's Gradle build script in the app directory:
Once open, add `'co.daily:client:0.8.0'` to the dependencies object:
```kotlin theme={null}
dependencies {
implementation 'co.daily:client:0.8.0'
//...
}
```
The latest release of Daily's Client SDK for Android is 0.8.0 at
the time of this publication. When developing your production application, we
recommend referencing the
latest stable version
.
Save the Gradle file and then sync the changes by using the `Sync Project with Gradle Files` command in the Android Studio File menu.
## Import namespaces and classes
After adding a dependency on Daily's Android SDK, we can import relevant classes. Open `app/java/com.example.[YOUR_APP_NAME]/MainActivity.kt` and add the following `import` statements:
```kotlin theme={null}
// ...Existing imports above...
```
## Setting up the Main Activity
The next step is modifying the `MainActivity` class to set up the basic structure of our application.
Start by adding the `TAG` member variable and two functions:
* `initializeCallClient()`
* `checkPermissions()`
Then, add a call to `checkPermissions()` from the `onCreate()` function.
```kotlin theme={null}
class MainActivity : AppCompatActivity() {
private val TAG: String = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
checkPermissions()
}
private fun initializeCallClient() {
// Initialize the Daily Call Client object once permissions have been granted
}
private fun checkPermissions() {
// Check permissions have been granted and if not, ask for permissions
}
}
```
Build the application to verify that there are not errors or warnings.
## Configure application permissions
The application will need a number of user permissions in order to access the internet, use the device camera, and record and play audio. To request these permissions, we have to declare what we need as part of our app manifest.
Open `manifests/AndroidManifest.xml`. Then, add the following `uses-permission` and `uses-feature` elements inside the `` tag:
```xml theme={null}
```
Modifying the app manifest tells Android which permissions the app *intends* to use. However, we still need to request these permissions from the user. To do so, we'll add some additional code to `MainActivity.kt`, which uses Android's built-in tools for creating [runtime permission requests](https://developer.android.com/training/permissions/requesting).
First, create a member variable named `requestPermissionLauncher` and use it to register an activity using the `RequestMultiplePermissions` [contract](https://developer.android.com/reference/androidx/activity/result/contract/ActivityResultContracts):
```kotlin theme={null}
private val TAG: String = "MainActivity"
private val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result ->
if (result.values.any { !it }) {
checkPermissions()
} else {
// Permission is granted, we can initialize the call
initializeCallClient()
}
}
```
The activity `RequestMultiplePermissions` takes an array of permissions the application would like to request.
In the activity callback, we check to see if additional permissions are needed. If so, we run `checkPermissions()`. If not, the application can call `initializeCallClient()` to begin setting up the video call.
Next, implement the `checkPermissions()` method you defined within the `MainActivity` class as follows:
```kotlin theme={null}
private fun checkPermissions() {
// Check whether permissions have been granted.
// If not, ask for permissions
val appContext: Context = applicationContext
val permissionList: Array = appContext.packageManager.getPackageInfo(
appContext.packageName,
PackageManager.GET_PERMISSIONS
).requestedPermissions
val notGrantedPermissions:MutableList = ArrayList()
for(permission in permissionList) {
if (ContextCompat.checkSelfPermission(appContext, permission)
!= PackageManager.PERMISSION_GRANTED) {
notGrantedPermissions.add(permission)
}
}
if (notGrantedPermissions.isNotEmpty()) {
requestPermissionLauncher.launch(notGrantedPermissions.toTypedArray())
} else {
// Permission is granted, we can initialize the call
initializeCallClient()
}
}
```
The `checkPermissions()` method above gets the list of permissions the application needs from the app manifest and checks whether they have already been granted.
If all of permissions have been granted, the application begins initializing the Daily `CallClient` object by calling the `initializeCallClient()` method.
If the application requires additional permissions from the user, it launches the built-in request flow.
For this quickstart we're not handling conditions where the user declines
permissions, but in a real application you would want to do that.
## Define the user interface
After implementing permission handling, we can define the user interface for our application. The user interface will include the following:
* Displaying participants' video
* Presenting call controls for toggling the camera/microphone and leaving the meeting
To implement the above, we'll create two main UI elements:
* A main UI that contains call controls and a participant list
* A wrapper around the Daily [`VideoView`](https://reference-android.daily.co/daily-android/co.daily.view/-video-view/index.html) that holds each participant's video
Open the `/res/layout/activity_main.xml` layout file and switch to Code view:
Replace the default UI XML with the following:
```xml theme={null}
```
The XML above creates two `ToggleButton`s for controlling the camera and microphone, a single `Button` to leave the call, and a `LinearLayout` to contain participant videos.
Next, we need a wrapper for `VideoView`. In `/res/layout`, create a new Android Resource file named `participant_view.xml`. Replace the default UI XML with the following:
```xml theme={null}
```
Before you build and run the application, verify that you've created a device
emulator or that your physical device is set up for debugging.
Build and run the application by clicking the "Play" button in the debug toolbar at the top of the Android Studio IDE window:
The application should prompt you for permissions and, once granted, display the basic interface you created.
You won't see any video just yet because we haven't set up the call client or joined a Daily room. We'll do that next.
## Create the call client
Now that the basics of the application are in place, we can implement functionality to join a call and display participant videos.
The [`CallClient`](https://reference-android.daily.co/daily-android/co.daily/-call-client/index.html) is the main interface into your Daily video call. It should be instantiated and retained for at least the duration of the video call session.
Open `MainActivity.kt` and locate the `initializeCallClient()` method. Within it, create an instance of `CallClient` followed by a map of `VideoView` objects:
```kotlin theme={null}
private fun initializeCallClient() {
// Create call client
val call = CallClient(applicationContext)
// Create map of video views
val videoViews = mutableMapOf()
}
```
Next, set up relevant event listeners within `initializeCallClient()`. Start by retrieving the participant layout view within this method:
```kotlin theme={null}
private fun initializeCallClient() {
//...Call client and video view map creation logic above...
val layout = findViewById(R.id.videoLinearLayout)
}
```
Then, add the relevant `CallClient` event listeners. These events are raised in response to actions like meeting participants joining, leaving, or being updated:
```kotlin theme={null}
private fun initializeCallClient() {
//...Call client and video view map creation logic above...
val layout = findViewById(R.id.videoLinearLayout)
// Listen for events
call.addListener(object : CallClientListener {
// Handle a remote participant joining
override fun onParticipantJoined(participant: Participant) {
val participantView = layoutInflater.inflate(R.layout.participant_view, layout, false)
val videoView = participantView.findViewById(R.id.participant_video)
videoView.track = participant.media?.camera?.track
videoViews[participant.id] = videoView
layout.addView(participantView)
}
// Handle a participant updating (e.g. their tracks changing)
override fun onParticipantUpdated(participant: Participant) {
val videoView = videoViews[participant.id]
videoView?.track = participant.media?.camera?.track
}
})
}
```
For each participant who joins, we create an instance of the `VideoView` UI element. The `VideoView` instance has its track set to the joining participant's available video track.
If a participant is updated (for example, by turning off their camera), we update that participant's `VideoView` accordingly.
## Join a call
Now that our application has a `CallClient` instance and can react to meeting participant events, we're ready to join a room. To do this, call the `join()` function and pass in the URL of the Daily room you created at the start of this tutorial.
```kotlin theme={null}
private fun initializeCallClient() {
//...Logic we added in prior steps above...
// Join the call
call.join(url = "[YOUR_DAILY_ROOM_URL]") {
it.error?.apply {
Log.e(TAG, "Got error while joining call: $msg")
}
it.success?.apply {
Log.i(TAG, "Successfully joined call.")
}
}
}
```
Replace `"[YOUR_DAILY_ROOM_URL]"` with th URL of your room. You can find the room URL in your [Daily developer dashboard](https://dashboard.daily.co/rooms).
Go ahead and run the application again. Once you have successully joined the meeting, if you are running on actual hardware, you should see your Android device's camera video being shown as a participant in the application. If you are using the Android emulator, you should see an emulated camera.
To test the app with a remote participant, open the room URL in your browser on any device. Once you've joined via the browser, the new participant's video should appear in the app view on your Android device or emulator.
## Toggling microphone and camera states
Now that we have participant video being displayed in the app, we can implement call controls.
We'll begin by checking the initial state of the local participant's microphone and camera and reflect it in the call control UI.
To do so, initialize the toggle button member variables within the `MainActivity` class definition:
```kotlin theme={null}
private val TAG: String = "MainActivity"
private lateinit var toggleCamera: ToggleButton
private lateinit var toggleMicrophone: ToggleButton
```
Next, modify `onCreate()` to find the toggle buttons within the application layout:
```kotlin theme={null}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
toggleCamera = findViewById(R.id.toggleCamera)
toggleMicrophone = findViewById(R.id.toggleMicrophone)
checkPermissions()
}
```
In the `join()` callback we defined earlier, check the `inputs()` function to get current camera and microphone states:
```kotlin theme={null}
// Join the call
call.join(url = "[YOUR_DAILY_ROOM_URL]") {
it.error?.apply {
Log.e(TAG, "Got error while joining call: $msg")
}
it.success?.apply {
Log.i(TAG, "Successfully joined call.")
toggleCamera.isChecked = call.inputs().camera.isEnabled
toggleMicrophone.isChecked = call.inputs().microphone.isEnabled
}
}
```
Next, we'll react to changes in the local device state by overriding the `onInputsUpdated()` event handler within the call client listener:
```kotlin theme={null}
call.addListener(object : CallClientListener {
// ...Previously-defined handlers above...
// Handle local input settings being updated (e.g., the camera being disabled or enabled)
override fun onInputsUpdated(inputSettings: InputSettings) {
toggleCamera.isChecked = inputSettings.camera.isEnabled
toggleMicrophone.isChecked = inputSettings.microphone.isEnabled
}
}
```
Finally, let's allow the end user to toggle their input device state. We'll do so using the [`setInputEnabled()`](https://reference-android.daily.co/daily-android/co.daily/-call-client/set-input-enabled.html) call client instance method. This method will be defined within `initializeCallClient()` and invoked when the microphone and camera button states change:
```kotlin theme={null}
private fun initializeCallClient() {
//...Previously-defined logic above...
toggleMicrophone.setOnCheckedChangeListener { _, isChecked ->
Log.d("BUTTONS", "User tapped the Mute button")
call.setInputEnabled(OutboundMediaType.Microphone, isChecked)
}
toggleCamera.setOnCheckedChangeListener { _, isChecked ->
Log.d("BUTTONS", "User tapped the Cam button")
call.setInputEnabled(OutboundMediaType.Camera, isChecked)
}
}
```
## Leaving a call
Now that we're done with the video handling and device toggling functionality, we'll implement a final critical feature: leaving the call.
The application user should be able to disconnect from the Daily room by tapping the Leave button. This action invokes the call client's [`leave()`](https://reference-android.daily.co/daily-android/co.daily/-call-client/leave.html) method. Add the following code within `initializeCallClient()`:
```kotlin theme={null}
private fun initializeCallClient() {
//...Previously-defined logic above...
findViewById