Player Configuration
Set peak bitrate
Configure the player's variant adaptation logic with the maximum bitrate constraint.
player.set(preferences: [.preferredPeakBitRate(bitrate: 842_742)])
Note: If you set preferences before the player enters the loaded state, these preferences are considered on-load preferences and override any preference set using the
load(with preferences: Preference...)method. If you set preferences during playback, they're applied to the player immediately.
Set initial forward buffer duration
Set the preferred initial forward buffer duration to optimize playback startup
time. This setting applies only before playback starts. To reset, set the
value to 0.0, which uses the system-preferred buffer. Set this preference
before calling the play() or load() API.
player.set(preferences: [.preferredInitialForwardBufferDuration(duration: 1.0)])
Set forward buffer duration after rebuffer
To change the playback preference, either reset it to the default value by
setting the value to 0.0, or set a new value to use after playback starts.
The new value applies only after the video has started playing. Setting this
to 0.0 uses the system buffer duration, which is based on different factors.
player.set(preferences: [.preferredForwardBufferDurationAfterRebuffer(duration: 8.0)])
Set initial playback time
Set the initial time from which the player should start playback.
player.set(preferences: [.initialPlaybackTime(time: 10.0)])
Set maximum resolution
Set the preferred maximum resolution for playback video by passing the size (height and width).
player.set(preferences: [.preferredMaximumResolution(size: CGSize(width: 1080, height: 720))])
Set network resources for live streaming
The canUseNetworkResourcesForLiveStreamingWhilePaused property indicates
whether the player item can use network resources to keep the playback state
up to date while paused. When you set this property to true, the
seekableTimeRanges property is periodically updated to reflect the current
state of the live stream.
player.set(preferences: [.canUseNetworkResourcesForLiveStreamingWhilePaused(paused: true)])
Setting MaximumResolution For Expensive Networks
By setting this preference, player may adjust the video resolution based on network condition to improve the user’s experience.
player.set(preferences: [.preferredMaximumResolutionForExpensiveNetworks(size: CGSize(width: 1080, height: 720))])
Available from, iOS 15.0+, tvOS 15.0+
Setting starts On First Eligible Variant
Setting startsOnFirstEligibleVariant indicates whether playback starts with the first eligible variant that appears in the stream’s main playlist. The default value of this property is false.
player.set(preferences: [.startsOnFirstEligibleVariant(eligibleVariant: true)])
Note: Available from iOS 14.0+ and tvOS 14.0+.
Set peak bit rate for expensive networks
Set preferredPeakBitRateForExpensiveNetworks to set the maximum bit rate for
streaming content when the player is connected to an expensive network.
player.set(preferences: [.preferredPeakBitRateForExpensiveNetworks(preferredPeakBitRate: 5397000.0)])
Note: The value of the
preferredPeakBitRateproperty applies unconditionally. This property value has no effect if it's less restrictive than thepreferredPeakBitRatevalue. Available from iOS 15.0+ and tvOS 15.0+.
Protect playback from insecure devices
You can allow or disallow playback on insecure devices, that is, jailbroken devices. By default, FLPlayer allows playback on insecure devices.
player.set(preferences: [.allowPlaybackOnInsecureDevice(allow: false)])
You can enable additional security checks on top of detecting jailbreak:
// Opt in to additional checks
let additionalChecks = [.emulatorCheck, .debuggerCheck, .proxyCheck, .integrityCheck(bundleID: "com.organisation.appname")]
player.set(preferences: [.enableSecurityChecks(additionalChecks: additionalChecks)])
You can enable the following opt-in checks:
| Name | Description |
|---|---|
| Debugger detection | Determines if the application is being debugged |
| Emulator detection | Determines if the application runs in an emulator |
| Proxy detection | Determines if an HTTP proxy is set in the iOS settings |
| Device tampering detection | Determines if the application has been tampered |
Note: We recommend you integrate these checks with a remote configuration to enable or disable each detection and select the security level based on your requirements.
Determine device security status
You can access device security status through PlatformClient:
let device = FLPlatformCoreFactory.createDevice()
let result = device.securityStatus(bundleID: "com.org.app")
if !result.status {
// print(result.failureReason)
}
Trick play
Set the factor by which to speed up playback.
// Standard playback rate is 1 and paused is 0.
// You can use rates other than 0.0 and 1.0
// if the stream supports trick play.
player.rate = 1.25;
Picture in picture
FLPlayer library supports picture in picture (PiP). Your application must include the Audio, AirPlay & Picture in Picture capability. Picture in picture is possible only on iPad and on selected models. This is a platform limitation.
AirPlay
FLPlayer library supports AirPlay 2. Your application must include the Audio, AirPlay & Picture in Picture capability. Note that AirPlaying FairPlay-protected content requires an on-demand license key, so you can't AirPlay offline content.
Now playing info
iOS displays now-playing information on the device lock screen and in the
multimedia controls in the multitasking UI. If you direct playback of your
media to Apple TV through AirPlay, the now-playing information appears on the
television screen. If you connect a device to an iPod accessory, such as in a
car, the accessory may display now-playing information. Pass nil to clear
the existing now-playing info.
// Setting NowPlayingInfo
var nowPlayingInfo = [String: Any]()
if #available(iOS 10.3, *) {
nowPlayingInfo[MPNowPlayingInfoPropertyAssetURL] = <url>
} else {
// Fallback on earlier versions
}
// Sample inputs
nowPlayingInfo[MPMediaItemPropertyTitle] = "Content Title"
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = player.duration
nowPlayingInfo[MPMediaItemPropertyMediaType] = MPMediaType.anyVideo.rawValue
nowPlayingInfo[MPNowPlayingInfoPropertyDefaultPlaybackRate] = 1.0
nowPlayingInfo[MPMediaItemPropertyArtist] = "Artist"
nowPlayingInfo[MPMediaItemPropertyAlbumArtist] = "Album Artist"
nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = "Album Title"
#if os(iOS)
player.nowPlayingInfo = nowPlayingInfo
#endif
Thumbnail preview
Thumbnail preview lets users see a preview image of the video while seeking. The player uses a series of images woven into a sprite from a given URL to retrieve the corresponding image for a playhead position.
Set up thumbnail preview
This section describes how to create and configure thumbnail preview.
Create thumbnail configuration
ContentThumbnailPreviewConfiguration describes the URL, dimensions, and
duration of each image in each sprite.
| Name | Type | Description |
|---|---|---|
| endPoint | String | The fully formed sprite image URL that combines the endpoint URL and generic URL suffix, which includes the flag ~index~. The player calculates the sprite index based on the given position and replaces ~index~ with the required index to construct the URL. |
| noOfcolumns | Int | The number of columns in each sprite image. |
| noOfRows | Int | The number of rows in each sprite image. |
| keyFrameDuration | Int | The time (in seconds) that each thumbnail in each sprite image corresponds to. |
| thumbnailWidth | Int | The width (in pixels) of each thumbnail in each sprite image. |
| thumbnailHeight | Int | The height (in pixels) of each thumbnail in each sprite image. |
let thumbnailConfiguration: ContentThumbnailPreviewConfiguration = FLPlayerFactory.thumbnailConfiguration(
endPoint: spriteURL,
noOfColumns: columns,
noOfRows: rows,
keyFrameDuration: frequency,
thumbnailHeight: height,
thumbnailWidth: width
)
Pass information to the player
Thumbnail preview is an optional feature. You can opt in by passing a
ContentThumbnailPreviewConfiguration object to the corresponding player
instance. For more information, see
Player creation.
// If using AVURLAsset to create player
let player = FLPlayer.player(
asset: avURLAsset,
thumbnailConfiguration: thumbnailConfiguration
)
// If using content URL to create player
let player = FLPlayer.player(
contentURL: contentURL,
thumbnailConfiguration: thumbnailConfiguration
)
Implement thumbnail preview
This section describes how to call the API to get the thumbnail image.
Call the getThumbnail API
You can get the preview image for a particular position by calling the
getThumbnail extension API on the player instance. The API returns the
preview image for the given position as a UIImage.
| Parameter | Type | Description |
|---|---|---|
| progress | TimeInterval | The position of the playhead for which to retrieve the thumbnail, in seconds. |
| completionHandler | @escaping (UIImage) -> Void | The callback function that returns a UIImage of the thumbnail. |
player.getThumbnail(for: progress, completionHandler: { [weak self] thumbnail in
// Display preview image as required
})
You typically call this function with a scrub bar listener attached to the player that listens to all seeking activity from the user.
SMPTE-TT subtitles
SMPTE-TT is a bitmap or image-based subtitle format in which subtitle information is embedded within the stream and delivered to the client as XML through ID3 timed metadata. Because AVPlayer doesn't support this format, we added custom support for SMPTE-TT subtitle rendering in the Quickplay Player.
Alternatively, you can deliver SMPTE-TT subtitles using a sidecar approach, where the entire subtitle content is provided upfront in an XML file covering the full duration of the media.
Enable SMPTE-TT subtitle rendering
Enable this player preference to instruct the player to render SMPTE-TT subtitles.
Note: This is a resource-intensive operation, so enable it only for channels that support SMPTE-TT subtitles.
XML through ID3 event
let player = FLPlatformPlayerFactory.player(asset: urlAsset, thumbnailConfiguration: nil)
player.setPreference(.enableAdditionalSubtitle([.SMPTE_ID3]))
XML through sidecar load
let language = SubtitleLanguage(endpoint: "Configure EndPoint", languageCode: "Language code (en)")
let subtitleConfiguration = SubtitleConfiguration(languages: [language])
player.set(preferences: [.enableAdditionalSubtitle([.SMPTE_SIDECAR(subtitleConfiguration)])])
let player = FLPlatformPlayerFactory.player(asset: urlAsset, thumbnailConfiguration: nil)
player.setPreference(.enableAdditionalSubtitle([.SMPTE_SideLoad(subtitleConfiguration)]))
Limitations for SMPTE_ID3
The following limitations apply to SMPTE_ID3:
- Not supported on tvOS.
- Not supported during AirPlay playback.
- Not supported in picture-in-picture mode.
- SMPTE-TT subtitle tracks become available only after playback starts, whereas natively supported subtitles are available before playback begins.
- Multi-language SMPTE-TT subtitles aren't supported on iOS 16 and below because ID3 timed metadata isn't reported to the client.
- Subtitle selection depends on the
enableAdditionalSubtitlepreference and the available tracks in the stream.
Limitations for SMPTE_SideLoad
The following limitations apply to SMPTE_SideLoad:
- Not supported on tvOS.
- Not supported during AirPlay playback.
- Not supported in picture-in-picture mode.
- SMPTE-TT subtitle tracks become available only after playback starts, whereas natively supported subtitles are available before playback begins.
- Subtitle selection depends on the
enableAdditionalSubtitlepreference and the available tracks in the stream.
Subtitle selection behavior
The following table shows subtitle selection behavior based on preferences:
| Preference | Available subtitle tracks | Displayed subtitle |
|---|---|---|
'SMPTE_ID3' | 'SMPTE_ID3' | 'SMPTE_ID3' |
'SMPTE_SideLoad' | 'SMPTE_SideLoad' | 'SMPTE_SideLoad' |
'SMPTE_SideLoad, SMPTE_ID3' | 'SMPTE_SideLoad, SMPTE_ID3' | 'SMPTE_ID3' |
undefined or no preference | 'Native supported' | 'Native supported' |
undefined or no preference | 'SMPTE_ID3' | 'No tracks display' |