[object Object] Icon

Encoding
Learn how to create, start, manage and modify Encodings

[object Object] Icon

Player
Learn how to create, start, manage and modify Players

[object Object] Icon

Analytics
Learn how to create, start, manage and modify Analyticss

Docs Home
User shortcuts for search
Focus by pressing f
Hide results by pressing Esc
Navigate via   keys

Tue Apr 27 2021

Migration Guide - iOS/tvOS SDK v2 to v3

OverviewLink Icon

The following points will explain all breaking changes, renamed methods and configuration objects, as well as minimum requirements that need to be fullfilled to migrate and benefit from all the major performance and usability improvements that become available with v3.

V3 of the iOS/tvOS Player SDK marks a new direction where the player itself and the sources it plays back become more decoupled. This allows for sources to have their own lifecycle, emit their own events and offer functionality even when the source is currently not being played back. For more details on how the top-level components fit together in V3, refer to the Player, Source and PlaylistApi documentation.

With this new direction comes the ability to load multiple sources into the player via a PlaylistConfig. The player will play back one source after another until it reaches the end of the playlist. Sources in the playlist can already preload content before they are being played back, leading to gapless playback across sources without the overhead of unloading and loading a new source like in V2.


Minimum RequirementsLink Icon

Package manager: v3 SDK will be delivered as pre-compiled XCFramework through

  • Cocoapods 1.9+ or
  • Carthage 0.37.0+

Supported iOS/tvOS Platforms (Deployment Target): With v3 the support for iOS 10 and iOS 11 will be dropped. The adoption rate for more recent iOS/tvOS versions is very high, therefore the overall usage of iOS10/11 dropped already to very low value, that would not justify that much backward compatibility. In case you still need to support these platforms, you'd would have to use v2 of our SDK still.

  • iOS 12 or higher
  • tvOS 12 or higher

Google Cast:

  • CAF compatible v3 receiver applications required

Bitmovin Player UI:

  • v3.25.x or higher (default and custom versions)

LimitationsLink Icon

  • The initial 3.0.0 version does not support loading live-streams inside a playlist. As we can't detect the type until we actually start loading the source there won't be an error when loading a live-stream. Doing so will result in unexpected behavior.

  • The event transition towards SourceEvents isn't finished yet. More events will be migrated to SourceEvents and emitted on a per-source basis over the next releases. If you plan on directly using the types PlayerEvent and SourceEvent anywhere, be aware that there could be API breaking change in the future when changing the super-type of event classes. Learn More

RenamingsLink Icon

This table lists all naming changes from v2 to v3 with its replacements.

v2v3
*Configuration*Config
SourceItemSourceConfig
SourceItem.itemTitleSourceConfig.title
SourceItem.itemDescriptionSourceConfig.sourceDescription
BMPBitmovinPlayerViewPlayerView
MediaSourceTypeSourceType
MediaSourceType.HLSSourceType.hls
MediaSourceType.DASHSourceType.dash
Player.sourceMetadataWas moved to Source.metadata
RemoteControlAPIRemoteControlApi
UserInterfaceAPIUserInterfaceApi
Boolean properties could be accessed without a proper prefix (e.g. .isPlaying was accessible via .playing from ObjC)All Boolean properties now have a proper prefix
BMP prefix when using type/enum from SwiftNo more BMP prefixes for types/enums used from Swift

RemovalsLink Icon

This table lists API which was removed in v3 with its replacements (if any).

v2v3
CastConfigurationRemoteControlConfig
Player.preloadremoved without replacement as this was never implemented properly
Player.streamTypeis now represented through SourceConfig.type
OfflineContentManager.download(minimumBitrate:)The minimumBitrate can now be set only via the DownloadConfig
Player.setupremoved without replacement (Details)
ConfigurationUpdatedEventremoved as a configuration can't be updated anymore
PlayerConfiguration.sourceConfigurationreplaced with new loading workflows (Details)
Jsonableremoved without replacement as we no longer support loading a web-based PlayerConfig

Player SetupLink Icon

We no longer expose the concrete implementation for the Player. Therefore You can no longer create a direct instance from the Player. From now on the only way to create a player instance is using the PlayerFactory:

If you are migrating from 2.50.x or lower Please make sure to apply the migration guide to v2.51+ first

v2

1let player = Player(configuration: configuration)
2// or
3let player = Player() // when no PlayerConfig is needed

v3

1let player = PlayerFactory.create(playerConfig: playerConfig)
2// or
3let player = PlayerFactory.create() // when no PlayerConfig is needed

Loading A SourceLink Icon

SourceConfig

The SourceItem was replaced by SourceConfig and the old SourceConfiguration was removed completely. SourceConfig from now on refers to the old SourceItem.

As our SourceConfig was based on the SourceConfig from the web-player there was the possibility to set up multiple configurations for each streaming technology (HLS, Dash ...). We want to detach from this concept starting with v3. Therefore we deprecated all the legacy types which were used to set up those different sources:

  • MediaSource
    • AdaptiveSource
      • HLSSource
      • DashSource
    • ProgressiveSource

The new designated way to create a SourceConfig is to use the URL and the type directly on the SourceConfig initializer:

v2

1let sourceConfig = SourceConfig(hlsSource: HLSSource(url: streamUrl))

v3

1let sourceConfig = SourceConfig(url: streamUrl, type: .HLS)

Source

The Source is, next to the Player, the new main component in the SDK. See the documentation for more detailed insights.

To create an instance of a Source a SourceConfig is needed. The SourceConfig can then be passed to the SourceFactory to create a Source instance.

1let source = SourceFactory.create(from: sourceConfig)

To load a Source into the Player we created a new load method that accepts a Source:

1player.load(source: source)

If you don't need to handle Sources explicitly you can still load a SourceConfig directly:

1// v3
2player.load(sourceConfig: sourceConfig)

Event HandlingLink Icon

Each Source can have its own listeners by now. To enable that we split the existing PlayerEvents into PlayerEvent and SourceEvent.

v2

1class PlayerEvent: NSObject { ... }
2class SourceLoadedEvent: PlayerEvent { ... }

v3

1protocol Event: NSObject { ... }
2protocol SourceEvent: Event { ... }
3class SourceLoadedEvent: SourceEvent { ... }

We introduce the new Event protocol as the root type for all events. Each SourceEvent (e.g. SourceLoadedEvent) implements the SourceEvent protocol and each PlayerEvent (e.g. PlayEvent) extends the PlayerEvent super class.

Events which are already SourceEvents:

  • DurationChangedEvent
  • SourceLoadEvent
  • SourceLoadedEvent
  • SourceUnloadEvent
  • SourceUnloadedEvent
  • SourceWarningEvent
  • SourceErrorEvent

Every SourceEvent emitted from the currently active Source will be also emitted through the Player. This means that SourceEvents will be received for the according Source instance or directly via the Player for the currently active Source.

1extension PlaybackViewController: PlayerListener {
2 // Receive the DurationChangedEvent through the player only for the active source
3 func onDurationChanged(_ event: DurationChangedEvent, player: Player) {
4 // ...
5 }
6}
7
8extension PlaybackViewController: SourceListener {
9 // Receive the DurationChangedEvent on the source emitting the event (even if the source is not active)
10 func onDurationChanged(_ event: DurationChangedEvent, source: Source) {
11 // ...
12 }
13}

Source Listener

If you want to listen to SourceEvent and receive them on the actual source (also for non-active Sources) you can attach a SourceListener to a Source:

1// v3
2source.add(listener: sourceListener)

Sender

To distinguish which source emitted an event we added the sender to the SourceListener methods. To have a unified API we decided to also add this to the PlayerListener and to the UserInterfaceListener:

v2

1func onPlay(_ event: PlayEvent) {
2 // If the same listener handles multiple player instances there is no way to detect which player emitted the event
3}

v3

1func onPlay(_ event: PlayEvent, player: Player) {
2 // The player instance which is associated with the emitted event
3}
4
5func onSourceLoaded(_ event: SourceLoadedEvent, source: Source) {
6 // The source instance which is associated with the emitted event
7}

DurationChangedEvent

The DurationChangedEvent is no longer emitted initially when the duration is available the first time. As replacement access the duration when the SourceLoadedEvent is received.

As the SourceLoaded and the SourceUnloaded events will now be emitted per source (and also for non-active sources), we needed to add replacements to ensure old workflows still work as expected.

v2v3
SourceLoadedEvent was emitted when we were about to load a source indicating the player started a source life-cyclePlayerActiveEvent is emitted when the player received one or more sources and is about to start loading
SourceUnloadedEvent was emitted after we finished unloading a source indicating the player finished the source life-cyclePlayerInactiveEvent is emitted when all sources were removed from the player and as no more sources attached

UI / ViewLink Icon

Default Bitmovin Player Web UI

The new v3 iOS SDK isn’t compatible with Bitmovin Player Web UI v2.x. To use the v3 SDK with a customized Bitmovin Player Web UI you will need to update your Player Web UI version to v3.x. The recommended version is 3.25.0 and above.

We continue to support Bitmovin Player Web UI v2.x for use with our v2 iOS SDK only. More details on the Bitmovin Player Web UI can be found here.

Customization

To create a custom UI you no longer need to sub-class PlayerView, you can just subclass UIView by now. The PlayerView should only be used if you want to use any of the UIs we provide.

We added new methods on the Player protocol to allow registering an AVPlayerLayer or an AVPlayerViewController to give more flexibility about where the video should be rendered.

v2

1class CustomView: PlayerView {
2 override init(player: Player, frame: CGRect) {
3 super.init(player: player, frame: frame)
4 }
5}

v3 Using AVPlayerLayer.

1class CustomView: UIView {
2 init(player: Player, frame: CGRect) {
3 super.init(frame: frame)
4
5 player.register(playerLayer)
6 }
7
8 var playerLayer: AVPlayerLayer {
9 layer as! AVPlayerLayer
10 }
11
12 override class var layerClass: AnyClass {
13 AVPlayerLayer.self
14 }
15}

Using AVPlayerViewController.

1let avPlayerViewController = AVPlayerViewController()
2player.register(avPlayerViewController)

ExamplesLink Icon

We have updated our iOS Samples GH Repository as well to get you started with our new major version 3 for iOS/tvOS. Check them out!

https://github.com/bitmovin/bitmovin-player-ios-samples

Give us feedback