This topic describes how to use the advanced features of the ApsaraVideo Player SDK for iOS. For a complete description of all features, see API reference.
To try out the demo, download it and follow the instructions in Run the demo to compile and run the project.
Professional Skills Confirmation
Some player features require a Professional Edition license. For more information, see Features. To obtain a license, refer to Obtain a license.
You can set the listener when your application starts or before you call any player API operations.
void premiumVeryfyCallback(AVPPremiumBizType biztype, bool isValid, NSString* errorMsg) {
NSLog(@"onPremiumLicenseVerifyCallback: %d, isValid: %d, errorMsg: %@", biztype, isValid, errorMsg);
}
[AliPrivateService setOnPremiumLicenseVerifyCallback:premiumVeryfyCallback];Here, AVPPremiumBizType is an enumeration of advanced features. When you use a related feature, the player verifies the license and returns the result through this callback. If isValid is false, errorMsg contains the reason for the failure.
Playback
List playback
The ApsaraVideo Player SDK for iOS provides a full-featured list playback capability. The SDK uses mechanisms such as preloading to minimize the time-to-first-frame (TTTF) for short videos.
For an enhanced list playback experience, use our short-form drama solution. For more information, see Client-side development for short-form dramas.
Play videos with an alpha channel
Overview
The ApsaraVideo Player SDK supports rendering an alpha channel to create dynamic effects, such as animated gifts. During live streaming, you can play animated gifts without obscuring the main content, enhancing the user experience.
Limits
Alpha channel rendering is supported in the all-in-one SDK V6.8.0 and later, or the ApsaraVideo Player SDK V6.9.0 and later.
Benefits
MP4 videos with alpha channel support enhance gift effects by providing better animation quality, smaller file sizes, higher compatibility, and improved development efficiency. This allows gift effects to display more effectively to users, thereby improving the user experience.
Better animation quality: MP4 videos preserve original animation details and colors more accurately than other formats.
Smaller file size: Compared to other formats such as APNG or IXD, MP4 video files offer more effective compression, which improves loading speed and reduces network bandwidth consumption.
Higher compatibility: The MP4 format is widely supported across devices and browsers.
Using MP4 videos for gift effects is a simple technical solution that improves development efficiency. Developers do not need to create complex parsing and rendering logic, which allows them to focus on implementing other features.
Metal rendering
The ApsaraVideo Player SDK for iOS supports video rendering using the Metal framework.
Currently supports only background color, scaling mode, and the Picture-in-Picture (PiP) feature.
Configuration
/**
@brief Video render type. 0 means default render. 1 means mixed render. Default is 0.
*/
/****
@brief video render type, 0 means default render; 1 means mixed render.
*/
@property(nonatomic, assign) int videoRenderType;Usage Example
AVPConfig *config = [self.player getConfig];
// Enable Metal rendering.
config.videoRenderType = 1;
[self.player setConfig:config];
[self.player prepare];External subtitles
For a detailed code example, see the ExternalSubtitle module in the API-Example project. This project is an Objective-C-based iOS sample project for the ApsaraVideo Player SDK that helps developers quickly master core SDK integration.
The ApsaraVideo Player SDK for iOS supports adding and switching external subtitles in SRT, SSA, ASS, and VTT formats.
Examples:
Create a view to display subtitles.
Create different views for different formats.
// Initialize a custom subTitleLabel. UILabel *subTitleLabel = [[UILabel alloc] initWithFrame:frame]; // Add the subtitle label to a custom superView. The superView is a parent view that exists in the custom interface. [superView addSubview:subTitleLabel];Set subtitle-related listeners.
// External subtitle added. - (void)onSubtitleExtAdded:(AliPlayer*)player trackIndex:(int)trackIndex URL:(NSString *)URL {} // Subtitle header information callback. - (void)onSubtitleHeader:(AliPlayer *)player trackIndex:(int)trackIndex Header:(NSString *)header{} // Subtitle display callback. - (void)onSubtitleShow:(AliPlayer*)player trackIndex:(int)trackIndex subtitleID:(long)subtitleID subtitle:(NSString *)subtitle { subTitleLabel.text =subtitle; subTitleLabel.tag =subtitleID; } // Subtitle hide callback. - (void)onSubtitleHide:(AliPlayer*)player trackIndex:(int)trackIndex subtitleID:(long)subtitleID{ [subTitleLabel removeFromSuperview]; }Add a subtitle track.
[self.player addExtSubtitle:URL];Switch a subtitle track.
[self.player selectExtSubtitle:trackIndexenable:YES];
External subtitles (custom rendering using rendering components)
Full support for WebVTT external subtitles is implemented using AliVttSubtitleView and AliVttRenderImpl, enabling flexible customization of font size, color, and specific fonts.
Use cases:
Customize WebVTT subtitle styles, including font, color, and size.
Integrate ApsaraVideo Player SDK V7.11.0 and use AliVttSubtitleView.
Support multilingual subtitles (such as Arabic, Chinese, Japanese, and Korean) and auto-match corresponding fonts.
Prerequisites:
Font files (.ttf) are added to the Xcode project.
Subtitle listeners are added and WebVTT content can be retrieved.
The loadFontFromBundle method is called and fonts load successfully.
Steps to customize subtitle styles
Create a custom rendering implementation class (AliVttRenderImpl).
// CustomFontVttRenderImpl.h @interface CustomFontVttRenderImpl : AliVttRenderImpl @end // CustomFontVttRenderImpl.m @implementation CustomFontVttRenderImpl // Optional: Override font generation logic. - (UIFont *)customizeFont:(UIFont *)originalFont contentAttribute:(VttContentAttribute *)contentAttribute contentText:(NSString *)text { // Example: Automatically select font based on content. if ([self containsArabicCharacters:text]) { return [UIFont fontWithName:@"NotoSansArabic-Regular" size:originalFont.pointSize]; } if ([self containsCJKCharacters:text]) { return [UIFont fontWithName:@"NotoSansCJKsc-Regular" size:originalFont.pointSize]; } return originalFont; } // Optional: Force color change. - (void)applyColorStyle:(NSMutableDictionary *)attrs contentAttribute:(VttContentAttribute *)contentAttribute { // Force red color. attrs[NSForegroundColorAttributeName] = [UIColor redColor]; } // Optional: Enlarge font. - (void)applyFontStyle:(NSMutableDictionary *)attrs contentAttribute:(VttContentAttribute *)contentAttribute context:(RenderContext *)context { CGFloat originalSize = contentAttribute.fontSizePx / context.contentsScale; CGFloat newSize = originalSize * 2.0; // Double the size. UIFont *font = [self generateFontWithName:contentAttribute.fontName fontSize:newSize isBold:contentAttribute.mBold isItalic:contentAttribute.mItalic]; attrs[NSFontAttributeName] = font; } // Helper method: Detect Arabic characters. - (BOOL)containsArabicCharacters:(NSString *)text { for (NSUInteger i = 0; i < text.length; i++) { unichar c = [text characterAtIndex:i]; if ((c >= 0x0600 && c <= 0x06FF) || (c >= 0x0750 && c <= 0x077F)) { return YES; } } return NO; } // Helper method: Detect CJK characters. - (BOOL)containsCJKCharacters:(NSString *)text { for (NSUInteger i = 0; i < text.length; i++) { unichar c = [text characterAtIndex:i]; if ((c >= 0x4E00 && c <= 0x9FFF) || // Chinese (c >= 0x3040 && c <= 0x309F) || // Japanese Hiragana (c >= 0xAC00 && c <= 0xD7AF)) { // Korean return YES; } } return NO; } @end(Optional) Dynamically load custom fonts.
- (void)loadCustomFontFromBundle:(NSString *)fontName { NSString *path = [[NSBundle mainBundle] pathForResource:fontName ofType:@"ttf"]; if (path) { NSData *fontData = [NSData dataWithContentsOfFile:path]; CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)fontData); CGFontRef fontRef = CGFontCreateWithDataProvider(provider); if (CTFontManagerRegisterGraphicsFont(fontRef, NULL)) { NSLog(@"Font registration succeeded: %@", fontName); } else { NSLog(@"Font registration failed: %@", fontName); } CGFontRelease(fontRef); CGDataProviderRelease(provider); } }Initialize the subtitle view and bind the custom renderer.
// Create subtitle view. AliVttSubtitleView *subtitleView = [[AliVttSubtitleView alloc] init]; // Set custom renderer factory. [subtitleView setRenderImplFactory:^AliVttRenderImpl*() { CustomFontVttRenderImpl *impl = [[CustomFontVttRenderImpl alloc] init]; // Optional: Preload fonts. [impl loadCustomFontFromBundle:@"LongCang-Regular"]; return impl; }]; // Associate with player. [player setExternalSubtitleView:subtitleView];Handle player subtitle callbacks.
Implement the following methods in AVPDelegate:
// Subtitle header (includes style and region definitions). - (void)onSubtitleHeader:(AliPlayer *)player trackIndex:(int)trackIndex Header:(NSString *)header { [self.subtitleView setVttHeader:player trackIndex:trackIndex Header:header]; } // Show subtitle. - (void)onSubtitleShow:(AliPlayer *)player trackIndex:(int)trackIndex subtitleID:(long)subtitleID subtitle:(NSString *)subtitle { [self.subtitleView show:player trackIndex:trackIndex subtitleID:subtitleID subtitle:subtitle]; } // Hide subtitle. - (void)onSubtitleHide:(AliPlayer *)player trackIndex:(int)trackIndex subtitleID:(long)subtitleID { [self.subtitleView hide:player trackIndex:trackIndex subtitleID:subtitleID]; } // Subtitle added (used to enable track). - (void)onSubtitleExtAdded:(AliPlayer *)player trackIndex:(int)trackIndex URL:(NSString *)URL { [player selectExtSubtitle:trackIndex enable:YES]; }
Audio-only playback
You can disable video playback to play only the audio track. Configure this setting before calling prepare.
AVPConfig *config = [self.player getConfig];
config.disableVideo = YES;
[self.player setConfig:config];Switch between software and hardware decoding
The iOS Player SDK provides hardware decoding capability for H.264 and H.265, and includes the enableHardwareDecoder toggle. By default, hardware decoding is enabled. If hardware decoding fails to initialize, software decoding is automatically used to ensure normal playback. The following example shows how to enable hardware decoding:
// Enable hardware decoding. It is enabled by default.
self.player.enableHardwareDecoder = YES;If automatic failover occurs from hardware decoding to software decoding, the onPlayerEvent callback is triggered. The following example shows how to handle this event:
-(void)onPlayerEvent:(AliPlayer*)player eventWithString:(AVPEventWithString)eventWithString description:(NSString *)description {
if (eventWithString == EVENT_SWITCH_TO_SOFTWARE_DECODER) {
// Switched to software decoding.
}
}H.265 adaptive playback
An adaptive fallback is triggered when the current device model is on the cloud-based H.265 blacklist or if H.265 hardware decoding fails. If an H.264 backup stream is configured, it will be played. Otherwise, the player falls back to H.265 software decoding.
This feature is available only after you enable the cloud-native adaptive decoding service. You need to submit a Yida form to request license authorization.
The cloud-native adaptive decoding value-added service includes dynamic delivery of hardware decoding compatibility data and adaptive fallback from H.265 to H.264 streams.
The SDK still automatically switches to software decoding upon hardware decoding failure, even if this value-added service is not enabled.
Example of configuring a backup stream:
// The application layer maintains a map of original URLs to backup URLs.
NSString* getBackupUrlCallback(AVPBizScene scene, AVPCodecType codecType, NSString* oriurl){
NSMutableDictionary *globalMap = [AliPlayerViewController getGlobalBackupUrlMap];
NSString *backupUrl = globalMap[oriurl];
return backupUrl;
}
[AliPlayerGlobalSettings setAdaptiveDecoderGetBackupURLCallback:getBackupUrlCallback];Switch video definition based on network conditions
Multi-bitrate adaptive HLS streams can be generated in ApsaraVideo VOD using a video packaging transcoding template group. For instructions, see Adaptive bitrate streaming configuration for video on demand.
Adaptive video streams generated through ApsaraVideo VOD transcoding require you to specify
AUTOas the default playback definition list when using Vid-based playback to retrieve and play adaptive video streams. Otherwise, the player SDK selects lower-definition video streams according to the default logic. For information about the default playback order, see Which definition does the player SDK play by default when multiple definitions are generated through video transcoding?. The following example shows how to specify the definition list for VidAuth-based playback:AVPVidAuthSource *authSource = [[AVPVidAuthSource alloc] init]; authSource.definitions = @"AUTO";
The ApsaraVideo Player SDK for iOS supports adaptive bitrate streaming of HTTP Live Streaming (HLS) video streams and Dynamic Adaptive Streaming over HTTP (DASH) video streams. After prepare completes successfully, you can retrieve information about each bitrate stream by calling getMediaInfo, which returns TrackInfo. The following sample code shows how to query media information:
AVPMediaInfo *info = [self.player getMediaInfo];
NSArray<AVPTrackInfo*>* tracks = info.tracks;During playback, you can call the player's selectTrack method to switch the bitrate stream. When the value is set to SELECT_AVPTRACK_TYPE_VIDEO_AUTO, adaptive bitrate streaming is enabled. For example:
// Switch to a specific bitrate.
[self.player selectTrack:track.trackIndex];
// Enable adaptive bitrate switching.
[self.player selectTrack:SELECT_AVPTRACK_TYPE_VIDEO_AUTO];The switch triggers the onTrackChanged callback. The following example shows how to handle track changes.
- (void)onTrackChanged:(AliPlayer*)player info:(AVPTrackInfo*)info {
if (info.trackType == AVPTRACK_TYPE_VIDEO) {
// Rendition changed.
}
// etc
}Optional: Before calling the player's selectTrack method to enable adaptive bitrate streaming, you can set an upper limit for the definition of adaptive bitrate (ABR) switching through config to prevent automatic switching to an unintended bitrate. The following example shows how to do this: (We recommend calling this code before the player calls the prepare method or the playlist player calls the moveTo method so that the configuration takes effect.)
AVPConfig *config = [self.player getConfig];
config.maxAllowedAbrVideoPixelNumber = 921600;// Set the maximum allowed pixel count for ABR to 1280x720. The player will only switch to definitions with a pixel count less than or equal to this value.
[self.player setConfig:config];Take a snapshot
The iOS Player SDK provides the snapshot capture feature for the current video playback, which is implemented by the snapShot interface. The captured raw data is converted to a bitmap and returned. The callback interface is onCaptureScreen. The following sample code shows how to capture a snapshot of the current video playback.
// Snapshot callback.
- (void)onCaptureScreen:(AliPlayer *)player image:(UIImage *)image {
// Process the snapshot.
}
// Take a snapshot of the current frame.
[self.player snapShot];The snapshot does not include the UI.
Preview
In combination with ApsaraVideo VOD configurations, you can implement a preview feature. This is supported for both VidSts and VidAuth (recommended for video-on-demand) playback. For configuration instructions, see Preview videos.
After you configure the video preview feature, use the VidPlayerConfigGen interface's setPreviewTime method to set the player's preview duration. For example, if you use VidSts-based playback, the following sample code demonstrates this:
AVPVidStsSource *source = [[AVPVidStsSource alloc] init];
....
VidPlayerConfigGenerator* vp = [[VidPlayerConfigGenerator alloc] init];
[vp setPreviewTime:20];// 20-second preview
source.playConfig = [vp generatePlayerConfig];// Set for the playback source
...When a preview duration is set, the server returns only the content for that time period.
VidPlayerConfigGen supports setting various server-side request parameters. See Request parameter descriptions.
Set the Referer
The iOS player SDK supports setting the Referer. You can control access permissions using the Referer blacklists and whitelists in the console and setting the request Referer through the AVPConfig method. The following sample code provides an example:
// Get the configuration first.
AVPConfig *config = [self.player getConfig];
// Set the Referer.
config.referer = referer;
....// Other settings
// Set the configuration for the player.
[self.player setConfig:config];Set the User-Agent
The iOS player SDK provides AVPConfig to set the User-Agent header. After you specify the User-Agent header, the player includes the user agent information in its requests. The following sample code shows how to...
// Get the configuration first.
AVPConfig *config = [self.player getConfig];
// Set the User-Agent.
config.userAgent = userAgent;
....// Other settings
// Set the configuration for the player.
[self.player setConfig:config];Configure network retry count and timeout
You can set the network timeout duration and the number of retries for the iOS player SDK using the AVPConfig method. The following sample code provides an example:
// Get the current configuration.
AVPConfig *config = [self.player getConfig];
// Specify the network timeout period. Unit: milliseconds.
config.networkTimeout = 5000;
// Specify the maximum number of retries upon a network timeout. The retry interval is the value of the networkTimeout parameter. A value of 0 indicates that no retry is performed. The application determines the retry policy. The default value is 2.
config.networkRetryCount = 2;
....// Configure other settings.
// Configure the settings for the player.
[self.player setConfig:config];If networkRetryCount is greater than 0, the player retries networkRetryCount times when a network problem occurs, with an interval of networkTimeout between retries.
If the loading state persists after all retries, the
onErrorevent is triggered, and AVPErrorModel.code is set to ERROR_LOADING_TIMEOUT.If
networkRetryCountis set to 0, a network retry timeout triggers theonPlayerEventcallback, and theeventWithStringparameter is set toEVENT_PLAYER_NETWORK_RETRY. You can then call the player'sreloadmethod to reload the stream or perform other actions.
Configure cache and latency control
Buffer control is important for a player. You can decrease the startup loading duration and improve playback smoothness using proper configurations. The iOS Player SDK provides the AVPConfig interface to configure buffer and latency. The following example shows how to configure buffer and latency settings:
// Retrieve the configuration.
AVPConfig *config = [self.player getConfig];
// Specify the maximum latency. Note: This parameter is valid for only live streaming. If the latency is high, Player SDK synchronizes frames to ensure that the latency is within the specified limit.
config.maxDelayTime = 5000;
// Specify the maximum buffer duration. Unit: milliseconds. This parameter specifies the maximum duration of data that the player can buffer at a time.
config.maxBufferDuration = 50000;
// Specify the peak buffer duration. Unit: milliseconds. When the player loads data due to poor network conditions, the player stops loading after the duration of the buffered data reaches this value.
config.highBufferDuration = 3000;
// Specify the startup buffer duration. Unit: milliseconds. A smaller value indicates a shorter startup loading duration. However, the player may enter the loading status soon after the playback starts.
config.startBufferDuration = 500;
// Configure other settings.
// Apply the configuration to the player.
[self.player setConfig:config];The buffer durations must satisfy: startBufferDuration ≤ highBufferDuration ≤ maxBufferDuration.
When the maximum buffer duration (maxBufferDuration) is greater than 5 minutes, the system defaults to a 5-minute duration to prevent excessive memory usage.
Set HTTP headers
You can use the AVPConfig method to add HTTP header parameters to requests in the player. The following sample code shows how to:
// Retrieve the configuration.
AVPConfig *config = [self.player getConfig];
// Define the headers.
NSMutableArray *httpHeaders = [[NSMutableArray alloc] init];
// For example, configure a host when you use HTTPDNS.
[httpHeaders addObject:@"Host:example.com"];
// Configure the headers.
config.httpHeaders = httpHeaders;
....// Configure other settings.
// Configure the settings for the player.
[self.player setConfig:config];Picture-in-Picture
For detailed code examples, see the PictureInPicture module in the API-Example project. This project is an Objective-C-based iOS sample project for the ApsaraVideo Player SDK that helps developers quickly master core SDK integration.
PiP requires iOS 15 or later and ApsaraVideo Player SDK for iOS 5.4.9.0 or later.
For versions of ApsaraVideo Player SDK for iOS earlier than 5.5.2.0, the PiP feature provides only methods to enable and disable PiP and to display the PiP window when the app is in the background. Starting from version 5.5.2.0, the SDK supports setting the PiP delegate from the outside, which allows for more personalized PiP feature development.
To use PiP, ensure it is enabled in your device's settings (Settings > General > Picture in Picture).
Enable PiP
After the picture-in-picture (PiP) feature is enabled, the video is played in a floating window when the application is switched to the background. When the application is switched to the foreground, the video is played in the application window. The PiP feature is controlled by the setPictureInPictureEnable setting. To enable the PiP feature, you must configure it in the AVPEventPrepareDone state. The following sample code provides an example:
- (void)onPlayerEvent:(AliPlayer *)player eventType:(AVPEventType)eventType {
switch (eventType) {
case AVPEventPrepareDone:
{
[self.player setPictureInPictureEnable:YES];
}
break;
default:
break;
}
}When the player calls stop to stop playback, the Picture-in-Picture window is no longer needed, so you must first disable Picture-in-Picture by calling setPictureInPictureEnable before calling stop.
Set the PiP delegate
The following code examples demonstrate common interactive operations between Picture-in-Picture (PiP) windows and player windows, such as displaying the Pause, Play, Fast Forward, Fast Backward, and Replay buttons in PiP mode. For details about the corresponding delegate methods, see the Player SDK Demo, specifically the AliPlayerPictureInPictureDelegate.h header file in the AliyunPlayer.framework folder.
Set the PiP delegate.
/** * @brief Set the PiP delegate. */ -(void) setPictureinPictureDelegate:(id<AliPlayerPictureInPictureDelegate>)delegate; // Set the PiP delegate. [self.player setPictureinPictureDelegate:self];Add variables and implement the delegate interface.
You can add a global variable to control the player's state changes.
#import "YourUIViewController.h" #import <AliyunPlayer/AliyunPlayer.h> @interface YourUIViewController () <AVPDelegate, AliPlayerPictureInPictureDelegate> // Player instance. @property (nonatomic, strong) AliPlayer *player; // Player view container. @property (nonatomic, strong) UIView *playerView; // Listen for whether PiP is currently paused. @property (nonatomic, assign) BOOL isPipPaused; // Listen for the current playback status of the player. Set it through the newStatus callback of the playback event status change listener. @property (nonatomic, assign) AVPStatus currentPlayerStatus; // Set the PiP controller. Set it in the callback method for when PiP is about to start. You need to actively set it to nil when the page is about to be destroyed. We recommend setting it. @property (nonatomic, weak) AVPictureInPictureController *pipController; // Listen for the current playback progress of the player. Set currentPosition to the value of the position parameter in the callback for the current video playback position. @property (nonatomic, assign) int64_t currentPosition; @endNoteYou must use the weak or assign modifier for pipController. If you use the assign modifier, make sure that you set the correct variables to null.
Update the status of the PiP controller when you listen for the onPlayerStatusChanged event.
- (void)onPlayerStatusChanged:(AliPlayer*)player oldStatus:(AVPStatus)oldStatus newStatus:(AVPStatus)newStatus { self.currentPlayerStatus = newStatus; if (_pipController) { [self.pipController invalidatePlaybackState]; } }Update the status of the PiP controller when you listen for the onPlayerEvent event.
- (void)onPlayerEvent:(AliPlayer*)player eventType:(AVPEventType)eventType { if (eventType == AVPEventCompletion) { if (_pipController) { self.isPipPaused = YES; // After playback ends, change the PiP status to paused. [self.pipController invalidatePlaybackState]; } } else if (eventType == AVPEventSeekEnd) { // Seeking is complete. if (_pipController) { [self.pipController invalidatePlaybackState]; } } }Set listeners.
Listen for the callback when PiP is about to start.
/** @brief Picture-in-Picture is about to start. @param pictureInPictureController The Picture-in-Picture controller. */ - (void)pictureInPictureControllerWillStartPictureInPicture:(AVPictureInPictureController *)pictureInPictureController { if (!_pipController) { self.pipController = pictureInPictureController; } self.isPipPaused = !(self.currentPlayerStatus == AVPStatusStarted); [pictureInPictureController invalidatePlaybackState]; }Listen for the callback when PiP is preparing to stop.
/** @brief Picture-in-Picture is preparing to stop. @param pictureInPictureController The Picture-in-Picture controller. */ - (void)pictureInPictureControllerWillStopPictureInPicture:(AVPictureInPictureController *)pictureInPictureController { self.isPipPaused = NO; [pictureInPictureController invalidatePlaybackState]; }Listen for the callback that instructs the delegate to restore the user interface before PiP stops.
/** @brief Tells the delegate to restore the user interface before Picture-in-Picture stops. @param pictureInPictureController The Picture-in-Picture controller. @param completionHandler Call and pass YES to allow the system to finish restoring the player user interface. */ - (void)pictureInPictureController:(AVPictureInPictureController *)pictureInPictureController restoreUserInterfaceForPictureInPictureStopWithCompletionHandler:(void (^)(BOOL restored))completionHandler { if (_pipController) { _pipController = nil; } completionHandler(YES); }Listen for the callback that sets the current playable time range for PiP.
/** @brief Notifies the Picture-in-Picture controller of the current playable time range. @param pictureInPictureController The Picture-in-Picture controller. @return The current playable time range. */ - (CMTimeRange)pictureInPictureControllerTimeRangeForPlayback:(nonnull AVPictureInPictureController *)pictureInPictureController layerTime:(CMTime)layerTime{ Float64 current64 = CMTimeGetSeconds(layerTime); Float64 start; Float64 end; if (currentPosition <= self.player.duration) { double curPostion = self.currentPosition / 1000.0; double duration = self.player.duration / 1000.0; double interval = duration - curPostion; start = current64 - curPostion; end = current64 + interval; CMTime t1 = CMTimeMakeWithSeconds(start, layerTime.timescale); CMTime t2 = CMTimeMakeWithSeconds(end, layerTime.timescale); return CMTimeRangeFromTimeToTime(t1, t2); } else { return CMTimeRangeMake(kCMTimeNegativeInfinity, kCMTimePositiveInfinity); } }This callback monitors the Picture-in-Picture (PiP) playback state (paused or playing).
/** @brief Reflects the paused or playing state on the UI. @param pictureInPictureController The Picture-in-Picture controller. @return Paused or playing. */ - (BOOL)pictureInPictureControllerIsPlaybackPaused:(nonnull AVPictureInPictureController *)pictureInPictureController{ return self.isPipPaused; }NoteThis callback is triggered before PiP starts. Make sure that the return value of this callback is false at this time. Otherwise, PiP cannot be activated.
Listen for the callback when the user skips forward or backward to synchronize the playback progress to the player.
/** @brief The fast forward or fast backward button is clicked. @param pictureInPictureController The Picture-in-Picture controller. @param skipInterval The time interval for fast forwarding or fast backwarding. @param completionHandler A closure that must be called to indicate that the seek operation is complete. */ - (void)pictureInPictureController:(nonnull AVPictureInPictureController *)pictureInPictureController skipByInterval:(CMTime)skipInterval completionHandler:(nonnull void (^)(void))completionHandler { int64_t skipTime = skipInterval.value / skipInterval.timescale; int64_t skipPosition = self.currentPosition + skipTime * 1000; if (skipPosition < 0) { skipPosition = 0; } else if (skipPosition > self.player.duration) { skipPosition = self.player.duration; } [self.player seekToTime:skipPosition seekMode:AVP_SEEKMODE_INACCURATE]; [pictureInPictureController invalidatePlaybackState]; }Listen for the callback when the pause or play button is clicked in PiP, and perform the required operations.
/** @brief The pause button in Picture-in-Picture is clicked. @param pictureInPictureController The Picture-in-Picture controller. @param playing Whether it is playing. */ - (void)pictureInPictureController:(nonnull AVPictureInPictureController *)pictureInPictureController setPlaying:(BOOL)playing { if (!playing){ [self.player pause]; self.isPipPaused = YES; } else { // Recommendation: If PiP playback is complete and needs to be replayed, you can additionally execute the code in the following if statement. if (self.currentPlayerStatus == AVPStatusCompletion) { [self.player seekToTime:0 seekMode:AVP_SEEKMODE_ACCURATE]; } [self.player start]; self.isPipPaused = NO; } [pictureInPictureController invalidatePlaybackState]; }
In-app Picture-in-Picture
By default, PiP activates when the app moves to the background. To implement in-app PiP, you can manually control its activation. First, determine if PiP has been started.
/**
@brief Whether PiP is started.
@param pictureInPictureController The PiP controller.
@param isEnable Whether PiP is started.
*/
/****
@brief pictureInPicture is enable or not
@param pictureInPictureController picture in picture controller
@param isEnable is enable or not
*/
- (void)pictureInPictureControllerIsPictureInPictureEnable:(nullable AVPictureInPictureController *)pictureInPictureController isEnable:(BOOL)isEnable;When PiP is enabled, disable automatic activation and control it manually.
- (void) pictureInPictureControllerIsPictureInPictureEnable:(nullable AVPictureInPictureController *) pictureInPictureController isEnable:(BOOL) isEnable
{
if (isEnable && pictureInPictureController) {
_pipController = pictureInPictureController;
// close pip auto start
if (@available(iOS 15.0, *)) {
_pipController.canStartPictureInPictureAutomaticallyFromInline = false;
}
} else {
_pipController = NULL;
}
}
- (void) switchPip:(bool) enable {
if (_pipController == nil) {
return;
}
if (enable) {
// start pip
[_pipController startPictureInPicture];
} else {
// close pip
[_pipController stopPictureInPicture];
}
}Live RTS fallback
For a detailed code example, see the RtsLiveStream module in the API-Example project. This project is an Objective-C-based iOS sample project for the ApsaraVideo Player SDK that helps developers quickly master core SDK integration.
For more information, see RTS live playback.
Switch between left and right audio channels
The iOS Player SDK uses the outputAudioChannel property to set the output audio channel. If the input source is stereo, you can switch to the left or right channel. If the input source is mono, this setting has no effect.
The output audio channel setting affects both audio rendering and PCM data callbacks.
// Set the AVPOutputAudioChannel enumeration value to switch channels.
// AVP_AUDIO_CHANNEL_NONE: Do not specify a channel. Play with the input source's audio channel. This is the default value.
// AVP_AUDIO_CHANNEL_LEFT: Switch to the left audio channel for playback.
// AVP_AUDIO_CHANNEL_RIGHT: Switch to the right audio channel for playback.
self.player.outputAudioChannel = AVP_AUDIO_CHANNEL_NONE;Set the video background color
Set the background color of the player's rendering view.
API example
/**
@brief Set the background color of the video.
@param color the color
*/
/****
@brief Set video background color
@param color the color
*/
-(void) setVideoBackgroundColor:(UIColor *)color;Usage
// The parameter is an 8-digit hexadecimal value. The 8 digits are grouped into pairs, representing A (alpha/transparency), R (red), G (green), and B (blue) in order.
// For example, 0x0000ff00 represents green.
[self.player setVideoBackgroundColor:0x0000ff00]Specify a playback domain for VidAuth
With the VidAuth method, you can specify parameters such as the playback domain for the vid. For a list of supported parameters, see GetPlayInfo. The following content describes how to specify a domain name for vidAuth-based playback and provides sample code:
API example
/**
@brief Play using the vid+playauth method. See https://www.alibabacloud.com/help/zh/vod/user-guide/use-playback-credentials-to-play-videos
@param source The input type of AVPVidAuthSource.
@see AVPVidAuthSource
*/
- (void)setAuthSource:(AVPVidAuthSource*)source;Usage
Add the playDomain field through the VidPlayerConfigGenerator interface.
VidPlayerConfigGenerator* gen = [[VidPlayerConfigGenerator alloc]init];
// Add the playDomain field. For the fields that can be added, see
// https://www.alibabacloud.com/help/zh/vod/developer-reference/api-vod-2017-03-21-getplayinfo
[gen addVidPlayerConfigByStringValue:@"playDomain" value: @"com.xxx.xxx"];
[source setPlayConfig:[gen generatePlayerConfig]];
[self.player setAuthSource:source]:Background decoding
Starting from version 6.12.0, the SDK supports background decoding. When enabled, the player can continue to decode and play video streams when the app is in the background.
// A value of 1 enables background decoding. A value of 0 disables background decoding. The default value is 0.
[self.player setOption:ALLOW_DECODE_BACKGROUND valueInt:1];H.266 decoding plugin
H.266, also known as Versatile Video Coding (VVC), is a next-generation video coding standard that offers significantly lower bitrates at the same quality. The H.266 decoding capability is provided as a separate plug-in for on-demand integration.
Prerequisites
Use Player or all-in-one SDK V7.6.0 or later.
The Professional Edition license has been authorized. For more information, see Obtain the Player SDK License.
ApsaraVideo Player with the H.266 decoding plug-in supports only H.266 videos encoded by ApsaraVideo Transcoding.
Integrate the plugin
Activate the plugin
Starting from v7.7.0, the plug-in is enabled by default and does not need manual activation.
[AliPlayerGlobalSettings enableCodecPlugin:@"vvc" valid:true];Related error codes
For error codes related to the H.266 plug-in, see General FAQ for players on different platforms.
Auto-refresh playback sources
Enabling auto-refresh prevents playback interruptions caused by expired authentication. When a source expires, the player triggers a listener to fetch a new URL, ensuring smooth, uninterrupted playback.
Prerequisites
Use Player or all-in-one SDK V7.9.0 or later.
Use VidAuth sources for playback or configure URL signing in your business.
VidAuth source
API example
/**
@brief Set the callback for VidAuth source expiration notification.
When the player detects that the current VidAuth source has expired, this callback is triggered. VidAuth source expiration includes PlayAuth expiration and playback URL expiration.
You can refresh the VidAuth source in the callback and submit the new VidAuth source object via `callback` to ensure stable and smooth playback.
@param callback The callback block triggered when the VidAuth source expires.
You can return a valid `VidAuth` object via this callback to update the player.
*/
/****
@brief Set the callback for VidAuth source expiration notification.
This method is triggered when the player detects that the current VidAuth source has expired.
You can refresh the VidAuth source within the callback and use the `callback` to return the updated VidAuth source,
ensuring uninterrupted and smooth video playback.
@param callback The callback block triggered when the VidAuth source expires.
Use this callback to provide a valid `VidAuth` object to update the player.
*/
-(void)setOnVidAuthExpiredCallback:(void (^)(id expiredSource, id<AVPSourceRefreshCallback> callback))callback;Function composition
Usage
You can obtain audio-video playback credentials by calling the GetVideoPlayAuth operation. We recommend integrating the ApsaraVideo VOD server-side SDK to get credentials and avoid self-signing. For more information, see OpenAPI Explorer.
[self.player setOnVidAuthExpiredCallback:^(id expiredSource, id<AVPSourceRefreshCallback> callback) {
// Get AVPVidAuthSource
if ([expiredSource isKindOfClass:[AVPVidAuthSource class]]) {
// ------------------- User implementation begins -------------------
// Call your own function to get a new PlayAuth from your app server.
// clinetGetPlayAuthFunction is a sample function name. Replace it with your own implementation.
[self clinetGetPlayAuthFunction:vid success:^(NSString* newPlayAuth){
// 1. Callback for successful retrieval of new credentials.
[vidAuth setPlayAuth:newPlayAuth];
// 2. Return the updated object to the player via the SDK callback.
[callback onSuccess:vidAuth];
} failure:^(NSString* errorMsg) {
// Callback for failed credential retrieval.
// errorMsg contains detailed error information.
[callback onError:errorMsg];
}];
// ------------------- User implementation ends -------------------
}
}];URL source
API example
/**
@brief Set the callback for URL source expiration notification.
When the player detects that the current URL source has expired, this callback is triggered.
You can refresh the URL source in the callback and call `callback` to return the new URL source, ensuring uninterrupted playback.
@note For information about configuring URL signing, see the Alibaba Cloud documentation:
https://www.alibabacloud.com/help/zh/vod/user-guide/configure-url-signing?spm=a2c4g.11186623.0.0.560c4140fGh8MW
@param callback The callback block triggered when the URL source expires.
You can return a valid `URLSource` object via this callback to update the player.
*/
/****
@brief Set the callback for URL source expiration notification.
This method is triggered when the player detects that the current URL source has expired.
You can refresh the URL source within the callback and use the `callback` to return the updated URL source,
ensuring uninterrupted video playback.
@param callback The callback block triggered when the URL source expires.
Use this callback to provide a valid `URLSource` object to update the player.
*/
-(void)setOnURLSourceExpiredCallback:(void (^)(id expiredSource, id<AVPSourceRefreshCallback> callback))callback;Function composition
Usage
[self.player setOnURLSourceExpiredCallback:^(id expiredSource, id<AVPSourceRefreshCallback> callback) {
// Get AVPUrlSource
if ([expiredSource isKindOfClass:[AVPUrlSource class]]) {
AVPUrlSource *expiredUrlSource = (AVPUrlSource *)expiredSource;
NSString *expiredUrl = [expiredUrlSource.playerUrl absoluteString];
// Check if auth_key is included
if (![expiredUrl containsString:@"auth_key="]) {
return;
}
// 1. Extract the original URL from the expired URL
NSRange authKeyQuestionRange = [expiredUrl rangeOfString:@"?auth_key="];
NSRange authKeyAmpersandRange = [expiredUrl rangeOfString:@"&auth_key="];
NSInteger authKeyIndex = NSNotFound;
if (authKeyQuestionRange.location != NSNotFound) {
authKeyIndex = authKeyQuestionRange.location;
} else if (authKeyAmpersandRange.location != NSNotFound) {
authKeyIndex = authKeyAmpersandRange.location;
}
NSString *originalUrl = nil;
if (authKeyIndex != NSNotFound) {
originalUrl = [expiredUrl substringToIndex:authKeyIndex];
} else {
// If auth_key is not found, treat the entire URL as the original URL
originalUrl = expiredUrl;
}
// 2. Prepare new authentication parameters: authKey and expiration time
// If the class member authKey is valid, use it
NSString *key = (self.authKey.length > 0) ? self.authKey : @"";
if (!NOT_EMPTY(key)) {
[callback onError:@"REFRESH_ERROR:key fail"];
return;
}
// If the class member validTime is valid, use it. Otherwise, use the default value
NSTimeInterval validTime = (self.validTime > 0) ? self.validTime : 3600; // Default 3600 seconds
NSTimeInterval newExpireTime = [[NSDate date] timeIntervalSince1970] + validTime;
// 3. Generate a new authenticated URL using CdnAuthUtil (Method A)
NSString *newAuthUrl = [CdnAuthUtil aAuthWithUri:originalUrl key:key exp:newExpireTime];
AVPUrlSource *resultSource = [[AVPUrlSource alloc] urlWithString:newAuthUrl];
// 4. Handle callback
if (newAuthUrl) {
[callback onSuccess:resultSource];
} else {
[callback onError:@"REFRESH_ERROR:refresh fail"];
}
}
}];Utility functions
Example using Signing method A.
Performance
Set the playback scene
Setting the playback scene automatically configures optimal parameters (including buffer settings and feature toggles) for that scene. Custom parameters set via the setConfig interface remain effective (custom settings take precedence).
After setting the playback scene, use the
getConfiginterface to view the configuration.
API example
/**
@brief Set player scene.
@param scene Player scene.
@see AVPScene
*/
/****
@brief Set player scene.
@param scene Player scene.
@see AVPScene
*/
-(void) setPlayerScene:(AVPScene)scene;Playback scenes
typedef enum _AVPScene {
/**
* Scene: None
*/
/****
* scene none
*/
SceneNone,
/**
* Long video scene: Applies to videos longer than 30 minutes
*/
/****
* long scene: apply to more than 30min
*/
SceneLong,
/**
* Medium video scene: Applies to videos 5–30 minutes long
*/
/****
* middle scene: apply to 5min-30min
*/
SceneMedium,
/**
* Short video scene: Applies to videos up to 5 minutes long
*/
/****
* short scene: apply to 0s-5min
*/
SceneShort,
/**
* Live streaming scene
*/
/****
* live scene
*/
SceneLive,
/**
* Ultra-low-latency live streaming scene
*/
/****
* RTS live scene
*/
SceneRTSLive
} AVPScene;Usage
// Set short video scene.
[self.player setPlayerScene:SceneShort];
// Set medium video scene.
[self.player setPlayerScene:SceneMedium];
// Set long video scene.
[self.player setPlayerScene:SceneLong];
// Set live streaming scene.
[self.player setPlayerScene:SceneLive]; Pre-rendering
iOS Player SDK supports quick first-frame rendering before playback starts, improving startup speed.
This feature is disabled by default.
When enabled, it changes the trigger order of the ready and first-frame-rendered events: Without it, ready fires first, then first-frame-rendered. With it, first-frame-rendered may fire before ready, depending on decode/render speed. This does not affect playback.
Example:
[self.player setOption:ALLOW_PRE_RENDER valueInt:1];Local cache
For detailed code examples, see the PreloadUrl module in the API-Example project. This project is an Objective-C-based iOS sample project for the ApsaraVideo Player SDK that helps developers quickly master core SDK integration.
iOS Player SDK provides local caching to improve startup speed, seek speed, and reduce stuttering for repeated video playback. It also saves bandwidth.
Enable local cache
By default, the local caching feature is disabled. To use this feature, you must manually enable it. You can control it using AliPlayerGlobalSettings and the enableLocalCache parameter. Example:
/**
* Enable local cache. After enabling, it caches to local files.
* @param enable: Local cache toggle. true: enable, false: disable. Default is disable.
* @param maxBufferMemoryKB: Deprecated since V5.4.7.1. No effect.
* @param localCacheDir: Required. The directory for local cache files. Must be an absolute path.
*/
[AliPlayerGlobalSettings enableLocalCache:true maxBufferMemoryKB:1024 localCacheDir:@""];
/**
@brief Settings for automatic clearing of local cache files.
@param expireMin: Deprecated since V5.4.7.1. No effect.
@param maxCapacityMB: Maximum cache capacity in megabytes. Default is 20 GB. During cleanup, if the total cache capacity exceeds this size, the oldest cache files will be deleted one by one, sorted by the last cache time of the cacheItem, until the capacity is less than or equal to the maximum cache capacity.
@param freeStorageMB: Minimum free disk space in megabytes. Default is 0. During cleanup, similar to the maximum cache capacity, if the current disk space is less than this value, cache files will also be deleted one by one according to the rules until freeStorage is greater than or equal to this value or all caches are cleared.
*/
[AliPlayerGlobalSettings setCacheFileClearConfig:0 maxCapacityMB:0 freeStorageMB:0];
/**
* Callback to get the hash value of the loaded URL. Used as a unique ID for the URL. You must ensure that each URL is different.
*/
// You need to implement this function yourself and pass the function pointer to setCacheUrlHashCallback.
static NSString *CaheUrlHashHandle(NSString *url) {
return @"xxx";
}
[AliPlayerGlobalSettings setCacheUrlHashCallback:&CaheUrlHashHandle];If video URLs contain authentication parameters that change during caching/playback, improve cache hit rate by removing auth parameters before calculating hash via
setCacheUrlHashCallback(e.g., MD5). Example: For URLhttp://****.mp4?aaa, calculate hash usinghttp://****.mp4. However, for encrypted m3u8 videos, removing auth parameters from keyURLs causes different videos to share the same key, leading to playback failure. Solution: InsetCacheUrlHashCallback, only remove auth parameters from playback domains (http(s)://xxxxx.m3u8?aaaa) but not keyURL domains (http(s)://yyyyy?bbbb).
If the server supports both HTTP and HTTPS protocols, but the media files pointed to by different protocols are the same, you can remove or unify the request headers before you calculate the MD5 value. For example:
If the video playback URLs are
https://****.mp4andhttp://****.mp4, use****.mp4to calculate the MD5 value.If the video playback URL is
https://****.mp4, unify it tohttp://****.mp4before you calculate the MD5 value.
For Player SDK version 5.5.4.0 and later, if the video playback URL contains authentication parameters and the playback protocol is HLS, you can select different authentication modes by setting the
AVPConfig.enableStrictAuthModefield (the default value is false in versions earlier than 7.13.0; the default value is true in version 7.13.0 and later):Non-strict authentication (false): Authentication is cached. If only part of the media was cached last time, the player uses the cached authentication to make a request when playing the non-cached part next time. If the URL authentication validity period is very short, or playback resumes long after pausing, authentication may expire. To resolve this, integrate the auto-refresh playback sources feature.
Strict authentication (true): Authentication is not cached. Authentication is performed every time playback starts. This causes startup failure without a network.
Enable or disable local cache for a single URL
You can disable the local caching feature for a single URL by configuring a setting in the player config. The following example shows how to do this:
// Get the configuration first.
AVPConfig *config = [self.player getConfig];
// Whether to enable local cache for the playback URL. The default value is true. When the local cache in AliPlayerGlobalSettings is enabled, and the local cache here is also enabled (set to true), the local cache for this URL will take effect. If it is set to false here, the local cache for this URL is disabled.
config.enableLocalCache = false;
....// Other settings
// Set the configuration for the player.
[self.player setConfig:config];Use the default cache path
If you want to use the default path for caching, you can configure it as follows using AliPlayerGlobalSettings.
[AliPlayerGlobalSettings enableLocalCache:true];Preloading
iOS Player SDK provides preloading, an upgrade to local caching that downloads part of a video into the cache before playback begins, further improving startup speed.
The limits of the preloading feature are as follows:
Preloading supports single media files such as MP4, MP3, FLV, and HLS.
iOS Player SDK schedules preload network requests by default to reduce interference with the currently playing video. The preload request is sent only after the buffered content reaches a specific threshold. To disable this and manage requests in real-time, use the following:
[AliPlayerGlobalSettings enableNetworkBalance:false];Enable the local cache feature as described in Local cache.
You can set the data source.
VidAuth (recommended)
AVPVidAuthSource* vidAuthSource = [[AVPVidAuthSource alloc] init]; [vidAuthSource setVid:@"Vid information"]; // Required. The video ID (VideoId). [vidAuthSource setPlayAuth:@"<yourPlayAuth>"]; // Required. The playback credential. You need to call the GetVideoPlayAuth operation of ApsaraVideo VOD to generate it. [vidAuthSource setRegion:@"Access region"]; // For player SDK V5.5.5.0 and later, this parameter is deprecated. You do not need to set the region. The player will automatically parse the region. For player SDK versions earlier than 5.5.5.0, this parameter is required. The access region of ApsaraVideo VOD. The default is cn-shanghai. [vidAuthSource setQuality:@"Selected definition"]; //"AUTO" represents adaptive bitrate.VidSts
AVPVidStsSource* vidStsSource = [[AVPVidStsSource alloc] init]; [vidStsSource setVid: @"Vid information"]; // Required. The video ID (VideoId). [vidStsSource setRegion:@"Access region"]; // Required. The access region of ApsaraVideo VOD. The default is cn-shanghai. [vidStsSource setSecurityToken: @"<yourSecurityToken>"]; // Required. The STS security token. You need to call the AssumeRole operation of STS to generate it. [vidStsSource setAccessKeySecret: @"<yourAccessKeySecret>"]; // Required. The AccessKey secret of the temporary STS AccessKey pair. You need to call the AssumeRole operation of STS to generate it. [vidStsSource setAccessKeyId: @"<yourAccessKeyId>"]; // Required. The AccessKey ID of the temporary STS AccessKey pair. You need to call the AssumeRole operation of STS to generate it. [vidStsSource setQuality:@"Selected definition"]; //"AUTO" represents adaptive bitrate.UrlSource
NSString* url = @"Playback URL"; // Required. The playback URL. It can be a third-party VOD URL or a playback URL from ApsaraVideo VOD. AVPUrlSource* urlSource = [[AVPUrlSource alloc]urlWithString:url];Set task parameters.
NoteThis applies only to multi-bitrate videos. You can choose any one of
setDefaultBandWidth,setDefaultResolution, orsetDefaultQuality.AVPPreloadConfig *config = [[AVPPreloadConfig alloc]init]; // Set the preload bitrate for a multi-bitrate stream. [config setDefaultBandWidth:400000]; // Set the preload resolution for a multi-bitrate stream. [config setDefaultResolution:640 * 480]; // Set the preload quality for a multi-bitrate stream. [config setDefaultQuality:@"FD"]; // Set the preload duration. [config setDuration:1000];Add a task listener.
Build the task, add it to the
MediaLoaderV2instance, and start preloading.VidAuth (recommended)
// Build the preload task. AVPPreloadTask* mPreloadTask = [[AVPPreloadTask alloc]initWithVidAuthSource:vidAuthSource preloadConfig:config]; // Get the MediaLoaderV2 instance. AliMediaLoaderV2* vodMedialoader = [AliMediaLoaderV2 shareInstance]; // Add the task and start preloading. NSString* taskId = [vodMedialoader addTask:mPreloadTask listener:self];VidSts
// Build the preload task. AVPPreloadTask* mPreloadTask = [[AVPPreloadTask alloc]initWithVidStsSource:vidStsSource preloadConfig:config]; // Get the MediaLoaderV2 instance. AliMediaLoaderV2* vodMedialoader = [[AliMediaLoaderV2 alloc]init]; // Add the task and start preloading. NSString* taskId = [vodMedialoader addTask:mPreloadTask listener:self];UrlSource
// Build the preload task. AVPPreloadTask* mPreloadTask = [[AVPPreloadTask alloc]initWithUrlSource:urlSource preloadConfig:config]; // Get the MediaLoaderV2 instance. AliMediaLoaderV2* vodMedialoader = [[AliMediaLoaderV2 alloc]init]; // Add the task and start preloading. NSString* taskId = [vodMedialoader addTask:mPreloadTask listener:self];Optional: Manage tasks.
[vodMedialoader cancelTask:taskId];// Cancel the preload task with the specified task ID. [vodMedialoader pauseTask:taskId];// Pause the preload task with the specified task ID. [vodMedialoader resumeTask:taskId];// Resume the preload task with the specified task ID.Optional: Delete loaded files.
You can delete loaded files as needed to save space. The SDK does not provide a delete interface. You need to delete the files in the loading directory in the app.
Dynamic preloading
The dynamic preloading policy lets you balance playback experience and cost by controlling the cache of the current video and the number of preloaded items.
Preload multi-bitrate HLS videos
In listPlayer multi-bitrate HLS video playback scenarios, you can preload a stream that matches the current playback definition and choose a preload mode as needed.
Get the download speed
Get the download speed of the currently playing video in the onCurrentDownloadSpeed callback.
- (void)onCurrentDownloadSpeed:(AliPlayer *)player speed:(int64_t)speed{
intspeed_=speed;
}Network features
HTTPDNS
HTTPDNS sends domain resolution requests to specific HTTPDNS servers via DNS resolution technology for faster, more stable results and reduced DNS hijacking risk.
The ApsaraVideo Player SDK provides enhanced HTTPDNS exclusively for Alibaba Cloud CDN domains, supporting precise CDN scheduling and real-time resolution for improved network performance.
Enhanced HTTPDNS usage example
Enhanced HTTPDNS only works for Alibaba Cloud CDN domains. Ensure your domain is a configured Alibaba Cloud CDN domain. For adding/configuring CDN domains in VOD, see Add accelerated domain. For more CDN domain info, see Alibaba Cloud CDN.
// Enable enhanced HTTPDNS.
[AliPlayerGlobalSettings enableEnhancedHttpDns:YES];
// Optional. Add a domain name for HTTPDNS pre-resolution.
[[AliDomainProcessor shareInstance] addPreResolveDomain:@"player.***alicdn.com"];HTTP/2
iOS Player SDK enables HTTP/2 by default starting from V5.5.0.0.
iOS Player SDK supports HTTP/2, which uses multiplexing to avoid head-of-line blocking and improve playback performance.
[AliPlayerGlobalSettings setUseHttp2:true];Pre-establishing TCP connections for HTTP
For HTTP (not HTTPS) video playback requests, pre-establishing TCP connections significantly improves user experience, reduces connection time, ensures playback immediacy and continuity, and optimizes network and system resource usage.
// Domain format is host[:port]. Port is optional. Multiple domain names are separated by semicolons (;).
// Global setting.
// Each time the full interface is set, the current string is used (add for more, delete for less). An empty string stops pre-connection.
[AliPlayerGlobalSettings setOption:SET_PRE_CONNECT_DOMAIN value: @"domain1;domain2"];Video download
For detailed code examples, see the Download module in the API-Example project. This project is an Objective-C-based iOS sample project for the ApsaraVideo Player SDK that helps developers quickly master core SDK integration.
iOS Player SDK provides a video download feature for ApsaraVideo VOD content, with standard and secure modes.
Standard download: The downloaded video is not encrypted and can be played by third-party players.
Secure download: The downloaded video is encrypted and can only be played by the ApsaraVideo Player.
Usage notes
Only the VidSts and VidAuth methods enable the video download feature.
Enable and configure the download mode in the ApsaraVideo VOD console. For more information, see Offline Download.
The SDK supports resumable downloads.
Procedure
Optional: Configure the encryption verification file for secure download. Only required for secure download. Not required for standard download.
NoteEnsure the encryption verification file matches the app information. Otherwise, the video download fails.
If you use secure download, configure the key file generated in the ApsaraVideo VOD console in the Player SDK. The key file is used to decrypt and verify the video for download and playback. For more information about generating the key file, see Enable secure download.
We recommend configuring the key file once in the Application.
NSString *encrptyFilePath = [[NSBundle mainBundle] pathForResource:@"encryptedApp" ofType:@"dat"]; [AliPrivateService initKey:encrptyFilePath];Create and set up the downloader.
Example:
AliMediaDownloader *downloader = [[AliMediaDownloader alloc] init]; [downloader setSaveDirectory:self.downLoadPath]; [downloader setDelegate:self];Set event listeners.
The downloader provides multiple listeners.
-(void)onPrepared:(AliMediaDownloader *)downloader mediaInfo:(AVPMediaInfo *)info { // The download item is successfully prepared. } -(void)onError:(AliMediaDownloader *)downloader errorModel:(AVPErrorModel *)errorModel { // A download error occurred. } -(void)onDownloadingProgress:(AliMediaDownloader *)downloader percentage:(int)percent { // Download progress percentage. } -(void)onProcessingProgress:(AliMediaDownloader *)downloader percentage:(int)percent { // Processing progress percentage. } -(void)onCompletion:(AliMediaDownloader *)downloader { // The download is successful. }Prepare the download source.
Call the
preparemethod to prepare a download source. This method supports VidStsSource and VidAuthSource.VidSts
// Create VidSts. AVPVidStsSource* stsSource = [[AVPVidStsSource alloc] init]; stsSource.region = @"Access region"; // The access region of ApsaraVideo VOD. The default is cn-shanghai. stsSource.vid = @"Vid information"; // The video ID (VideoId). stsSource.securityToken = @"<yourSecurityToken>"; // The STS security token. You need to call the AssumeRole operation of STS to generate it. stsSource.accessKeySecret = @"<yourAccessKeySecret>"; // The AccessKey secret of the temporary STS AccessKey pair. You need to call the AssumeRole operation of STS to generate it. stsSource.accessKeyId = @"<yourAccessKeyId>"; // The AccessKey ID of the temporary STS AccessKey pair. You need to call the AssumeRole operation of STS to generate it. // If you have enabled HLS standard encryption parameter pass-through in the VOD console, and the default parameter name is MtsHlsUriToken, you need to set the config and pass it into the vid. See below. // If you have not enabled HLS standard encryption parameter pass-through in the VOD console, you do not need to integrate the following code. VidPlayerConfigGenerator* vp = [[VidPlayerConfigGenerator alloc] init]; [vp setHlsUriToken:yourMtsHlsUriToken]; stsSource.playConfig = [vp generatePlayerConfig]; // Prepare the download source. [downloader prepareWithVid:stsSource];VidAuth
// Create VidAuth. AVPVidAuthSource *authSource = [[AVPVidAuthSource alloc] init]; authSource.vid = @"Vid information"; // The video ID (VideoId). authSource.playAuth = @"<yourPlayAuth>"; // The playback credential. You need to call the GetVideoPlayAuth operation of ApsaraVideo VOD to generate it. authSource.region = @"Access region"; // For player SDK V5.5.5.0 and later, this parameter is deprecated. You do not need to set the region. The player will automatically parse the region. For player SDK versions earlier than 5.5.5.0, this parameter is required. The access region of ApsaraVideo VOD. The default is cn-shanghai. // If you have enabled HLS standard encryption parameter pass-through in the VOD console, and the default parameter name is MtsHlsUriToken, you need to set the config and pass it into the vid. See below. // If you have not enabled HLS standard encryption parameter pass-through in the VOD console, you do not need to integrate the following code. VidPlayerConfigGenerator* vp = [[VidPlayerConfigGenerator alloc] init]; [vp setHlsUriToken:yourMtsHlsUriToken]; authSource.playConfig = [vp generatePlayerConfig]; // Prepare the download source. [downloader prepareWithVid:authSource];
NoteIf you enable parameter pass-through for HLS encryption in the ApsaraVideo VOD console, the default parameter is MtsHIsUriToken. For more information, see Parameter pass-through for HLS encryption. Then, set the MtsHIsUriToken value to the ApsaraVideo VOD source by following the preceding code.
Select a download item after preparation succeeds.
After the download source is prepared, the
onPreparedmethod is called. The TrackInfo parameter provides information about video streams, such as their definitions. You can select a track to download. The following sample code provides an example:-(void)onPrepared:(AliMediaDownloader *)downloader mediaInfo:(AVPMediaInfo *)info { NSArray<AVPTrackInfo*>* tracks = info.tracks; // For example, download the first TrackInfo. [downloader selectTrack:[tracks objectAtIndex:0].trackIndex]; }Update the download source and start the download.
VidSts or VidAuth may expire before the download. Therefore, we recommend updating the download source before you start the download.
// Update the download source. [downloader updateWithVid:vidSource] // Start the download. [downloader start];Release the downloader after download success or failure.
After the download succeeds, call
destroyto release the downloader.[self.downloader destroy]; self.downloader = nil;
Encrypted playback
ApsaraVideo VOD supports HLS standard encryption, Alibaba Cloud proprietary encryption, and DRM encryption. Live streaming supports only DRM encryption. For instructions, see Play an encrypted video.
Native RTS playback
The SDK integrates the Native RTS SDK to implement low-latency live streaming. For more information, see Implement RTS stream pulling on iOS.