<!--
{
  "availability" : [
    "iOS: 27.0.0 -",
    "iOSAppExtension: 27.0.0 -",
    "iPadOS: 27.0.0 -",
    "macCatalyst: 27.0.0 -"
  ],
  "documentType" : "symbol",
  "framework" : "NowPlaying",
  "identifier" : "/documentation/NowPlaying/RemoteMediaSessionRepresentable",
  "metadataVersion" : "0.1.0",
  "role" : "Protocol",
  "symbol" : {
    "kind" : "Protocol",
    "modules" : [
      "Now Playing"
    ],
    "preciseIdentifier" : "s:10NowPlaying31RemoteMediaSessionRepresentableP"
  },
  "title" : "RemoteMediaSessionRepresentable"
}
-->

# RemoteMediaSessionRepresentable

A session that plays remotely, potentially across multiple devices.

```
@MainActor protocol RemoteMediaSessionRepresentable : Identifiable
```

## Overview

Conform to this protocol to represent playback happening outside of the current device.
This object is expected to interact with a remote device, and thus may require some
form of remote connection that you set up on initialization.

Your session provides metadata and supported commands, as well as the list of devices playing
in this session. It also handles volume changes and commands targeting the remote session.

> Important: The system may request updates about this session via ``doc://com.apple.nowplaying/documentation/NowPlaying/RemoteMediaSessionRepresentable/update(_:)``,
> where an instance of a `Codable` type your app defines passes into the function.
> Your implementation uses the passed ``doc://com.apple.nowplaying/documentation/NowPlaying/RemoteMediaSessionRepresentable/Attributes`` instance to update the model objects
> from your session, which informs the system of any metadata or command changes.

Your app donates remote sessions to the system in two ways: from the main app, or through push notifications.

See [`RemoteMediaSession`](/documentation/NowPlaying/RemoteMediaSession) for the in-app API to donate a remote session.

To start, update, or end remote sessions using push notifications, see: [Publishing remote media sessions](/documentation/NowPlaying/publishing-remote-media-sessions)

The following example shows a basic implementation:

```swift
// A struct representing the current playback information from a remote device.
struct PlayerSnapshot: Codable {
  let trackId: String
  let title: String
  let artist: String
  let album: String
  let duration: Double
  let elapsedTime: Double
  let timestamp: Date
  let isPlaying: Bool
  let playingDevices: [PlayingDevice]
}

struct PlayingDevice: Codable {
  let id: String
  let name: String
  let volume: Float
}

@Observable
class RemotePlayerModel {
    var server: ServerConnection
    var snapshot: PlayerSnapshot
}

class MySession: RemoteMediaSessionRepresentable {
    struct Attributes: RemoteMediaSessionAttributes {
        let id: String
        var snapshot: PlayerSnapshot
    }

    let id: String
    var remotePlayer: RemotePlayerModel

    var devices: [MediaDevice] {
        remotePlayer.snapshot.playingDevices.map { device in
            MediaDevice(
                id: device.id,
                name: device.name,
                type: .speaker,
                capabilities: [
                    .absoluteVolume(device.volume) { newLevel in
                        // Communicate with an external server to issue the volume change
                        try await remotePlayer.server.setVolume(newLevel, forDevice: device.id)
                    }
                ]
            )
        }
    }

    var content: (any MediaContentRepresentable)? {
        let snapshot = remotePlayer.snapshot
        return MusicContent(
            id: snapshot.trackId,
            songTitle: snapshot.title,
            artistName: snapshot.artist,
            albumName: snapshot.album,
            type: .audio,
            duration: .finite(snapshot.duration),
            artwork: Artwork(id: snapshot.trackId) { size in
                let data = await remotePlayer.server.loadArtworkData(for: snapshot.trackId, size: size)
                return try ArtworkRepresentation(data: data)
            }
        )
    }

    var playbackSnapshot: MediaPlaybackSnapshot {
        let snapshot = remotePlayer.snapshot
        if snapshot.isPlaying {
            return MediaPlaybackSnapshot(
                state: .playing(rate: 1.0),
                elapsedTime: snapshot.elapsedTime,
                timestamp: snapshot.timestamp
            )
        } else {
            return MediaPlaybackSnapshot(
                state: .paused,
                elapsedTime: snapshot.elapsedTime,
                timestamp: snapshot.timestamp
            )
        }
    }

    var commands: [MediaCommand] {[
        .play {
          // Communicate with an external server to issue the command
          try await remotePlayer.server.play()
        },
        .pause {
          try await remotePlayer.server.pause()
        },
        // … more supported commands …
    ]}

    func update(_ attributes: Attributes) {
      // Incorporate the incoming attributes into your existing model
      remotePlayer.update(with: attributes)
    }
    // …
}
```

## Topics

### Associated Types

[`associatedtype Attributes : RemoteMediaSessionAttributes`](/documentation/NowPlaying/RemoteMediaSessionRepresentable/Attributes)

A `Codable` type you define to identify this session and carry its remote state.

### Instance Properties

[`var commands: [MediaCommand]`](/documentation/NowPlaying/RemoteMediaSessionRepresentable/commands)

The commands supported by this session.

[`var content: (any MediaContentRepresentable)?`](/documentation/NowPlaying/RemoteMediaSessionRepresentable/content)

The content being played in this session.

[`var devices: [MediaDevice]`](/documentation/NowPlaying/RemoteMediaSessionRepresentable/devices)

The devices currently playing as part of this session.

[`var id: String`](/documentation/NowPlaying/RemoteMediaSessionRepresentable/id)

The unique identifier for this session.

[`var playbackSnapshot: MediaPlaybackSnapshot?`](/documentation/NowPlaying/RemoteMediaSessionRepresentable/playbackSnapshot)

The current playback state of this session.

[`var pushToken: Data?`](/documentation/NowPlaying/RemoteMediaSessionRepresentable/pushToken)

The token you use to send push notifications to update this remote session.

[`var pushTokenUpdates: AsyncStream<Data>`](/documentation/NowPlaying/RemoteMediaSessionRepresentable/pushTokenUpdates)

An asynchronous sequence you use to observe changes to the push token of this remote session.

### Instance Methods

[`func update(Self.Attributes)`](/documentation/NowPlaying/RemoteMediaSessionRepresentable/update(_:))

Updates the session state from new attributes.

## Relationships

### Inherits From

[`Identifiable`](/documentation/Swift/Identifiable)

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)