ID
NewiOSpublic typealias ID = StringA type representing the stable identity of the entity associated with an instance.
What's New / Media, Audio & Capture
MediaDevice is the framework for building media output device extensions. The API centers on MediaOutputDevice and the MediaDeviceExtension protocol family, covering device capabilities, volume control, authorization, and realtime sample handling.
The 27 SDK adds 22 APIs with no deprecations or removals. New types include the MediaDeviceExtension and MediaDeviceExtensionConfiguration protocols, the MediaOutputDevice struct, and a MediaDeviceError struct with a nested Code. MediaOutputDevice gains nested members for Capabilities (with ArrayLiteralElement, Element, and RawValue), DeviceType, VolumeControl, AuthorizationMethod, and CodeLength, plus a RealtimeSampleHandling protocol.
IDpublic typealias ID = StringA type representing the stable identity of the entity associated with an instance.
MediaDeviceErrorpublic struct MediaDeviceError : LocalizedError, SendableAn error returned by MediaDeviceExtension operations.
public struct MediaDeviceError : LocalizedError, Sendable {
/// Error codes for media device operations.
public enum Code : Sendable {
/// Discovery of media devices failed.
case discoveryFailed
/// Connection to the device failed.
case connectionFailed
/// Device is in use by another session.
case deviceInUse
/// Authorization to use the device failed.
case authorizationFailed
/// The session failed on the device.
case sessionFailed
/// Returns a Boolean value indicating whether two values are equal.
///
/// Equality is the inverse of inequality. For any values `a` and `b`,
/// `a == b` implies that `a != b` is `false`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func == (a: MediaDeviceError.Code, b: MediaDeviceError.Code) -> Bool
/// Hashes the essential components of this value by feeding them into the
/// given hasher.
///
/// Implement this method to conform to the `Hashable` protocol. The
/// components used for hashing must be the same as the components compared
/// in your type's `==` operator implementation. Call `hasher.combine(_:)`
/// with each of these components.
///
/// - Important: In your implementation of `hash(into:)`,
/// don't call `finalize()` on the `hasher` instance provided,
/// or replace it with a different instance.
/// Doing so may become a compile-time error in the future.
///
/// - Parameter hasher: The hasher to use when combining the components
/// of this instance.
public func hash(into hasher: inout Hasher)
/// The hash value.
///
/// Hash values are not guaranteed to be equal across different executions of
/// your program. Do not save hash values to use during a future execution.
///
/// - Important: `hashValue` is deprecated as a `Hashable` requirement. To
/// conform to `Hashable`, implement the `hash(into:)` requirement instead.
/// The compiler provides an implementation for `hashValue` for you.
public var hashValue: Int { get }
}
/// The error code for this error.
public let code: MediaDeviceError.Code
/// Creates an error with the specified error code.
///
/// - Parameter code: The error code for this error.
public init(_ code: MediaDeviceError.Code)
/// A localized description of the error.
public var errorDescription: String? { get }
/// A localized explanation of the reason for the error.
public var failureReason: String? { get }
/// A localized suggestion for how to recover from the error.
public var recoverySuggestion: String? { get }
/// A localized help anchor for the error.
public var helpAnchor: String? { get }
}MediaDeviceError.Codeextension MediaDeviceError.Code : Equatableextension MediaDeviceError.Code : Equatable {
}MediaDeviceError.Codeextension MediaDeviceError.Code : Hashableextension MediaDeviceError.Code : Hashable {
}MediaDeviceExtensionpublic protocol MediaDeviceExtension : AppExtensionA protocol that defines the requirements of a media device extension that discovers, activates, and plays media on a remote device.
The extension requires the com.apple.developer.media-device-extension entitlement. As part of this entitlement an ID for your protocol needs to be specified. This same identifier must also be declared in the extension's Info.plist as the UTTypeIdentifier. If the identifier in the entitlement and Info.plist do not match, the extension will not be run. This ID value can be used by other apps that use the AVSystemRouting framework and which intend to make use of an extension of this type.
The display name of the extension is sourced from the value of the UTTypeDescription key in the extension's Info.plist. It may be presented in user interfaces.
@MainActor public protocol MediaDeviceExtension : AppExtension {
/// The communication protocol that this extension implements.
///
/// ## Declaring the Protocol Type
///
/// Declare a custom Uniform Type Identifier in your extension's Info.plist using
/// `UTExportedTypeDeclarations`. The type must conform to `public.media-sharing-protocol`:
///
/// ```xml
/// <key>UTExportedTypeDeclarations</key>
/// <array>
/// <dict>
/// <key>UTTypeIdentifier</key>
/// <string>com.example.sharingprotocol</string>
/// <key>UTTypeDescription</key>
/// <string>My Sharing Protocol</string>
/// <key>UTTypeConformsTo</key>
/// <array>
/// <string>public.media-sharing-protocol</string>
/// </array>
/// <key>UTTypeIcons</key>
/// <dict>
/// <key>UTTypeSymbolName</key>
/// <string>sharingprotocol.logo</string>
/// </dict>
/// </dict>
/// </array>
/// ```
///
/// - `UTTypeIdentifier`: A reverse-DNS string that uniquely identifies your protocol. Media
/// apps receive this value through ``AVSystemRoute/protocolType`` and use it to determine
/// which protocol is active.
/// - `UTTypeDescription`: A human-readable name for the protocol. The system may display this
/// in user interfaces such as the route picker.
/// - `UTTypeConformsTo`: Must include `public.media-sharing-protocol`.
///
/// ## Returning the Type
///
/// Return a `UTType` whose identifier matches the `UTTypeIdentifier` declared in Info.plist:
///
/// ```swift
/// var protocolType: UTType {
/// UTType("com.example.sharingprotocol")!
/// }
/// ```
@MainActor var protocolType: UTType { get }
/// Indicates whether the extension supports handling simultaneous media sessions via `MediaOutputSession`.
///
/// When `true`, the extension can receive multiple active ``MediaOutputSession`` instances at once.
/// When `false`, only one session is active at a time.
@MainActor var supportsSimultaneousSessions: Bool { get }
/// Called when a user action requires discovered devices to be displayed.
///
/// Use the `Network`, `WiFiAware`, or `CoreBluetooth` frameworks for service discovery.
/// As devices are found, report them to the system by calling
/// ``MediaDeviceRoutingManager/foundDevice(_:)`` on the routing manager. When a previously
/// discovered device is no longer available, call ``MediaDeviceRoutingManager/lostDevice(_:)``.
/// If discovery fails unexpectedly, call ``MediaDeviceRoutingManager/discoveryFailed(_:)``.
@MainActor func startDeviceDiscovery()
/// Called when the user dismisses the UI element that is showing devices.
///
/// Stop any active network discovery operations started in ``startDeviceDiscovery()``.
@MainActor func stopDeviceDiscovery()
/// Called when the user activates a device via a user interface.
///
/// If the device requires additional user authentication, call ``MediaDeviceRoutingManager/requestPairingCode(for:session:reason:authorizationMethod:)``.
/// The system will report user input via ``MediaDeviceExtension/connectUsingPairingCode(_:to:session:)``.
///
/// If the authorization fails, or the connection to the device fails, call ``MediaDeviceRoutingManager/failedToActivateDevice(_:session:error:)``.
///
/// If the activation is successful, call ``MediaDeviceRoutingManager/activatedDevice(_:session:)``.
///
/// ## Grouping
///
/// If the extension receives multiple activations, then the associated ``MediaOutputDevice`` instances should be grouped together.Truncated.
MediaDeviceExtensionextension MediaDeviceExtensionextension MediaDeviceExtension {
@MainActor public var configuration: some MediaDeviceExtensionConfiguration { get }
}MediaDeviceExtensionConfigurationpublic protocol MediaDeviceExtensionConfiguration : AppExtensionConfigurationConfiguration for the app extension.
public protocol MediaDeviceExtensionConfiguration : AppExtensionConfiguration {
}MediaOutputDevicepublic struct MediaOutputDevice : CustomStringConvertible, Hashable, Identifiable, SendableRepresents a discoverable media output device such as a TV, speaker, or streaming stick.
public struct MediaOutputDevice : CustomStringConvertible, Hashable, Identifiable, Sendable {
/// Specifies what kind of authorization UI to present when connecting to a device.
///
/// Use the provided factory methods to create an authorization method appropriate for
/// your device's pairing requirements.
@available(iOS 27.0, *)
@available(macCatalyst, unavailable)
@available(visionOS, unavailable)
public struct AuthorizationMethod : Equatable, Sendable {
/// Represents the valid lengths for an authorization code.
///
/// Use one of the provided static properties to specify the length
/// of an authorization code.
@available(iOS 27.0, *)
@available(macCatalyst, unavailable)
@available(visionOS, unavailable)
public struct CodeLength : Equatable, Sendable {
/// A 4-character code.
public static let fourCharacter: MediaOutputDevice.AuthorizationMethod.CodeLength
/// A 6-character code.
public static let sixCharacter: MediaOutputDevice.AuthorizationMethod.CodeLength
/// Returns a Boolean value indicating whether two values are equal.
///
/// Equality is the inverse of inequality. For any values `a` and `b`,
/// `a == b` implies that `a != b` is `false`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func == (a: MediaOutputDevice.AuthorizationMethod.CodeLength, b: MediaOutputDevice.AuthorizationMethod.CodeLength) -> Bool
}
/// No authorization is required.
public static var none: MediaOutputDevice.AuthorizationMethod { get }
/// Creates a numeric PIN entry authorization method.
///
/// The system presents a UI with individual digit fields for the user to enter
/// a numeric code when connecting to the device.
///
/// - Parameter length: The number of digit fields presented in the pairing UI.
///
/// ```swift
/// // Present a 4-digit PIN entry UI
/// let auth = AuthorizationMethod.numericCode(length: .fourCharacter)
/// ```
public static func numericCode(length: MediaOutputDevice.AuthorizationMethod.CodeLength) -> MediaOutputDevice.AuthorizationMethod
/// Presents a freeform text password input for device authorization.
public static var password: MediaOutputDevice.AuthorizationMethod { get }
/// Returns a Boolean value indicating whether two values are equal.
///
/// Equality is the inverse of inequality. For any values `a` and `b`,
/// `a == b` implies that `a != b` is `false`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func == (a: MediaOutputDevice.AuthorizationMethod, b: MediaOutputDevice.AuthorizationMethod) -> Bool
}
/// A device type used for display in user interfaces.
@available(iOS 27.0, *)
@available(macCatalyst, unavailable)
@available(visionOS, unavailable)
public enum DeviceType : Sendable {
/// A hi-fi speaker.
case hifiSpeaker
/// A television.
case tv
/// A streaming media stick.Truncated.
MediaOutputDevice.DeviceTypeextension MediaOutputDevice.DeviceType : Equatableextension MediaOutputDevice.DeviceType : Equatable {
}MediaOutputDevice.DeviceTypeextension MediaOutputDevice.DeviceType : Hashableextension MediaOutputDevice.DeviceType : Hashable {
}MediaOutputDevice.VolumeControlextension MediaOutputDevice.VolumeControl : Equatableextension MediaOutputDevice.VolumeControl : Equatable {
}MediaOutputDevice.VolumeControlextension MediaOutputDevice.VolumeControl : Hashableextension MediaOutputDevice.VolumeControl : Hashable {
}RealtimeSampleHandlingpublic protocol RealtimeSampleHandling : MediaDeviceExtensionA protocol that extends a media device extension to support realtime sample delivery.
## Realtime Video Processing Use ScreenCaptureKit to receive system video samples, then use VideoToolbox for video sample encoding.
1. Provide an implementation of startRealtimeSampleDelivery(session:). 2. Set up ScreenCaptureKit for a media device extension:
let picker = SCContentSharingPicker.shared()
picker.addObserver(self)
picker.active = true3. Receive an SCContentFilter from the SCContentSharingPicker observer. 4. Create an SCStream. Call addStreamOutput(_:type:sampleHandlerQueue:), and start with startCapture(). 5. Receive and process real time screen samples via the SCStreamOutput protocol.
## Realtime Audio Processing Use AudioServerDriver to receive system audio samples, then use AudioToolbox for audio sample encoding.
@MainActor public protocol RealtimeSampleHandling : MediaDeviceExtension {
/// Called when the extension can receive realtime samples.
/// - Parameter session: The session associated with the sample delivery.
@MainActor func startRealtimeSampleDelivery(session: MediaOutputSession)
/// Called when the extension should stop realtime sample delivery.
/// - Parameter session: The session to stop delivering samples for.
@MainActor func stopRealtimeSampleDelivery(session: MediaOutputSession)
}MediaOutputDevice.AuthorizationMethodpublic struct AuthorizationMethod : Equatable, SendableSpecifies what kind of authorization UI to present when connecting to a device.
Use the provided factory methods to create an authorization method appropriate for your device's pairing requirements.
public struct AuthorizationMethod : Equatable, Sendable {
/// Represents the valid lengths for an authorization code.
///
/// Use one of the provided static properties to specify the length
/// of an authorization code.
@available(iOS 27.0, *)
@available(macCatalyst, unavailable)
@available(visionOS, unavailable)
public struct CodeLength : Equatable, Sendable {
/// A 4-character code.
public static let fourCharacter: MediaOutputDevice.AuthorizationMethod.CodeLength
/// A 6-character code.
public static let sixCharacter: MediaOutputDevice.AuthorizationMethod.CodeLength
/// Returns a Boolean value indicating whether two values are equal.
///
/// Equality is the inverse of inequality. For any values `a` and `b`,
/// `a == b` implies that `a != b` is `false`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func == (a: MediaOutputDevice.AuthorizationMethod.CodeLength, b: MediaOutputDevice.AuthorizationMethod.CodeLength) -> Bool
}
/// No authorization is required.
public static var none: MediaOutputDevice.AuthorizationMethod { get }
/// Creates a numeric PIN entry authorization method.
///
/// The system presents a UI with individual digit fields for the user to enter
/// a numeric code when connecting to the device.
///
/// - Parameter length: The number of digit fields presented in the pairing UI.
///
/// ```swift
/// // Present a 4-digit PIN entry UI
/// let auth = AuthorizationMethod.numericCode(length: .fourCharacter)
/// ```
public static func numericCode(length: MediaOutputDevice.AuthorizationMethod.CodeLength) -> MediaOutputDevice.AuthorizationMethod
/// Presents a freeform text password input for device authorization.
public static var password: MediaOutputDevice.AuthorizationMethod { get }
/// Returns a Boolean value indicating whether two values are equal.
///
/// Equality is the inverse of inequality. For any values `a` and `b`,
/// `a == b` implies that `a != b` is `false`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func == (a: MediaOutputDevice.AuthorizationMethod, b: MediaOutputDevice.AuthorizationMethod) -> Bool
}MediaOutputDevice.Capabilitiespublic struct Capabilities : OptionSet, CustomStringConvertible, SendableDefines the media capabilities supported by a MediaOutputDevice.
Use these options to describe what a device can do, such as streaming audio or video in realtime, playing media from a URL, or launching a remote application.
public struct Capabilities : OptionSet, CustomStringConvertible, Sendable {
/// The corresponding value of the raw type.
///
/// A new instance initialized with `rawValue` will be equivalent to this
/// instance. For example:
///
/// enum PaperSize: String {
/// case A4, A5, Letter, Legal
/// }
///
/// let selectedSize = PaperSize.Letter
/// print(selectedSize.rawValue)
/// // Prints "Letter"
///
/// print(selectedSize == PaperSize(rawValue: selectedSize.rawValue)!)
/// // Prints "true"
public let rawValue: Int
/// Creates a new option set from the given raw value.
///
/// This initializer always succeeds, even if the value passed as `rawValue`
/// exceeds the static properties declared as part of the option set. This
/// example creates an instance of `ShippingOptions` with a raw value beyond
/// the highest element, with a bit mask that effectively contains all the
/// declared static members.
///
/// let extraOptions = ShippingOptions(rawValue: 255)
/// print(extraOptions.isStrictSuperset(of: .all))
/// // Prints "true"
///
/// - Parameter rawValue: The raw value of the option set to create. Each bit
/// of `rawValue` potentially represents an element of the option set,
/// though raw values may include bits that are not defined as distinct
/// values of the `OptionSet` type.
public init(rawValue: Int)
/// Capable of receiving audio samples and processing them in realtime.
public static let realtimeAudioStreaming: MediaOutputDevice.Capabilities
/// Capable of receiving video samples and processing them in realtime.
public static let realtimeVideoStreaming: MediaOutputDevice.Capabilities
/// Capable of receiving a media URL and providing a playback experience.
public static let urlPlayback: MediaOutputDevice.Capabilities
/// Capable of launching an application and providing an application-to-application data channel.
public static let appLaunch: MediaOutputDevice.Capabilities
/// A textual representation of the capabilities.
public var description: String { get }
/// The type of the elements of an array literal.
@available(iOS 27.0, *)
@available(macCatalyst, unavailable)
@available(visionOS, unavailable)
public typealias ArrayLiteralElement = MediaOutputDevice.Capabilities
/// The element type of the option set.
///
/// To inherit all the default implementations from the `OptionSet` protocol,
/// the `Element` type must be `Self`, the default.
@available(iOS 27.0, *)
@available(macCatalyst, unavailable)
@available(visionOS, unavailable)
public typealias Element = MediaOutputDevice.Capabilities
/// The raw type that can be used to represent all values of the conforming
/// type.
///
/// Every distinct value of the conforming type has a corresponding unique
/// value of the `RawValue` type, but there may be values of the `RawValue`
/// type that don't have a corresponding value of the conforming type.
@available(iOS 27.0, *)
@available(macCatalyst, unavailable)
@available(visionOS, unavailable)
public typealias RawValue = Int
}MediaOutputDevice.DeviceTypepublic enum DeviceType : SendableA device type used for display in user interfaces.
public enum DeviceType : Sendable {
/// A hi-fi speaker.
case hifiSpeaker
/// A television.
case tv
/// A streaming media stick.
case mediaStick
/// A laptop computer.
case laptopComputer
/// A desktop computer.
case desktopComputer
/// A television with a connected media box.
case tvAndMediabox
/// A pair of hi-fi speakers.
case hifiSpeakerTwo
/// A television with a connected hi-fi speaker.
case tvAndHifiSpeaker
/// Returns a Boolean value indicating whether two values are equal.
///
/// Equality is the inverse of inequality. For any values `a` and `b`,
/// `a == b` implies that `a != b` is `false`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func == (a: MediaOutputDevice.DeviceType, b: MediaOutputDevice.DeviceType) -> Bool
/// Hashes the essential components of this value by feeding them into the
/// given hasher.
///
/// Implement this method to conform to the `Hashable` protocol. The
/// components used for hashing must be the same as the components compared
/// in your type's `==` operator implementation. Call `hasher.combine(_:)`
/// with each of these components.
///
/// - Important: In your implementation of `hash(into:)`,
/// don't call `finalize()` on the `hasher` instance provided,
/// or replace it with a different instance.
/// Doing so may become a compile-time error in the future.
///
/// - Parameter hasher: The hasher to use when combining the components
/// of this instance.
public func hash(into hasher: inout Hasher)
/// The hash value.
///
/// Hash values are not guaranteed to be equal across different executions of
/// your program. Do not save hash values to use during a future execution.
///
/// - Important: `hashValue` is deprecated as a `Hashable` requirement. To
/// conform to `Hashable`, implement the `hash(into:)` requirement instead.
/// The compiler provides an implementation for `hashValue` for you.
public var hashValue: Int { get }
}MediaOutputDevice.IDpublic typealias ID = UUIDA type representing the stable identity of the entity associated with an instance.
MediaOutputDevice.VolumeControlpublic enum VolumeControl : SendableDefines the type of volume control supported by an output device or group.
This enumeration specifies how volume can be controlled on a device, affecting which volume control methods are available and how the system should present volume controls to the user.
public enum VolumeControl : Sendable {
/// Volume control is not available.
///
/// The device does not support any form of volume control. Volume adjustment
/// methods will not be available and volume controls should not be shown in the user interface.
case none
/// Full volume control is supported, ``MediaDeviceExtension/setVolume(_:for:)`` may be used to set the volume.
///
/// The device supports absolute volume control, allowing direct setting of volume
/// to specific levels (such as 0-100%). This provides the most precise volume control
/// and enables features like volume sliders in the user interface.
case absolute
/// Relative volume control is supported, ``MediaDeviceExtension/changeVolume(by:for:)`` must be used to change the volume.
///
/// The device only supports relative volume adjustments (up/down by increments).
/// This is common with devices that have hardware volume buttons but do not expose
/// their current volume level or allow direct volume setting.
case relative
/// Returns a Boolean value indicating whether two values are equal.
///
/// Equality is the inverse of inequality. For any values `a` and `b`,
/// `a == b` implies that `a != b` is `false`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func == (a: MediaOutputDevice.VolumeControl, b: MediaOutputDevice.VolumeControl) -> Bool
/// Hashes the essential components of this value by feeding them into the
/// given hasher.
///
/// Implement this method to conform to the `Hashable` protocol. The
/// components used for hashing must be the same as the components compared
/// in your type's `==` operator implementation. Call `hasher.combine(_:)`
/// with each of these components.
///
/// - Important: In your implementation of `hash(into:)`,
/// don't call `finalize()` on the `hasher` instance provided,
/// or replace it with a different instance.
/// Doing so may become a compile-time error in the future.
///
/// - Parameter hasher: The hasher to use when combining the components
/// of this instance.
public func hash(into hasher: inout Hasher)
/// The hash value.
///
/// Hash values are not guaranteed to be equal across different executions of
/// your program. Do not save hash values to use during a future execution.
///
/// - Important: `hashValue` is deprecated as a `Hashable` requirement. To
/// conform to `Hashable`, implement the `hash(into:)` requirement instead.
/// The compiler provides an implementation for `hashValue` for you.
public var hashValue: Int { get }
}MediaOutputDevice.AuthorizationMethod.CodeLengthpublic struct CodeLength : Equatable, SendableRepresents the valid lengths for an authorization code.
Use one of the provided static properties to specify the length of an authorization code.
public struct CodeLength : Equatable, Sendable {
/// A 4-character code.
public static let fourCharacter: MediaOutputDevice.AuthorizationMethod.CodeLength
/// A 6-character code.
public static let sixCharacter: MediaOutputDevice.AuthorizationMethod.CodeLength
/// Returns a Boolean value indicating whether two values are equal.
///
/// Equality is the inverse of inequality. For any values `a` and `b`,
/// `a == b` implies that `a != b` is `false`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func == (a: MediaOutputDevice.AuthorizationMethod.CodeLength, b: MediaOutputDevice.AuthorizationMethod.CodeLength) -> Bool
}MediaOutputDevice.Capabilities.ArrayLiteralElementpublic typealias ArrayLiteralElement = MediaOutputDevice.CapabilitiesThe type of the elements of an array literal.
MediaOutputDevice.Capabilities.Elementpublic typealias Element = MediaOutputDevice.CapabilitiesThe element type of the option set.
To inherit all the default implementations from the OptionSet protocol, the Element type must be Self, the default.
MediaOutputDevice.Capabilities.RawValuepublic typealias RawValue = IntThe raw type that can be used to represent all values of the conforming type.
Every distinct value of the conforming type has a corresponding unique value of the RawValue type, but there may be values of the RawValue type that don't have a corresponding value of the conforming type.
No APIs match your filter.