client-sdk-js icon indicating copy to clipboard operation
client-sdk-js copied to clipboard

Safari background audio

Open vostack13 opened this issue 1 month ago • 2 comments

Select which package(s) are affected

@livekit/components-react

Describe the bug

Hi LiveKit team đź‘‹

I’ve run into an issue specific to Safari (both desktop and iOS) when rendering each participant’s audio track in a separate

When the LiveKit room is active in the background (e.g. the tab is not focused), new participants’ audio tracks are not audible until the user returns to the tab. Existing audio tracks continue to play fine, but any new audio elements created while the page is in the background remain muted/suspended by Safari’s autoplay policy.

This happens even if:

  • The user has already interacted with the page (e.g. clicked “Join room”).
  • The existing audio elements are already playing successfully.
  • Each new

Reproduction

const tracks = useTracks([
    Track.Source.Microphone,
    Track.Source.ScreenShareAudio,
    Track.Source.Unknown,
  ]).filter((ref) => !isLocal(ref.participant) && ref.publication.kind === Track.Kind.Audio);

  return (
    <div style={{ display: 'none' }}>
      {tracks.map((trackRef) => (
        <AudioTrack
          key={getTrackReferenceId(trackRef)}
          trackRef={trackRef}
          volume={volume}
          muted={muted}
        />
      ))}
    </div>
  );

Logs


System Info

LiveKit packages:
- @livekit/components-react: 2.9.15
- @livekit/components-styles: 1.1.6
- livekit-client: 2.15.14
Safari version: 17.x
Platform: macOS

Severity

serious, but I can work around it

Additional Information

Is there any recommended workaround or LiveKit-specific API pattern to handle this Safari behavior? For example:

  • Using a single shared
  • Combining remote tracks into one MediaStream?
  • Managing playback through AudioContext instead of

Any suggestions or best practices for reliable background audio playback in Safari would be greatly appreciated 🙏

vostack13 avatar Nov 12 '25 07:11 vostack13

Thanks for the report!

We are (painfully) aware of this issue, but haven't found a suitable workaround so far.

  • Combining all audio tracks in the same audio element would render any volume controls that we have useless.
  • Piping audio through AudioContext creates its own set of auto play issues on Safari unfortunately.

lukasIO avatar Nov 17 '25 09:11 lukasIO

As @lukasIO mentioned, the code already accounts for that Safari bug, and it’s something quite difficult to fix at the framework level: https://github.com/livekit/client-sdk-js/blob/main/src/room/track/Track.ts#L402

At the application layer, you could listen for any captured errors related to NotAllowedError. If that happens, you may require the user to interact (e.g. a button, a blurred overlay?) and then trigger a re-render of the component.

It’s not the ideal solution, but it might still work for you.

itamayo avatar Nov 27 '25 17:11 itamayo