This guide walks through integration with iOS and TVOS AVPlayer player to collect video performance metrics with Mux data.
Features
Install the Mux Data SDK
Initialize the monitor for your AVPlayer instance
Make your data actionable
Set or update metadata after monitor
Advanced
Release notes
Mux Data integration for AVPlayer supports applications running on iOS 12.0 or newer, tvOS 12.0 or newer, and Mac Catalyst that use AVPlayerViewController
, AVPlayerLayer
, or a standalone AVPlayer
playing audio or if presented with a fixed size. Applications running on visionOS 1.0 and higher are also supported if they use AVPlayerViewController
or a standalone AVPlayer
playing audio or if presented with a fixed size.
This integration uses Mux's core Objective-C SDK and the full source can be seen here: muxinc/mux-stats-sdk-avplayer. This SDK is packaged as an xcframework.
The following data can be collected by the Mux Data SDK when you use the AVPlayer SDK, as described below.
Supported Features:
renditionchange
eventsPackaged with: cocoapods, SPM and carthage. Request Latency is not available.
https://github.com/muxinc/mux-stats-sdk-avplayer.git
https://github.com/muxinc/mux-stats-sdk-avplayer.git
Next
.MUXSDKStats
follows SemVer, we recommend setting the "Rules" to install the latest version and choosing the option "Up to Next Major". Here's an overview of the different SPM Dependency Rules and their semantics.Open your Package.swift file, add the following to dependencies
:
.package(
url: "https://github.com/muxinc/mux-stats-sdk-avplayer",
.upToNextMajor(from: "4.0.0")
),
Note that MUXSDKStats
has a dependency on MuxCore
, so you will see that MuxCore
gets installed as well.
As of Xcode 14.3.1 integrating the Mux SDKs as part of a shared framework using Swift Package Manager library targets is now supported. An example for setting this up is available here.
To install with CocoaPods, modify your Podfile to use frameworks by including use_frameworks!
and then add the following pods to your Podfile:
pod 'Mux-Stats-AVPlayer', '~>4.0'
This will install Mux-Stats-AVPlayer
and the latest current release of our core Objective-C Library.
Next, add correct import statement into your application.
@import MUXSDKStats;
Get your ENV_KEY
from the Mux environments dashboard.
Env Key is different than your API token
ENV_KEY
is a client-side key used for Mux Data monitoring. These are not to be confused with API tokens which are created in the admin settings dashboard and meant to access the Mux API from a trusted server.
The example below uses monitorAVPlayerViewController
. If you are using AVPlayerLayer
, use monitorAVPlayerLayer
instead.
The playerName
parameter is a string that identifies this instance of your player. When calling destroyPlayer
or videoChangeForPlayer
later on, you will need this string. Each instance of a player that runs simultaneously in your application should have a different playerName
.
If you are using SwiftUI, attach the monitor in the onAppear
action for your view. This ensures that the Mux Data SDK is able to get the dimensions of the view which is used to calculate video quality metrics.
MUXSDKCustomerPlayerData *playerData = [[MUXSDKCustomerPlayerData alloc] initWithPropertyKey:@"ENV_KEY"];
MUXSDKCustomerVideoData *videoData = [MUXSDKCustomerVideoData new];
// insert videoData metadata
videoData.videoTitle = @"Title1";
videoData.videoSeries = @"animation";
MUXSDKCustomerData *customerData = [[MUXSDKCustomerData alloc] initWithCustomerPlayerData:playerData
videoData:videoData
viewData:nil
customData:nil
viewerData:nil];
_playerBinding = [MUXSDKStats monitorAVPlayerViewController:_avplayerController
withPlayerName:@"mainPlayer"
customerData:customerData];
For more complete examples check the 3 demo apps in the repo. There is one demo app for iOS objective-c, one for iOS swift and another one for tvOS.
After you've integrated, start playing a video in your player. A few minutes after you stop watching, you'll see the results in your Mux data dashboard. Login to the dashboard and find the environment that corresponds to your env_key
and look for video views.
The only required field is env_key
. But without some more metadata the metrics in your dashboard will lack the necessary information to take meaningful actions. Metadata allows you to search and filter on important fields in order to diagnose issues and optimize the playback experience for your end users.
Metadata fields are provided via the MUXSDKCustomerPlayerData
and MUXSDKCustomerVideoData
objects.
For the full list of properties view the header files for this interfaces:
For more details about each property, view the Make your data actionable guide.
MUXSDKCustomerPlayerData *playerData = [[MUXSDKCustomerPlayerData alloc] initWithPropertyKey:@"ENV_KEY"];
playerData.viewerUserId = @"1234";
playerData.experimentName = @"player_test_A";
playerData.playerName = @"iOS AVPlayer";
playerData.playerVersion = @"1.0.0";
MUXSDKCustomerVideoData *videoData = [MUXSDKCustomerVideoData new];
videoData.videoTitle = @"Big Buck Bunny";
videoData.videoId = @"bigbuckbunny";
videoData.videoSeries = @"animation";
videoData.videoDuration = @(120000); // in milliseconds
videoData.videoIsLive = @NO;
videoData.videoCdn = @"cdn";
MUXSDKCustomerViewData *viewData= [[MUXSDKCustomerViewData alloc] init];
viewData.viewSessionId = @"some session id";
MUXSDKCustomData *customData = [[MUXSDKCustomData alloc] init];
[customData setCustomData1:@"my-data-string"];
[customData setCustomData2:@"my-custom-dimension-2"];
MUXSDKCustomerViewerData *viewerData = [[MUXSDKCustomerViewerData alloc] init];
viewerData.viewerApplicationName = @"MUX DemoApp";
MUXSDKCustomerData *customerData = [[MUXSDKCustomerData alloc] initWithCustomerPlayerData:playerData
videoData:videoData
viewData:viewData
customData:customData
viewerData:viewerData];
_playerBinding = [MUXSDKStats monitorAVPlayerViewController:_avplayerController
withPlayerName:@"mainPlayer"
customerData:customerData];
There are some cases where you may not have the full set of metadata until after the video playback has started. In this case, you should omit the values when you first call monitorAVPlayer*
. Then, once you have the metadata, you can update the metadata with the updateCustomerDataForPlayer
method.
// Sometime later before the player is destroyed you can do this:
// The player name ("mainPlayer" in this example) should be a player that
// you have already called one of the `monitorAVPlayer` methods with
// In this example we are updating videoData, but the same can be done
// for updating playerData, customData or viewData
// Note that the values in customerData passed as nil will keep previously set data
// Note that viewerData can't be updated
MUXSDKCustomerVideoData *videoData = [MUXSDKCustomerVideoData new];
videoData.videoTitle = @"Big Buck Bunny";
videoData.videoId = @"bigbuckbunny";
MUXSDKCustomerData *customerData = [[MUXSDKCustomerData alloc] init];
customerData.customerVideoData = videoData;
[MUXSDKStats setCustomerData:customerData
forPlayer:@"mainPlayer"];
There are two cases where the underlying tracking of the video view need to be reset. First, when you load a new source URL into an existing player, and second when the program within a singular stream changes (such as a program within a live stream).
Note: You do not need to change the video info when changing to a different source of the same video content (e.g. different resolution or video format).
When you change to a new video (in the same player) you need to update the information that Mux knows about the current video. Examples of when this is needed are:
This is done by calling videoChangeForPlayer:
which will remove all previous video data and reset all metrics for the video view. You can include any metadata when changing the video but you should only need to update the values that start with video_
.
It is required to call videoChangeForPlayer:
immediately before telling the player which new source to play. This recommendation changed in v1.2.0
.
It is also required to call player.play
after replacing the current item.
If you have new player data you instead call videoChangeForPlayer
.
// Example of changing the AVPlayerItem
let videoData = MUXSDKCustomerVideoData()
videoData.videoId = "abcd123"
videoData.videoTitle = "My Great Video"
videoData.videoSeries = "Weekly Great Videos"
videoData.videoDuration = 120000 // in milliseconds
videoData.videoIsLive = false
videoData.videoCdn = "cdn"
MUXSDKStats.videoChange(forPlayer: "AVPlayer", with: videoData)
player.replaceCurrentItem(with: AVPlayerItem(url: url!))
// calling `play()` here is necessary
player.play()
In some cases, you may have the program change within a stream, and you may want to track each program as a view on its own. An example of this is a live stream that streams multiple programs back to back, with no interruptions.
In this case, call programChangeForPlayer:withCustomerData:
. This will remove all previous video data and reset all metrics for the video view, creating a new video view. You can include any metadata when changing the video but you should only need to update the values that start with video
.
If you are using Google Interactive Media Ads, and specifically either the iOS SDK GoogleAds-IMA-iOS-SDK
or the tvOS SDK GoogleAds-IMA-tvOS-SDK
then we have another
plugin library that integrates tracking of ad playback events. You should have a fully functioning Google Ads IMA integration working in your iOS or tvOS application first.
The v0.14.0
and higher releases of the Mux Google Ads IMA plugin expose a new API. If you've already integrated an earlier version documentation is available to migrate to the new API.
https://github.com/muxinc/mux-stats-google-ima.git
In order to install in your iOS application open your Package.swift
file, add the following to dependencies:
.package(
url: "https://github.com/muxinc/mux-stats-google-ima",
.upToNextMajor(from: "0.14.0")
)
The Mux Google IMA plugin is available through CocoaPods. To install it, add the following line to your Podfile:
pod 'Mux-Stats-Google-IMA'
import MuxStatsGoogleIMAPlugin
in Swift #import <MuxStatsGoogleIMAPlugin/MuxStatsGoogleIMAPlugin.h>
in Objective-CmonitorAVPlayerViewController
or monitorAVPlayerLayer
, save this value to a variable (below it's called playerBinding
)adListener
instance using the playerBinding
you created above and your applications IMA ads loader by calling MUXSDKIMAAdListener(playerBinding: playerBinding!, monitoringAdsLoader: yourAdsLoader)
.IMAAdsManager
monitoring by calling adListener.monitorAdsManager(yourIMAAdsManager)
adListener
when you send your ad requestimaListener.clientAdRequest(yourIMAAdsRequest)
to forward each IMAAdsRequest
you initiateimaListener.daiAdRequest(yourIMAStreamRequest)
to forward each IMAAdsRequest
you initiateMUXSDKIMAAdListener
will automatically intercept IMAAdsLoader
and IMAAdsManager
delegate callsMuxImaLister
with MUXSDKIMAAdListener
. MuxImaListener
supports the same new API so this step is optional, the remaining steps are applicable to MuxImaListener
. As of v0.14.0``MuxImaLister
is deprecated and will be removed in a future release.IMAAdsLoader
when calling the MUXSDKIMAAdListener
initializer. Make sure your IMAAdsLoader delegate is configured before this step.IMAAdsLoaderDelegate
calls to your delegate.IMAAdsManager
, like you've done with IMAAdsLoader
, configure your own IMAAdsManagerDelegate
first and then call monitorAdsManager
.IMAAdsManagerDelegate
calls to your delegate.dispatchEvent
, dispatchError
, and onContentPauseOrResume
from your integration.#import<MuxStatsGoogleIMAPlugin/MuxStatsGoogleIMAPlugin.h>
- (void)viewDidLoad {
// Follow the instructions from pod 'GoogleAds-IMA-iOS-SDK' to set up
// your adsLoader and set your ViewController as the delegate
//
// From your ViewController, when you call either
// monitorAVPlayerViewController:withPlayerName:playerData:videoData:
// monitorAVPlayerLayer:withPlayerName:playerData:videoData:
//
// You will get back a MUXSDKPlayerBinding object
[MUXSDKPlayerBinding *playerBinding] = [MUXSDKStats monitorAVPlayerViewController:_avplayerController
withPlayerName:DEMO_PLAYER_NAME
customerData:customerData];
//
// Use the MUXSDKPlayerBinding object to initialize the MuxImaListener class
//
_adsListener = [[MUXSDKIMAAdListener alloc] initWithPlayerBinding:playerBinding
monitorAdsLoader:adsLoader];
//...
// When you send your ad request, you must report it to the IMA listener so it can properly track state
[_adsListener clientAdRequest:request]; // for Client-Side Ads (the usual case)
// OR
[_adsListener daiAdRequest:daiRequest]; // for Dynamic Server-Side Ads (DAI/SSAI)
}
// when the adsLoader fires adsLoadedWithData you get a
// reference to the adsManager. Set your ViewController as the delegate
// for the adsManager
- (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData {
_adsManager = adsLoadedData.adsManager;
// Set your adsManager delegate before passing it to adsListener for monitoring
_adsManager.delegate = self;
IMAAdsRenderingSettings *adsRenderingSettings = [[IMAAdsRenderingSettings alloc] init];
adsRenderingSettings.webOpenerPresentingController = self;
[_adsManager initializeWithAdsRenderingSettings:adsRenderingSettings];
[_adsListener monitorAdsManager: _adsManager];
}
//
- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdEvent:(IMAAdEvent *)event {
// When the SDK notified us that ads have been loaded, play them.
if (event.type == kIMAAdEvent_LOADED) {
[_adsManager start];
}
}
- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdError:(IMAAdError *)error {
[_avplayer play];
}
- (void)adsManagerDidRequestContentPause:(IMAAdsManager *)adsManager {
[_avplayer pause];
}
- (void)adsManagerDidRequestContentResume:(IMAAdsManager *)adsManager {
[_avplayer play];
}
If you have enabled Picture in Picture support and are using the IMAPictureInPictureProxy
, you will need an additional step in order to track ad related metrics correctly.
#import<MuxStatsGoogleIMAPlugin/MuxStatsGoogleIMAPlugin.h>
- (void)viewDidLoad {
// Follow the instructions from pod 'GoogleAds-IMA-iOS-SDK' to set up
// your adsLoader and set your ViewController as the delegate
//
// From your ViewController, when you call either
// monitorAVPlayerViewController:withPlayerName:playerData:videoData:
// monitorAVPlayerLayer:withPlayerName:playerData:videoData:
//
// You will get back a MUXSDKPlayerBinding object
[MUXSDKPlayerBinding *playerBinding] = [MUXSDKStats monitorAVPlayerViewController:_avplayerController
withPlayerName:DEMO_PLAYER_NAME
customerData:customerData];
//
// Use the MUXSDKPlayerBinding object to initialize the MuxImaListener class
//
_adsListener = [[MUXSDKIMAAdListener alloc] initWithPlayerBinding:playerBinding
monitorAdsLoader:adsLoader];
[_adsListener setPictureInPicture:YES];
//...
// When you send your ad request, you must report it to the IMA listener so it can properly track state
[_adsListener clientAdRequest:request]; // for Client-Side Ads (the usual case)
// OR
[_adsListener daiAdRequest:daiRequest]; // for Dynamic Server-Side Ads (DAI/SSAI)
}
// when the adsLoader fires adsLoadedWithData you get a
// reference to the adsManager. Set your ViewController as the delegate
// for the adsManager
- (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData {
_adsManager = adsLoadedData.adsManager;
// Set your adsManager delegate before passing it to adsListener for monitoring
_adsManager.delegate = self;
IMAAdsRenderingSettings *adsRenderingSettings = [[IMAAdsRenderingSettings alloc] init];
adsRenderingSettings.webOpenerPresentingController = self;
[_adsManager initializeWithAdsRenderingSettings:adsRenderingSettings];
[_adsListener monitorAdsManager: _adsManager];
}
//
- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdEvent:(IMAAdEvent *)event {
// When the SDK notified us that ads have been loaded, play them.
if (event.type == kIMAAdEvent_LOADED) {
[_adsManager start];
}
}
- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdError:(IMAAdError *)error {
[_avplayer play];
}
- (void)adsManagerDidRequestContentPause:(IMAAdsManager *)adsManager {
[_avplayer pause];
}
- (void)adsManagerDidRequestContentResume:(IMAAdsManager *)adsManager {
[_avplayer play];
}
For a complete example project written in Swift with UIKit, check out the Example/DemoApp
folder of muxinc/mux-stats-google-ima
You can find more examples in the "/apps" directory of muxinc/mux-stats-sdk-avplayer on GitHub. All of these apps have examples with Google IMA ads. video-demo
is an iOS app written in Swift and TVDemoApp
is a TVOS app written in objective-c
As of 1.3.0 Mux-Stats-AVPlayer can optionally track orientationchange
events. To use this functionality, call the orientationChangeForPlayer
method.
These events will show up on the events log on the view views page.
@implementation ViewController
- (void)viewWillTransitionToSize:(CGSize)size
withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {} completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
[MUXSDKStats orientationChangeForPlayer:DEMO_PLAYER_NAME withOrientation:[self viewOrientationForSize:size]];
}];
}
- (MUXSDKViewOrientation) viewOrientationForSize:(CGSize)size {
return (size.width > size.height) ? MUXSDKViewOrientationLandscape : MUXSDKViewOrientationPortrait;
}
@end
To use with AVQueuePlayer
you will need to follow these steps:
AVPlayerItemDidPlayToEndTime
in your applicationvideoChangeForPlayer:withVideoData
Here is an example that sets up a AVQueuePlayer with two items, and listener after the first item finishes playing and passes in new videoData
.
let playName = "iOS AVPlayer"
override func viewDidLoad() {
super.viewDidLoad()
let item1 = AVPlayerItem(url: URL(string: "https://stream.mux.com/jY02nK1sxQKmJiQ7ltXY01w9LZQWdtNetE.m3u8")!)
let item2 = AVPlayerItem(url: URL(string: "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8")!)
NotificationCenter.default.addObserver(
self,
selector: #selector(self.playerItemDidReachEnd),
name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
object: item1
)
player = AVQueuePlayer(items: [item1, item2])
let playerData = MUXSDKCustomerPlayerData(environmentKey: "ENV_KEY");
playerData?.playerName = "AVPlayer"
let videoData = MUXSDKCustomerVideoData();
videoData.videoIsLive = false;
videoData.videoTitle = "Title1"
MUXSDKStats.monitorAVPlayerViewController(self, withPlayerName: playName, playerData: playerData!, videoData: videoData);
player!.play()
}
@objc func playerItemDidReachEnd (notification: NSNotification) {
let videoData = MUXSDKCustomerVideoData();
videoData.videoTitle = "Title2"
videoData.videoId = "applekeynote2010-2"
MUXSDKStats.videoChange(forPlayer: playName, with: videoData)
}
By default, the Mux Data SDK for iOS collects data about your users' device to report on the dashboard. If you wish to provide your own device metadata, you can use CustomerViewerData
to override the detected values.
// ... set up videoData, playerData, etc
MUXSDKCustomerViewerData *viewerData = [[MUXSDKCustomerViewerData alloc] init];
viewerData.viewerApplicationName = @"MUX DemoApp";
viewerData.viewerDeviceCategory = "kiosk";
viewerData.viewerDeviceModel = "ABC-12345";
viewerData.viewerDeviceManufacturer = "Example Display Systems, Inc";
MUXSDKCustomerData *customerData = [[MUXSDKCustomerData alloc] initWithCustomerPlayerData:playerData
videoData:videoData
viewData:viewData
customData:customData
viewerData:viewerData];
_playerBinding = [MUXSDKStats monitorAVPlayerViewController:_avplayerController withPlayerName:DEMO_PLAYER_NAME customerData:customerData];
By default, automaticErrorTracking
is enabled which means the Mux SDK will catch errors that the player throws and track an error
event. Error tracking is meant for fatal errors. When an error is thrown it will mark the view as having encountered an error in the Mux dashboard and the view will no longer be monitored.
If you want to disable automatic and track errors manually you can do by passing in automaticErrorTracking: false
to the monitor*
method that you are using.
Whether automatic error tracking is enabled or disabled, you can dispatch errors manually with dispatchError
.
_avplayer = player;
_avplayerController.player = _avplayer;
NSString *playerName = @"iOS AVPlayer"
NSString *environmentKey = @"yourEnvironmentKey";
MUXSDKCustomData *customData = [[MUXSDKCustomData alloc] init];
[customData setCustomData1:@"my-custom-dimension"];
MUXSDKCustomerPlayerData *playerData = [[MUXSDKCustomerPlayerData alloc] initWithEnvironmentKey:environmentKey];
MUXSDKCustomerVideoData *videoData = [[MUXSDKCustomerVideoData alloc] init];
videoData.videoTitle = @"Your Video Title";
MUXSDKCustomerViewData *viewData= [[MUXSDKCustomerViewData alloc] init];
viewData.viewSessionId = @"some session id";
MUXSDKCustomerViewerData *viewerData = [[MUXSDKCustomerViewerData alloc] init];
viewerData.viewerApplicationName = @"MUX DemoApp";
MUXSDKCustomerData *customerData = [[MUXSDKCustomerData alloc] initWithCustomerPlayerData:playerData
videoData:videoData
viewData:viewData
customData:customData
viewerData:viewerData];
_playerBinding = [MUXSDKStats monitorAVPlayerViewController:_avplayerController
withPlayerName:playerName
customerData:customerData
automaticErrorTracking: NO];
// later you can dispatch an error yourself
[MUXSDKStats dispatchError: @"1234"
withMessage: @"Something is not right"
forPlayer: playerName];
Set custom error metadata to distinguish between fatal errors or warnings and classify errors as playback failures or business exceptions. Errors categorized as warnings or as business exceptions are not considered playback failures, meaning these errors are excluded from alerting, giving a more accurate picture of the health of your system with less noise from alerts. You can find more general information on Error Categorization here.
This is an example of how to categorize an error event to be a warning.
_avplayer = player;
_avplayerController.player = _avplayer;
NSString *playerName = @"iOS AVPlayer"
NSString *environmentKey = @"yourEnvironmentKey";
MUXSDKCustomData *customData = [[MUXSDKCustomData alloc] init];
[customData setCustomData1:@"my-custom-dimension"];
MUXSDKCustomerPlayerData *playerData = [[MUXSDKCustomerPlayerData alloc] initWithPropertyKey:envKey];
MUXSDKCustomerVideoData *videoData = [MUXSDKCustomerVideoData new];
videoData.videoTitle = @"Your Video Title";
MUXSDKCustomerViewData *viewData= [[MUXSDKCustomerViewData alloc] init];
viewData.viewSessionId = @"some session id";
MUXSDKCustomerViewerData *viewerData = [[MUXSDKCustomerViewerData alloc] init];
viewerData.viewerApplicationName = @"MUX DemoApp";
MUXSDKCustomerData *customerData = [[MUXSDKCustomerData alloc] initWithCustomerPlayerData:playerData
videoData:videoData
viewData:viewData
customData:customData
viewerData:viewerData];
_playerBinding = [MUXSDKStats monitorAVPlayerViewController:_avplayerController
withPlayerName:playerName
customerData:customerData];
// later you can dispatch an error yourself
[MUXSDKStats dispatchError: @"1234"
withMessage: @"Something is not right"
severity: MUXSDKErrorSeverityWarning
errorContext: @"Error context"
forPlayer: playerName];
This is an example of how to categorize an error event as a business exception.
// Call this method from the source of the business exception with parameters appropriate to your integration.
- (void)dispatchBusinessExceptionWithPlayerName:(NSString *)playerName
playerErrorSeverity:(MUXSDKErrorSeverity)errorSeverity
playerErrorCode:(NSString *)playerErrorCode
playerErrorMessage:(NSString *)playerErrorMessage
playerErrorContext:(NSString *)playerErrorContext {
[MUXSDKStats dispatchError: playerErrorCode,
withMessage: playerErrorMessage,
severity: MUXSDKErrorSeverityWarning,
isBusinessException: YES,
errorContext: playerErrorContext,
forPlayer: playerName];
}
The recommended way to install the Mux SDKs is with CocoaPods. However, if you want to install manually via Carthage that is supported only for version 1.x of Mux-Stats-AVPlayer.
If you are installing Mux-Stats-AVPlayer your Cartfile
will also need to specify the mux-core library. Like this:
binary "https://raw.githubusercontent.com/muxinc/mux-stats-sdk-avplayer/master/MUXSDKStats.json"
binary "https://raw.githubusercontent.com/muxinc/stats-sdk-objc/master/MUXCore.json"
After running carthage update --platform iOS
follow the usual instructions for linking the frameworks. The Carthage README on GitHub walks through that and this guide is a good walk-through.
If you are using the Google IMA integration there are a few extra steps. Your Cartfile
will have these dependencies:
binary "https://raw.githubusercontent.com/muxinc/mux-stats-sdk-avplayer/master/MUXSDKStats.json"
binary "https://raw.githubusercontent.com/muxinc/stats-sdk-objc/master/MUXCore.json"
github "muxinc/mux-stats-google-ima" ~> 0.14.0
In addition to specifying these dependencies in the Cartfile
and linking them up, you will also need to follow Google's documentation for "Manually, using the SDK download".
It has come up a few times that users of our iOS library get this warning from Apple.
Apple will stop accepting submissions of apps that use UIWebView APIs . See https://developer.apple.com/documentation/uikit/uiwebview for more information.
If you run grep -r "UIWebView" .
in your project you will see a match coming from the dSYM/
directory in Mux-Core. At first glance, we too thought our SDK was triggering this warning.
However, after looking into this with several different applications we found that the warning was not being triggered by our SDK. In every case it was coming from another 3rd party.
Note that none of the Mux iOS libraries (including Mux-Core
and Mux-Stats-AVPlayer
) use UIWebView
. If you are getting this warning you must have another SDK that is using UIWebView
.
The reason there is some confusion around this and the reason you get a match in the dSYM/
directory in Mux-Core is because our SDK links to UIKit
and targets a version of iOS that may include UIWebView
. The dSYM
files are used for debugging purposes and they do not contain any functional code. You may see that this same confusion came up in other SDKs like Mapbox and Stripe (listed below).
Improvements:
Improvements:
Improvements:
viewend
when a new AVPlayerItem
becomes the player currentItem
.Fixes:
viewinit
if the player currentItem
is replaced with nil
.New:
Improvements:
API Changes:
MUXSDKStats
APIs.Fixes:
Improvements:
Improvements:
visionOS
can monitor metrics for AVPlayerViewController
or AVPlayer
with a fixed player size. We recommend testing your visionOS
application's AVPlayer monitoring integration on both the simulator and a physical device prior to deploying to the App Store.Fixes:
AVPlayer
with a fixed player size.Known Issues:
visionOS
applications is not currently supported. Installation on iOS
and tvOS
using Cocoapods is not affected.AVPlayerLayer
playback on visionOS
applications is not supported at this time.visionOS
will always indicate Used Fullscreen to be false
.Fixes:
API Changes:
Known Issues:
SESSION-DATA
tag in the manifest of a monitored HLS stream may cause a crash in v3.5.0 or earlier of MUXSDKStats
. To resolve the issue limit SESSION-DATA
tags only to applications that use MUXSDKStats
v3.5.1 or higher.Fixes:
Fixes:
Improvements:
API Changes:
Improvements
Fixes:
Player width and height dimensions are now equal to the AVPlayerLayer
bounds or AVPlayerViewController
view bounds, depending on which is used. Previously AVPlayerViewController
videoBounds
or AVPlayerLayer
videoRect` were used to set the player width and height.
Upscale Percentage or Downscale Percentage calculations are not affected if the player draws the video with the same aspect ratio as the video resolution.
Fixes:
Improvements:
Updates:
drmType
to MUXSDKCustomerViewData
so you can track this field if you wishImprovements:
Fixes:
Fixes:
Updates:
MUXSDKCustomData
Updates:
CustomerViewerData
allowing them to override detected device metadata valuesBreaking:
Improvements:
AVMetadataItem
inspection when dispatching session dataisPaused
APPLICATION_EXTENSION_API_ONLY = YES
playerName
when destroyPlayer
is calledplayer_live_edge_program_time
player_program_time
programChangeForPlayer:withCustomerData:
MUXSDKCustomerViewData
, MUXSDKCustomerVideoData
, and MUXSDKCustomerPlayerData
into MUXSDKCustomerData
and deprecates methods that treat these as separate argumentsidentifierForVendor
with alternative UUIDvideochange
calls when using AVQueuePlayer
. This method can be called as:[MUXSDKStats setAutomaticVideoChange:PLAYER_NAME enabled:false];
viewer_device_model
fieldThis release moves the build process to use XCFramework bundle type. For iOS, there are no changes required to your application code.
If you are using this SDK with TVOS the name of the module has changed (the Tv
suffix is no longer needed):
TVOS before 2.0:
@import MuxCoreTv;
@import MUXSDKStatsTv;
TVOS after 2.0:
@import MuxCore;
@import MUXSDKStats;
view_session_id
.player_remote_played
- this will be true when a video is shown over Airplay.viewer_connection_type
for iOS (either wifi
or cellular
). Detecting viewer_connection
type is done off the main thread to make sure this doesn't interfere with the performance of your application. Note that viewer_connection_type
is omitted from TVOS because in versions before TVOS 12 there is no reliable way to detect wifi
vs. ethernet
.monitorAVPlayerLayer
with optional argument automaticErrorTracking
was misnamed to withAutomaticErrorTracking
. This has been changed to the correct name which is consistent with the corresponding monitorAVPlayerViewController
method (thanks @hlung in #58)monitorAVPlayerViewController
or monitorAVPlayerLayer
MUXSDKStats.dispatchError
method to manually dispatch an errorYou probably will not need to use these features, but if your player is throwing noisy non-fatal errors or you want to catch the player errors yourself and take precise control over the error code and error message then you now have that ability.
Dispatching an error should only be used for fatal errors. When the player goes into the error state then it is no longer being tracked and the view will show up as having encountered an error in the Mux dashboard.
carthage 0.35.0
. See the GitHub issue for more details. The gist of it is that Carthage no longer ignores dSYM files, so those need to be packaged up correctly with the framework.AVQueuePlayer
. Unlike other methods of changing the playerItem
on an AVPlayer
instance, when AVQueuePlayer
progresses from one item to the next the rate
observer does not fire so we have to handle it in a special case. See instructions above for usage with AVQueuePlayer
.tvOS
frameworkorientationchange
events. This can be dispatched with MUXSDKStats orientationChangeForPlayer: withOrientation:
renditionchange
events. You can see this new event in the events list for a view.AVPlayerItemNewAccessLogEntryNotification
programChange
so that it works consistently nowviewend
when destoryPlayer
is called. Previously this was not called which didn't affect metrics, but resulted in a viewdropped
event in the events list.requestStart
and requestResponseEnd
, so with those data points we can track throughput. This bug fix requires Mux-Stats-Core v2.1.3 or greater. Run pod update Mux-Stats-AVPlayer
and pod update Mux-Stats-Core
to get the latest versions.videoChangeForPlayer
from workingvideoChangeForPlayer
: videoChangeForPlayer:withPlayerData:withVideoData
destroyPlayer
when observers have not yet bet set up on the player instance.MUXSDKStats
updateCustomerDataForPlayer:withPlayerData:withVideoData
. This allows a developer to update customerPlayerData and/or customerVideoData after the SDK has been initialized. Not all metadata can be changed if it was previously set, but all metadata that was not set initially can be updated to the intended values.