### Complete Offline Playback Example Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-offline.md Demonstrates a comprehensive setup for offline playback, including determining the appropriate source configuration based on network availability and offline content state. It initializes the player, handles different offline states, and loads the source. ```swift final class PlaybackViewController: UIViewController, PlayerListener { @IBOutlet weak var playerViewContainer: UIView! var player: Player! var playerView: PlayerView! var sourceConfig: SourceConfig? override func viewDidLoad() { super.viewDidLoad() guard var sourceConfig = sourceConfig else { return } let offlineManager = OfflineManager.sharedInstance() do { let contentManager = try offlineManager.offlineContentManager(for: sourceConfig) let isOnline = isNetworkAvailable() // Determine appropriate source config switch contentManager.offlineState { case .downloaded, .downloading, .suspended: if !isOnline && contentManager.offlineState == .downloaded { // Device offline, use cached content only guard let offlineConfig = contentManager.createOfflineSourceConfig( restrictedToAssetCache: true ) else { showError("Content not available offline") return } sourceConfig = offlineConfig } else { // Allow streaming uncached content when online if let offlineConfig = contentManager.createOfflineSourceConfig( restrictedToAssetCache: false ) { sourceConfig = offlineConfig } } case .notDownloaded, .canceling: if !isOnline { showError("Device offline and content not downloaded") return } } } catch { print("Offline manager error: \(error)") } // Setup player let playerConfig = PlayerConfig() playerConfig.key = playerLicenseKey let analyticsConfig = AnalyticsConfig(licenseKey: analyticsLicenseKey) player = PlayerFactory.createPlayer( playerConfig: playerConfig, analytics: .enabled(analyticsConfig: analyticsConfig) ) let playerView = PlayerView(player: player, frame: .zero) player.add(listener: self) playerView.autoresizingMask = [.flexibleHeight, .flexibleWidth] playerView.frame = playerViewContainer.bounds playerViewContainer.addSubview(playerView) self.playerView = playerView // Load and play player.load(sourceConfig: sourceConfig) } func onEvent(_ event: Event, player: Player) { print("[Event] \(event)") } deinit { player?.destroy() } } ``` -------------------------------- ### Basic Analytics Setup Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-analytics.md Initialize the player with basic analytics enabled using a license key. This snippet shows the fundamental setup within a SwiftUI View. ```swift struct ContentView: View { private let player: Player private let playerViewConfig: PlayerViewConfig init() { let playerConfig = PlayerConfig() playerConfig.key = playerLicenseKey let analyticsConfig = AnalyticsConfig(licenseKey: analyticsLicenseKey) player = PlayerFactory.createPlayer( playerConfig: playerConfig, analytics: .enabled(analyticsConfig: analyticsConfig) ) playerViewConfig = PlayerViewConfig() } var body: some View { VideoPlayerView(player: player, playerViewConfig: playerViewConfig) .onAppear { let sourceConfig = SourceConfig(url: streamURL, type: .hls) player.load(sourceConfig: sourceConfig) } } } ``` -------------------------------- ### Setup Custom HTML UI Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-ui.md Configure the player for a custom HTML UI by setting the appropriate configuration in PlayerConfig. This snippet shows the basic setup within a UIViewController. ```swift class CustomHTMLUIViewController: UIViewController { var player: Player! var playerView: PlayerView! override func viewDidLoad() { super.viewDidLoad() let playerConfig = PlayerConfig() playerConfig.key = playerLicenseKey // Configure for custom HTML UI let styleConfig = playerConfig.styleConfig // (Set custom UI configuration as per SDK documentation) player = PlayerFactory.createPlayer( playerConfig: playerConfig, analytics: .enabled(analyticsConfig: analyticsConfig) ) playerView = PlayerView(player: player, frame: .zero) playerView.autoresizingMask = [.flexibleHeight, .flexibleWidth] playerView.frame = view.bounds view.addSubview(playerView) let sourceConfig = SourceConfig(url: streamURL, type: .hls) player.load(sourceConfig: sourceConfig) } deinit { player?.destroy() } } ``` -------------------------------- ### Create and Load Playlist Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-playlist.md This example demonstrates creating an array of sources using `SourceFactory` and then loading them as a playlist with specified options. ```swift func createPlaylist() -> [Source] { let source1 = SourceFactory.createSource( from: SourceConfig(url: url1, type: .hls) ) let source2 = SourceFactory.createSource( from: SourceConfig(url: url2, type: .dash) ) return [source1, source2] } let sources = createPlaylist() let playlistConfig = PlaylistConfig( sources: sources, options: PlaylistOptions(preloadAllSources: false) ) player.load(playlistConfig: playlistConfig) ``` -------------------------------- ### Offline Playback Example Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/getting-started.md Demonstrates how to check the offline state of content and load it if downloaded. Requires an `OfflineManager` and `SourceConfig`. ```swift let offlineManager = OfflineManager.sharedInstance() let contentManager = try offlineManager.offlineContentManager(for: sourceConfig) switch contentManager.offlineState { case .downloaded: if let offlineConfig = contentManager.createOfflineSourceConfig( restrictedToAssetCache: true ) { player.load(sourceConfig: offlineConfig) } case .notDownloaded: print("Content not available offline") default: break } ``` -------------------------------- ### Enable Analytics with Basic Configuration Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-analytics.md This example shows how to create a player with analytics enabled using only the basic configuration, which includes the license key. ```swift let analyticsConfig = AnalyticsConfig(licenseKey: "analytics-license-key") let player = PlayerFactory.createPlayer( playerConfig: playerConfig, analytics: .enabled(analyticsConfig: analyticsConfig) ) ``` -------------------------------- ### AdSource Example Usage Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-advertising.md Demonstrates creating AdSource instances using both String and URL object initializers for Google IMA ads. ```swift let imaTag = "https://pubads.g.doubleclick.net/gampad/ads?..." let adSource = AdSource(tag: imaTag, ofType: .ima) // Or with URL object let adSourceURL = URL(string: imaTag)! let adSourceFromURL = AdSource(tag: adSourceURL, ofType: .ima) ``` -------------------------------- ### tvOS Player Initialization and View Setup Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/getting-started.md Initialize the Bitmovin Player for tvOS applications and integrate it with PlayerView for focus management. ```swift let playerConfig = PlayerConfig() playerConfig.key = playerLicenseKey let player = PlayerFactory.createPlayer( playerConfig: playerConfig, analytics: .enabled(analyticsConfig: analyticsConfig) ) // tvOS-specific: Use PlayerView with focus management let playerView = PlayerView(player: player, frame: view.bounds) playerView.autoresizingMask = [.flexibleHeight, .flexibleWidth] view.addSubview(playerView) ``` -------------------------------- ### Basic Player Setup for Casting Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-casting.md Initialize the Bitmovin Player with casting enabled. Casting is automatically handled if the Google Cast SDK is present. ```swift import BitmovinPlayer class CastingViewController: UIViewController { var player: Player! var playerView: PlayerView! override func viewDidLoad() { super.viewDidLoad() // Create player configuration let playerConfig = PlayerConfig() playerConfig.key = playerLicenseKey let analyticsConfig = AnalyticsConfig(licenseKey: analyticsLicenseKey) // Create player - casting is automatically enabled if Google Cast SDK is present player = PlayerFactory.createPlayer( playerConfig: playerConfig, analytics: .enabled(analyticsConfig: analyticsConfig) ) // Create player view playerView = PlayerView(player: player, frame: .zero) playerView.autoresizingMask = [.flexibleHeight, .flexibleWidth] playerView.frame = view.bounds view.addSubview(playerView) // Load source let sourceConfig = SourceConfig(url: streamURL, type: .hls) sourceConfig.title = "Apple Sample Stream" player.load(sourceConfig: sourceConfig) } deinit { player?.destroy() } } ``` -------------------------------- ### Enable Analytics with Default Metadata Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-analytics.md This example demonstrates how to create a player with analytics enabled, including both the basic configuration and default metadata with custom user ID and data. ```swift let customData = CustomData( customData1: "free_tier", customData2: "us_east" ) let defaultMetadata = DefaultMetadata( customUserId: "user123", customData: customData ) let player = PlayerFactory.createPlayer( playerConfig: playerConfig, analytics: .enabled( analyticsConfig: analyticsConfig, defaultMetadata: defaultMetadata ) ) ``` -------------------------------- ### SourceMetadata Example Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-analytics.md Creates a SourceMetadata object with a title, path, and custom data, then uses it to create a source configuration. This is useful for detailed analytics on individual video streams. ```swift let sourceMetadata = SourceMetadata( title: "Art of Motion", path: "root/category/sports", customData: CustomData(customData1: "category-sports") ) let source = SourceFactory.createSource( from: sourceConfig, sourceMetadata: sourceMetadata ) ``` -------------------------------- ### Boolean Configuration Examples Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/types.md Set boolean properties to `true` or `false` to enable or disable specific player behaviors or UI elements. Examples include autoplay, mute, and hiding the first frame. ```swift playerConfig.playbackConfig.isAutoplayEnabled = true playerConfig.playbackConfig.isMuted = false uiConfig.hideFirstFrame = true playlistOptions.preloadAllSources = false ``` -------------------------------- ### CoordinationManager Setup and Session Handling Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-shareplay.md Sets up the CoordinationManager, including observing group sessions and handling asset changes. It automatically joins new sessions and updates the local asset reference when the group activity changes. ```swift class CoordinationManager { static let shared = CoordinationManager() let observer = GroupStateObserver() private var cancellables = Set() @Published var asset: Asset? @Published var groupSession: GroupSession? private init() { Task { for await groupSession in MediaWatchingActivity.sessions() { self.groupSession = groupSession cancellables.removeAll() groupSession.$state.sink { [weak self] state in if case .invalidated = state { self?.groupSession = nil self?.cancellables.removeAll() } } .store(in: &cancellables) groupSession.join() groupSession.$activity .removeDuplicates { $0.identifier == $1.identifier } .sink { [weak self] activity in self?.asset = activity.asset } .store(in: &cancellables) } } } func prepareToPlay(asset: Asset) { if let groupSession = groupSession, groupSession.state == .joined { if asset.customSharePlayIdentifier == groupSession.activity.asset.customSharePlayIdentifier, asset.url == groupSession.activity.asset.url { // Same asset, just update local reference self.asset = asset } else { // New asset, update group activity groupSession.activity = MediaWatchingActivity(asset: asset) } return } Task { let activity = MediaWatchingActivity(asset: asset) switch await activity.prepareForActivation() { case .activationDisabled: self.asset = activity.asset case .activationPreferred: do { _ = try await activity.activate() } catch { print("Unable to activate: error") } case .cancelled: break default: break } } } } ``` -------------------------------- ### Initialize GroupStateObserver Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-shareplay.md Initializes the GroupStateObserver. Use this to start observing state changes in a group session. ```swift init() ``` -------------------------------- ### Implement PlayerListener for Event Handling Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-player-core.md Example implementation of the PlayerListener protocol to handle playback events like play and pause. ```swift class MyViewController: UIViewController, PlayerListener { func onEvent(_ event: Event, player: Player) { if let playEvent = event as? PlayEvent { print("Playback started") } else if let pauseEvent = event as? PauseEvent { print("Playback paused") } } } ``` -------------------------------- ### CustomData Examples Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-analytics.md Demonstrates creating CustomData instances for global and source-specific analytics. Global data applies broadly, while source-specific data is tied to individual content. ```swift // Global custom data let globalData = CustomData( customData1: "premium", customData2: "us", customData3: "ios" ) // Source-specific custom data let sourceData = CustomData( customData3: "Free Running", customData4: "Sports" ) let sourceMetadata = SourceMetadata( title: "Art of Motion", customData: sourceData ) ``` -------------------------------- ### Advertising (IMA) Setup Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/getting-started.md Configures the player for advertising using IMA, including pre-roll, mid-roll, and post-roll ad insertion. Requires `PlayerConfig`, `AdSource`, and `AdItem`. ```swift let playerConfig = PlayerConfig() let adTag = "https://pubads.g.doubleclick.net/gampad/ads?..." let adSource = AdSource(tag: adTag, ofType: .ima) let preRoll = AdItem(adSources: [adSource], atPosition: "pre") let midRoll = AdItem(adSources: [adSource], atPosition: "50%") let postRoll = AdItem(adSources: [adSource], atPosition: "post") playerConfig.advertisingConfig = AdvertisingConfig( schedule: [preRoll, midRoll, postRoll] ) let player = PlayerFactory.createPlayer(playerConfig: playerConfig) ``` -------------------------------- ### MediaWatchingActivity Initializer Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-shareplay.md Initializes a MediaWatchingActivity with a specific media asset. This is the starting point for coordinating playback of a particular piece of content. ```APIDOC ## MediaWatchingActivity Initializer ### Description Initializes a `MediaWatchingActivity` with a specific media asset. This is the starting point for coordinating playback of a particular piece of content. ### Initializer Signature ```swift init(asset: Asset) ``` ### Parameters #### Path Parameters - **asset** (Asset) - Required - Media asset to watch together ### Request Example ```swift let asset = Asset( url: videoURL, customSharePlayIdentifier: "video-001", title: "Movie Title" ) let activity = MediaWatchingActivity(asset: asset) ``` ``` -------------------------------- ### Mixed Ad Schedule Setup Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-advertising.md Configure a mixed ad schedule including pre-roll, mid-roll at 25% of content duration, and post-roll ads. ```swift let playerConfig = PlayerConfig() // Pre-roll let preRollTag = "https://example.com/ads/preroll.xml" let preRollSource = AdSource(tag: preRollTag, ofType: .ima) let preRoll = AdItem(adSources: [preRollSource], atPosition: "pre") // Mid-roll at 25% let midRollTag = "https://example.com/ads/midroll.xml" let midRollSource = AdSource(tag: midRollTag, ofType: .ima) let midRoll = AdItem(adSources: [midRollSource], atPosition: "25%") // Post-roll let postRollTag = "https://example.com/ads/postroll.xml" let postRollSource = AdSource(tag: postRollTag, ofType: .ima) let postRoll = AdItem(adSources: [postRollSource], atPosition: "post") let adConfig = AdvertisingConfig(schedule: [preRoll, midRoll, postRoll]) playerConfig.advertisingConfig = adConfig playerConfig.key = playerLicenseKey let player = PlayerFactory.createPlayer(playerConfig: playerConfig) ``` -------------------------------- ### Numeric Configuration Examples Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/types.md Use numeric types like `Int`, `TimeInterval`, and `Double` to set values for properties such as bitrate, playback position, and progress indicators. ```swift let bitrate: Int = 5000000 // 5 Mbps let position: TimeInterval = 30.0 // 30 seconds let progress: Double = 0.75 // 75% ``` -------------------------------- ### Fallback Ad Sources Setup Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-advertising.md Configure fallback ad sources for a single ad break. The player will attempt to load the primary ad source first and fall back to the secondary if the primary fails. ```swift let primaryTag = "https://example.com/ads/primary.xml" let secondaryTag = "https://example.com/ads/secondary.xml" let primarySource = AdSource(tag: primaryTag, ofType: .ima) let secondarySource = AdSource(tag: secondaryTag, ofType: .ima) // Player tries primary first, falls back to secondary if primary fails let adItem = AdItem( adSources: [primarySource, secondarySource], atPosition: "pre" ) let adConfig = AdvertisingConfig(schedule: [adItem]) playerConfig.advertisingConfig = adConfig ``` -------------------------------- ### String Configuration Examples Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/types.md Assign string values to configure properties like video titles or custom data fields. A closure can also be used to modify string values, such as preparing a content ID. ```swift sourceConfig.title = "My Video" customData.customData1 = "category" fpsConfig.prepareContentId = { contentId in return "modified-\(contentId)" } ``` -------------------------------- ### Multiple Ad Breaks (VMAP) Setup Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-advertising.md Set up multiple ad breaks using a VMAP tag. The VMAP tag defines ad breaks server-side, and it's still configured as a single item in the schedule. ```swift // VMAP tag with multiple ad breaks defined server-side let vmapTag = "https://pubads.g.doubleclick.net/gampad/ads?" + "sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&" + "ad_rule=1&impl=s&gdfp_req=1&env=vp&output=vmap&" + "unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ar%3Dpostonly&" + "cmsid=496&vid=short_onecue&" + "correlator=\(Int.random(in: 0..<100000))" let vmapSource = AdSource(tag: vmapTag, ofType: .ima) // VMAP handles multiple breaks, still define as single item let vmapItem = AdItem(adSources: [vmapSource], atPosition: "pre") let adConfig = AdvertisingConfig(schedule: [vmapItem]) playerConfig.advertisingConfig = adConfig ``` -------------------------------- ### Track Complete Playback Sessions Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-analytics.md Implement session tracking to monitor complete playback sessions. This example demonstrates creating a session ID and generating metadata that includes the session ID and active status. ```swift class SessionTracker { let sessionId = UUID().uuidString var player: Player! func createSessionMetadata() -> DefaultMetadata { let data = CustomData( customData5: sessionId, customData6: "session_active" ) return DefaultMetadata( customUserId: getCurrentUserId(), customData: data ) } } ``` -------------------------------- ### Setup Coordination Manager for SharePlay Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-shareplay.md Manages the SharePlay group session, including observing session states, handling activity changes, and initiating playback of shared assets. This class should be initialized once and used as a shared instance. ```swift class CoordinationManager: ObservableObject { static let shared = CoordinationManager() @Published var asset: Asset? @Published var groupSession: GroupSession? private var cancellables = Set() private init() { observeGroupSessions() } private func observeGroupSessions() { Task { for await groupSession in MediaWatchingActivity.sessions() { self.groupSession = groupSession cancellables.removeAll() groupSession.$state .sink { [weak self] state in if case .invalidated = state { self?.groupSession = nil self?.cancellables.removeAll() } } .store(in: &cancellables) groupSession.join() groupSession.$activity .removeDuplicates { $0.identifier == $1.identifier } .sink { [weak self] activity in self?.asset = activity.asset } .store(in: &cancellables) } } } func play(asset: Asset) { if let groupSession = groupSession, groupSession.state == .joined { if isSameAsset(asset, groupSession.activity.asset) { self.asset = asset } else { groupSession.activity = MediaWatchingActivity(asset: asset) } return } Task { let activity = MediaWatchingActivity(asset: asset) switch await activity.prepareForActivation() { case .activationDisabled: self.asset = asset case .activationPreferred: do { _ = try await activity.activate() } catch { print("Failed to activate SharePlay: \(error)") } case .cancelled: break default: break } } } private func isSameAsset(_ a: Asset, _ b: Asset) -> Bool { a.customSharePlayIdentifier == b.customSharePlayIdentifier && a.url == b.url } } ``` -------------------------------- ### Initiate Offline Download Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-offline.md Use the OfflineManager to get an offline content manager and check the current download state before initiating a download. The exact download initiation method depends on SDK internals. ```swift let offlineManager = OfflineManager.sharedInstance() do { let contentManager = try offlineManager.offlineContentManager(for: sourceConfig) // Start download (implementation depends on SDK internals) // This is typically done through a UI button or automatic process switch contentManager.offlineState { case .notDownloaded: // Initiate download through content manager or separate download API print("Ready to download") case .downloading: print("Download in progress") case .downloaded: print("Already downloaded") default: break } } catch { print("Error: \(error)") } ``` -------------------------------- ### Google IMA Ads (VAST) Setup Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-advertising.md Configure a pre-roll ad using a VAST tag with Google IMA. Ensure to enable hideFirstFrame to prevent content from showing before ads. ```swift let playerConfig = PlayerConfig() // Enable hideFirstFrame to prevent content showing before ads let uiConfig = BitmovinUserInterfaceConfig() uiConfig.hideFirstFrame = true playerConfig.styleConfig.userInterfaceConfig = uiConfig // VAST tag with random correlator to prevent caching let vastTag = "https://pubads.g.doubleclick.net/gampad/ads?" + "sz=640x480&iu=/124319096/external/single_ad_samples&ciu_szs=300x250&" + "impl=s&gdfp_req=1&env=vp&output=vast&unviewed_position_start=1&" + "cust_params=deployment%3Ddevsite%26sample_ct%3Dlinear&" + "correlator=\(Int.random(in: 0..<100000))" let adSource = AdSource(tag: vastTag, ofType: .ima) let preRoll = AdItem(adSources: [adSource], atPosition: "pre") let adConfig = AdvertisingConfig(schedule: [preRoll]) playerConfig.advertisingConfig = adConfig playerConfig.key = playerLicenseKey let player = PlayerFactory.createPlayer( playerConfig: playerConfig, analytics: .enabled(analyticsConfig: analyticsConfig) ) ``` -------------------------------- ### Initialize Player with Configuration Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/README.md Create a new player instance with custom configuration and enable analytics. ```swift let playerConfig = PlayerConfig() playerConfig.key = "license-key" let player = PlayerFactory.createPlayer( playerConfig: playerConfig, analytics: .enabled(analyticsConfig: analyticsConfig) ) ``` -------------------------------- ### BufferingStartedEvent Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-events.md Emitted when the player starts buffering. ```APIDOC ## BufferingStartedEvent ### Description Emitted when buffering begins. ### Method `player.events.on(BufferingStartedEvent.self)` ### Parameters None ### Response Example ```swift player.events.on(BufferingStartedEvent.self) .sink { _ in print("Buffering started") } .store(in: &cancellables) ``` ``` -------------------------------- ### PlayEvent Class Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/types.md Represents the event emitted when playback starts. ```swift class PlayEvent: PlayerEvent { // Emitted when playback starts } ``` -------------------------------- ### OfflineContentManager.offlineState Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-offline.md Get the current offline availability state of the source managed by OfflineContentManager. ```APIDOC ## offlineState ### Description Current offline availability state of the source. ### Properties - **offlineState** (`OfflineState`) - The current state of the offline content. ### OfflineState Enum ```swift enum OfflineState { case notDownloaded // Content not downloaded case downloading // Download in progress case downloaded // Fully downloaded and playable case suspended // Download paused/suspended case canceling // Download cancellation in progress } ``` ### Example ```swift switch offlineContentManager.offlineState { case .downloaded: print("Ready for offline playback") case .downloading: print("Download in progress") case .notDownloaded: print("Not downloaded") default: break } ``` ``` -------------------------------- ### Listen to PlayEvent Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-events.md Emitted when playback starts. Use this to track when the video begins playing. ```swift player.events.on(PlayEvent.self) .sink { print("Playback started") } .store(in: &cancellables) ``` -------------------------------- ### Get Group Session ID Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-shareplay.md Retrieve the unique identifier for an active group session. ```swift let sessionId = groupSession.id ``` -------------------------------- ### AdStartEvent Class Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/types.md Represents the event emitted when an advertisement starts. Includes optional ad data. ```swift class AdStartEvent: PlayerEvent { var adData: AdData? // Ad information } ``` -------------------------------- ### Initialize PlaylistOptions Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-playlist.md Configure playlist behavior with PlaylistOptions. Set `preloadAllSources` to true to load all manifests upfront, or false for lazy loading to reduce initial memory usage. ```swift // Preload all sources upfront for faster switching let optionsPreloadAll = PlaylistOptions(preloadAllSources: true) // Lazy load sources to reduce initial memory usage let optionsLazy = PlaylistOptions(preloadAllSources: false) ``` -------------------------------- ### MediaWatchingActivity.prepareForActivation() Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-shareplay.md Prepares the SharePlay activity for activation and presents the system's UI, allowing the user to choose their participation mode. This method is crucial for initiating the SharePlay experience. ```APIDOC ## MediaWatchingActivity.prepareForActivation() ### Description Prepares the SharePlay activity for activation and presents the system's UI, allowing the user to choose their participation mode. This method is crucial for initiating the SharePlay experience. ### Method Signature ```swift func prepareForActivation() async -> GroupActivityActivationResult ``` ### Returns - `.activationPreferred` — User wants to share with group - `.activationDisabled` — Playback coordination disabled or user declined - `.cancelled` — User cancelled the operation ### Request Example ```swift let activity = MediaWatchingActivity(asset: asset) switch await activity.prepareForActivation() { case .activationPreferred: do { let session = try await activity.activate() // Activity activated, handle session } catch { print("Failed to activate: \(error)") } case .activationDisabled: // Play locally without SharePlay playLocally(asset: asset) case .cancelled: // User cancelled, do nothing break default: break } ``` ``` -------------------------------- ### Get Participant Count Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-shareplay.md Determine the number of participants, including the local user, in a group session. ```swift let participantCount = groupSession.participants.count ``` -------------------------------- ### PlayEvent Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-events.md Emitted when playback starts. This event can be observed to trigger actions when the player begins playing content. ```APIDOC ## PlayEvent ### Description Emitted when playback starts. ### Method `player.events.on(PlayEvent.self)` ### Parameters None ### Response Example ```swift player.events.on(PlayEvent.self) .sink { _ in print("Playback started") } .store(in: &cancellables) ``` ``` -------------------------------- ### Access OfflineManager Singleton Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-offline.md Get the shared singleton instance of the OfflineManager. This is the entry point for all offline operations. ```swift let offlineManager = OfflineManager.sharedInstance() ``` -------------------------------- ### Initialize PlaylistConfig Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-playlist.md Use this initializer to create a configuration object for loading a playlist of sources. Specify the array of sources and optional playlist behavior options. ```swift let playlistConfig = PlaylistConfig( sources: [source1, source2, source3], options: PlaylistOptions(preloadAllSources: false) ) player.load(playlistConfig: playlistConfig) ``` -------------------------------- ### GroupStateObserver Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-shareplay.md Observes state changes in a group session. It provides an initializer and a usage example demonstrating how to subscribe to state updates. ```APIDOC ## GroupStateObserver ### Description Observes state changes in a group session. ### Initializer ```swift init() ``` ### Usage ```swift let observer = GroupStateObserver() // Observe state changes groupSession.$state .sink { switch state { case .joined: print("Session joined") case .invalidated: print("Session ended") } } .store(in: &cancellables) ``` ``` -------------------------------- ### Create BitmovinUserInterfaceConfig Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-ui.md Initializes UI configuration with default settings. Assign this to `playerConfig.styleConfig.userInterfaceConfig`. ```swift let uiConfig = BitmovinUserInterfaceConfig() playerConfig.styleConfig.userInterfaceConfig = uiConfig ``` -------------------------------- ### Initialize SourceConfig Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-source.md Use this initializer to create a SourceConfig object with a media stream URL and its type. Ensure the URL is valid and the SourceType is correctly specified. ```swift let sourceConfig = SourceConfig( url: URL(string: "https://example.com/stream.m3u8")!, type: .hls ) ``` -------------------------------- ### Basic Playback with UIKit Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/getting-started.md Initialize the Bitmovin Player and load an HLS stream in a UIKit application. Ensure you replace 'license-key' and 'analytics-key' with your actual keys. ```swift import UIKit import BitmovinPlayer class ViewController: UIViewController { var player: Player! var playerView: PlayerView! override func viewDidLoad() { super.viewDidLoad() let playerConfig = PlayerConfig() playerConfig.key = "license-key" let analyticsConfig = AnalyticsConfig(licenseKey: "analytics-key") player = PlayerFactory.createPlayer( playerConfig: playerConfig, analytics: .enabled(analyticsConfig: analyticsConfig) ) playerView = PlayerView(player: player, frame: view.bounds) playerView.autoresizingMask = [.flexibleHeight, .flexibleWidth] view.addSubview(playerView) let sourceConfig = SourceConfig( url: URL(string: "https://example.com/stream.m3u8")!, type: .hls ) sourceConfig.title = "Sample Stream" player.load(sourceConfig: sourceConfig) } deinit { player?.destroy() } } ``` -------------------------------- ### Basic Playback with SwiftUI Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/getting-started.md Initialize the Bitmovin Player and load an HLS stream within a SwiftUI view. Remember to substitute 'license-key' and 'analytics-key' with your valid keys. ```swift import SwiftUI import BitmovinPlayer struct ContentView: View { @State private var player: Player @State private var playerViewConfig = PlayerViewConfig() init() { let playerConfig = PlayerConfig() playerConfig.key = "license-key" let analyticsConfig = AnalyticsConfig(licenseKey: "analytics-key") _player = State(initialValue: PlayerFactory.createPlayer( playerConfig: playerConfig, analytics: .enabled(analyticsConfig: analyticsConfig) )) } var body: some View { ZStack { Color.black VideoPlayerView( player: player, playerViewConfig: playerViewConfig ) } .onAppear { let sourceConfig = SourceConfig( url: URL(string: "https://example.com/stream.m3u8")!, type: .hls ) player.load(sourceConfig: sourceConfig) } } } ``` -------------------------------- ### Load Pre-configured Source Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-player-core.md Loads a source instance that has already been created using the SourceFactory. This allows for more complex source configurations. ```swift let sourceMetadata = SourceMetadata(title: "My Video") let source = SourceFactory.createSource(from: sourceConfig, sourceMetadata: sourceMetadata) player.load(source: source) ``` -------------------------------- ### Handling Casting Events Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-casting.md Implement the PlayerListener protocol to receive and handle casting-related events such as start, stop, availability, and errors. ```swift class CastingViewController: UIViewController, PlayerListener { func onEvent(_ event: Event, player: Player) { if let castStartEvent = event as? CastStartEvent { print("Casting started") } else if let castStopEvent = event as? CastStopEvent { print("Casting stopped") } else if let castAvailableEvent = event as? CastAvailableEvent { print("Casting devices available") } else if let castErrorEvent = event as? CastErrorEvent { print("Casting error: \(castErrorEvent.message)") } } } ``` -------------------------------- ### Initialize PlayerViewConfig Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-player-core.md Creates a PlayerViewConfig instance with default settings. Customize properties after initialization as needed. ```swift let playerViewConfig = PlayerViewConfig() // Customize properties as needed ``` -------------------------------- ### Initialize MediaWatchingActivity Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-shareplay.md Instantiate the core activity object for SharePlay coordination with a prepared media asset. ```swift let activity = MediaWatchingActivity(asset: asset) ``` -------------------------------- ### BitmovinUserInterfaceConfig.hideFirstFrame Property Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-ui.md Controls whether the first frame of content is hidden until playback starts or ads finish. Useful for ad scenarios. ```APIDOC ## BitmovinUserInterfaceConfig.hideFirstFrame ### Description Hide the first frame of content until playback starts or ads finish. ### Property - **hideFirstFrame** (Bool) - Description ### Example ```swift let uiConfig = BitmovinUserInterfaceConfig() uiConfig.hideFirstFrame = true playerConfig.styleConfig.userInterfaceConfig = uiConfig ``` ### Use Case Advertising — prevents content poster from showing while ads load/play. ``` -------------------------------- ### CoordinationManager Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-shareplay.md Manages group coordination logic, acting as a singleton. It handles asset and group session management, including setup and preparation for playback. ```APIDOC ## CoordinationManager ### Description Manager for handling group coordination logic. Implements a singleton pattern. ### Singleton Pattern ```swift class CoordinationManager { static let shared = CoordinationManager() @Published var asset: Asset? @Published var groupSession: GroupSession? // Private init ensures singleton private init() { } } ``` ### Key Functionality #### Asset Management ```swift @Published var asset: Asset? ``` The currently coordinated asset. When set, all participants are notified. #### Session Management ```swift @Published var groupSession: GroupSession? ``` The active group session, or nil if none active. ### Setup ```swift class CoordinationManager { static let shared = CoordinationManager() let observer = GroupStateObserver() private var cancellables = Set() @Published var asset: Asset? @Published var groupSession: GroupSession? private init() { Task { for await groupSession in MediaWatchingActivity.sessions() { self.groupSession = groupSession cancellables.removeAll() groupSession.$state.sink { [weak self] state in if case .invalidated = state { self?.groupSession = nil self?.cancellables.removeAll() } } .store(in: &cancellables) groupSession.join() groupSession.$activity .removeDuplicates { $0.identifier == $1.identifier } .sink { [weak self] activity in self?.asset = activity.asset } .store(in: &cancellables) } } } func prepareToPlay(asset: Asset) { if let groupSession = groupSession, groupSession.state == .joined { if asset.customSharePlayIdentifier == groupSession.activity.asset.customSharePlayIdentifier, asset.url == groupSession.activity.asset.url { // Same asset, just update local reference self.asset = asset } else { // New asset, update group activity groupSession.activity = MediaWatchingActivity(asset: asset) } return } Task { let activity = MediaWatchingActivity(asset: asset) switch await activity.prepareForActivation() { case .activationDisabled: self.asset = activity.asset case .activationPreferred: do { _ = try await activity.activate() } catch { print("Unable to activate: \(error)") } case .cancelled: break default: break } } } } ``` ``` -------------------------------- ### Configure Subtitle Tracks Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/configuration.md Set up subtitle tracks with their URLs, languages, labels, and default status. Ensure URLs point to valid VTT or SRT files. ```swift let engSubs = SubtitleTrack() engSubs.url = URL(string: "https://example.com/en.vtt")! engSubs.language = "en" engSubs.label = "English" engSubs.isDefault = true let spanishSubs = SubtitleTrack() spanishSubs.url = URL(string: "https://example.com/es.vtt")! spanishSubs.language = "es" spanishSubs.label = "Español" sourceConfig.subtitleTracks = [engSubs, spanishSubs] ``` -------------------------------- ### Configure Source with URL Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/types.md Configures the media source using standard Swift Foundation URL types for stream, poster, and license URLs. Ensure URLs are valid and correctly formatted. ```swift let streamURL = URL(string: "https://example.com/stream.m3u8")! let posterURL = URL(string: "https://example.com/poster.jpg")! let licenseURL = URL(string: "https://license.example.com/key")! let sourceConfig = SourceConfig(url: streamURL, type: .hls) sourceConfig.posterSource = posterURL ``` -------------------------------- ### SourceFactory.createSource (from SourceConfig) Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-source.md Creates a playable media Source instance from a SourceConfig. This is the basic method for initializing a source. ```APIDOC ## SourceFactory.createSource (from SourceConfig) ### Description Creates a playable media Source instance from a SourceConfig. This is the basic method for initializing a source. ### Method static func createSource(from sourceConfig: SourceConfig) -> Source ### Parameters #### Path Parameters - **sourceConfig** (SourceConfig) - Required - Configuration for the source ### Request Example ```swift let sourceConfig = SourceConfig(url: streamURL, type: .hls) let source = SourceFactory.createSource(from: sourceConfig) ``` ### Response #### Success Response - **Source** - An instance of the Source object. ``` -------------------------------- ### Configure Development Player Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/getting-started.md Use this configuration for development environments. It sets a development license key and enables autoplay. ```swift let playerConfig = PlayerConfig() playerConfig.key = "dev-license" playerConfig.playbackConfig.isAutoplayEnabled = true playerConfig.playbackConfig.isMuted = false ``` -------------------------------- ### Get OfflineContentManager for SourceConfig Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-offline.md Obtain an OfflineContentManager for a specific SourceConfig to manage its offline state. Ensure proper error handling as this operation can throw. ```swift let offlineManager = OfflineManager.sharedInstance() do { let contentManager = try offlineManager.offlineContentManager(for: sourceConfig) print("Offline state: \(contentManager.offlineState)") } catch { print("Error accessing offline manager: \(error)") } ``` -------------------------------- ### AdSource Alternative Initializer (String URL) Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-advertising.md Convenience initializer for AdSource accepting a String URL. ```APIDOC ## AdSource Alternative Initializer (String URL) ### Description Provides a convenient way to initialize an AdSource using a String representation of the URL. ### Parameters #### Path Parameters - **tag** (String) - Required - String URL to ad tag/playlist - **ofType** (AdSourceType) - Required - Type of ad source (ima, bitmovin, etc.) ### Request Example ```swift let imaTag = "https://pubads.g.doubleclick.net/gampad/ads?..." let adSource = AdSource(tag: imaTag, ofType: .ima) // Or with URL object let adSourceURL = URL(string: imaTag)! let adSourceFromURL = AdSource(tag: adSourceURL, ofType: .ima) ``` ``` -------------------------------- ### Configure a Media Playlist Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/configuration.md Use PlaylistConfig to queue multiple sources for sequential playback. You can also specify options for how the playlist behaves, such as preloading. ```swift let playlistConfig = PlaylistConfig( sources: [source1, source2], options: PlaylistOptions(preloadAllSources: false) ) ``` -------------------------------- ### Subscribe to Source Events Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-source.md Subscribe to all source-related events using the Combine framework. This example demonstrates how to specifically handle SourceErrorEvent and access its error property. ```swift source.events.on(SourceEvent.self) .sink { if let errorEvent = event as? SourceErrorEvent { print("Source error: \(errorEvent.error)") } } .store(in: &cancellables) ``` -------------------------------- ### Create Source from SourceConfig Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-source.md Use this factory method to create a basic Source instance from a SourceConfig. Ensure you have a valid SourceConfig object. ```swift let sourceConfig = SourceConfig(url: streamURL, type: .hls) let source = SourceFactory.createSource(from: sourceConfig) ``` -------------------------------- ### Configure Stream Source Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/getting-started.md Create a SourceConfig object to load streams. Specify the stream URL and the type of streaming protocol (HLS, DASH, Progressive MP4). ```swift let sourceConfig = SourceConfig(url: streamURL, type: .hls) ``` -------------------------------- ### Configure Player and Analytics Licenses in Code Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/getting-started.md Set your player and analytics license keys programmatically when creating the player instance. Ensure you have obtained these keys from the Bitmovin dashboard. ```swift let playerConfig = PlayerConfig() playerConfig.key = "your-player-license-key" let analyticsConfig = AnalyticsConfig(licenseKey: "your-analytics-key") let player = PlayerFactory.createPlayer( playerConfig: playerConfig, analytics: .enabled(analyticsConfig: analyticsConfig) ) ``` -------------------------------- ### Integrate Bitmovin Player with AVPlayerViewController Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-ui.md Demonstrates how to create and configure a Bitmovin Player, then integrate it with a native `AVPlayerViewController` for a system UI experience. Ensure to replace placeholders like `playerLicenseKey` and `streamURL`. ```swift import AVKit import BitmovinPlayer class SystemUIViewController: UIViewController { var player: Player! override func viewDidLoad() { super.viewDidLoad() let playerConfig = PlayerConfig() playerConfig.key = playerLicenseKey player = PlayerFactory.createPlayer( playerConfig: playerConfig, analytics: .enabled(analyticsConfig: analyticsConfig) ) // Create AVPlayerViewController with Bitmovin Player let avController = AVPlayerViewController() // Register Bitmovin player with AVPlayerViewController // (Implementation details depend on SDK integration) addChild(avController) view.addSubview(avController.view) avController.view.frame = view.bounds avController.didMove(toParent: self) let sourceConfig = SourceConfig(url: streamURL, type: .hls) player.load(sourceConfig: sourceConfig) } deinit { player?.destroy() } } ``` -------------------------------- ### Handle Offline State with Switch Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-offline.md Conditionally execute actions based on the current offline state of the content. This example demonstrates handling downloaded, downloading, and not downloaded states. ```swift switch offlineContentManager.offlineState { case .downloaded: print("Ready for offline playback") case .downloading: print("Download in progress") case .notDownloaded: print("Not downloaded") default: break } ``` -------------------------------- ### BitmovinUserInterfaceConfig Initializer Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-ui.md Initializes the UI configuration with default settings. This is the primary way to create a new UI configuration object. ```APIDOC ## BitmovinUserInterfaceConfig Initializer ### Description Creates UI configuration with default settings. ### Signature ```swift init() ``` ### Example ```swift let uiConfig = BitmovinUserInterfaceConfig() playerConfig.styleConfig.userInterfaceConfig = uiConfig ``` ``` -------------------------------- ### Chromecast Error Handling Implementation Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-casting.md Implement a listener to gracefully handle various Chromecast errors. This example shows how to map specific error codes to user-friendly messages and display them. ```swift class CastingErrorHandler: NSObject, PlayerListener { var player: Player! func onEvent(_ event: Event, player: Player) { if let castErrorEvent = event as? CastErrorEvent { handleCastError(castErrorEvent) } } private func handleCastError(_ event: CastErrorEvent) { switch event.code { case "CAST_SESSION_ERROR": showUserMessage("Failed to connect to Chromecast") case "CAST_LOAD_ERROR": showUserMessage("Content cannot be played on Chromecast") case "CAST_NETWORK_ERROR": showUserMessage("Network error during casting") default: showUserMessage("Chromecast error: \(event.message)") } } private func showUserMessage(_ message: String) { DispatchQueue.main.async { let alert = UIAlertController( title: "Chromecast", message: message, preferredStyle: .alert ) alert.addAction(UIAlertAction(title: "OK", style: .default)) UIApplication.shared.windows.first?.rootViewController?.present(alert, animated: true) } } } ``` -------------------------------- ### Initialize AnalyticsConfig Source: https://github.com/bitmovin/bitmovin-player-ios-samples/blob/main/_autodocs/api-reference-analytics.md Use this initializer to create an AnalyticsConfig object with your license key. This is required to enable analytics. ```swift init(licenseKey: String) ```