This article details how to integrate CDN Mesh Delivery into your mobile app using Viaccess-Orca VOPlayer.
Since DNA 2.15, due to the update of WebRTC, we no longer support iOS under version 10.
If you still require it, we recommend to stick to our SDK 3.12.x
Project setup
CocoaPods
Cocoapods 1.6.0 + is recommended
To integrate StreamrootSDK into your Xcode project using CocoaPods, specify this in your Podfile
:
use_frameworks!
target ' <Your Target Name >'
pod 'StreamrootSDK', '~> 3.23.0'
end
Then, run the following command:
$ pod update
Finally, open the generated Workspace.
Carthage
Add the dependencies to the Cartfile:
binary "https://sdk.streamroot.io/ios/StreamrootSDK.json" ~> 3.23.0
github "daltoniam/Starscream" ~> 3.1.0
github "getsentry/sentry-cocoa" ~> 4.4.0
github "apple/swift-protobuf" ~> 1.6.0
Link the frameworks to your project:
Manually
1. Install dependencies
Current dependencies versions can be found here.
2. Downloads Streamroot SDK
StreamrootSDK.framework: https://sdk.streamroot.io/ios/StreamrootSDK/3.22.0/StreamrootSDK.framework.zip
Copy script: http://sdk.streamroot.io/ios/copy_streamroot_sdk
3. Add StreamrootSDK.framework to your project
4. Link Binary With Libraries
Drag and drop StreamrootSDK.framework
into your Xcode project. Make sure StreamrootSDK.framework
has been added to your target's build phases under Link Binary With Libraries
.
5. Copy the framework
There is no need for the script if using ARM version.
Create a new build phase (New Run Script Phase
) to call the copy_streamroot_sdk
script.
Add the folder containing the StreamrootSDK.framework
in the Input Files
field. It defaults to $(SRCROOT)/
if none input file is set.
Notes: Make sure to have all the dependencies installed in your project (ref above);
For Objective-C projects, set Always Embed Swift Standard Libraries
to yes
in your target's build settings.
Integrate Streamroot SDK
1. Import the SDK
import StreamrootSDK
2. Set the streamrootKey
In the Project Navigator, right click on the main target "Info.plist", and "Open as" → "Source Code".
Add the following lines with the values of the right parameters:
<key>Streamroot</key>
<dict>
<key>Key</key>
<string>streamrootKey</string>
</dict>
Here, <streamrootKey>
refers to your Streamroot key that you will find in the Account section of the Streamroot Dashboard. If you don't have a Streamroot Key, you can register for a free trial account on our website.
3. Declare the Mesh Delivery Client as an Instance Variable
var dnaClient: DNAClient?
4. Build and start the Mesh Delivery Client
do { let playerInteractor = VOPlayerInteractor(self.voPlayer) dnaClient = try DNAClient.builder() .dnaClientDelegate(playerInteractor) .latency(30) .streamrootKey(<#streamrootKey#>) .start(manifestUrl) } catch let error { print("\(error)") }
Parameter name | Mandatory | Description |
---|---|---|
manifestUrl | Yes | The HLS .m3u8 master playlist URL needed to be passed to the dnaClient |
latency | Yes | The delay between the playback time and the live edge. To get the best offload capacity, we recommend setting 30s. |
streamrootKey | Yes | The unique Streamroot key that we have assigned to you; make sure it is identical to the one provided in the Account section of your dashboard. |
Other DNA options can be called in the builder. Please refer to this article to learn more about them.
5. Play the stream
if let localPath = self.dnaClient?.manifestLocalURLPath { voPlayer!.contentURL = URL(string: localPath) } else { voPlayer!.contentURL = contentURL } voPlayer!.prepareToPlay()
localUrl
refers to the HLS .m3u8
master playlist URL that will be passed to the player.
6. Implement DNAClientDelegate
It is first needed to add the DNAClientDelegate
.
class VOPlayerInteractor: DNAClientDelegate { private let player: VOPlayer public init(_ player: VOPlayer) { self.player = player } func playbackTime() -> Double { return player.currentPlaybackTimeAbsolute } func loadedTimeRanges() -> [NSValue] { let seekableRange = player.httpStreamingSeekableRange let range = TimeRange(start: Double(seekableRange.lowerBound), duration: Double(seekableRange.upperBound - seekableRange.lowerBound)) return [NSValue(timeRange: range)] } func updatePeakBitRate(_ bitRate: Double) { player.httpStreamingMaximumBitrate = Int(bitRate) } public func bufferTarget() -> Double { return Double(player.getCurrentBufferLevel) } public func setBufferTarget(_ target: Double) { } }
Method name | Mandatory | Description |
---|---|---|
playbackTime | Yes | Must return the current time of the player in seconds. |
loadedTimeRanges | Yes | Must return an array of NSValue. Each NSValue must contain a TimeRange object (in seconds). |
bitrate | Yes | Must be implemented to update the player with the new bitrate. |
bufferTarget | No | Should be implemented to update the player with dynamic buffer target. |
7. Integrate the QoS module (optional)
This QoS module will allow you to link VOPlayer events to our SDK in order to get accurate metrics regarding the client session.
If this QoS module isn't implemented, a default module directly embedded in the SDK will be used instead.
class VOQosModuleWrapper: NSObject, VOPlayerObserver {
let dnaQoSModule: QosModule = DNAQos.module(type: .custom)
private let player: VOPlayer
public init(_ player: VOPlayer) {
self.player = player
super.init()
player.add(self)
}
func onPlayerEvent(_ event: VOPlayerEvent!) {
let type = event.type
switch type {
case .bufferingIndicationDidChangeNotification:
self.dnaQoSModule.playerStateDidChange(PlaybackState.buffering)
case .playbackDidFailNotification:
self.dnaQoSModule.playbackErrorOccurred()
case .playbackDidFinishNotification:
self.dnaQoSModule.playerStateDidChange(PlaybackState.ended)
case .seekCompleteNotification:
self.dnaQoSModule.playerStateDidChange(PlaybackState.seeking)
fallthrough
default:
if player.isPlaying {
self.dnaQoSModule.playerStateDidChange(PlaybackState.playing)
break
}
}
}
deinit {
player.remove(self)
}
}
It is then required to call the QosModule in the builder.
do {
let playerInteractor = VOPlayerInteractor(self.voPlayer)
let qosModuleWrapper = VOQosModuleWrapper(self.voPlayer)
dnaClient = try DNAClient.builder()
.dnaClientDelegate(playerInteractor)
.qosModule(qosModuleWrapper)
.start(manifestUrl)
} catch let error {
print("\(error)")
}
Stop the SDK
override func viewDidDisappear(_ animated: Bool) {
dnaClient?.stop()
}
Disable App Transport security
In the Project Navigator, right click on "Info.plist", and "Open as" → "Source Code".
Add the following lines with the corresponding parameters values.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>