All Products
Search
Document Center

ApsaraVideo VOD:Advanced features

Last Updated:Mar 12, 2026

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.

Important

To try out the demo, download it and follow the instructions in Run the demo to compile and run the project.

Professional skill confirmation

Note

Some player features require a Professional Edition license. For more information, see Features. To obtain a license, refer to Obtain a license.

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 professional capabilities. When you use a related feature, the player verifies the capability and returns the verification result through this callback. If isValid is false, errorMsg contains the specific reason.

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.

Procedure

  1. Create a player.

    Create an AliListPlayer instance.

    self.listPlayer = [[AliListPlayer alloc] init];
    [self.listPlayer setTraceID:@"xxxxxx"];  // The TraceID is a unique identifier for a device or user, such as an IMEI or IDFA.

  2. Optional: Set listeners.

    When you create list playback, the listener is optional. However, if you do not configure it, you will not receive event notifications such as playback failure or playback progress from the player. Therefore, we recommend that you configure it.

    The player supports setting multiple listeners. We recommend that you set onPlayerEvent and onError because they are particularly important.

    /**
     @brief Error callback.
     @param player The player pointer.
     @param errorModel The player error description. See AliVcPlayerErrorModel.
     */
    - (void)onError:(AliPlayer*)player errorModel:(AVPErrorModel *)errorModel {
        // Display an error message and stop playback.
    }
    /**
     @brief Player event callback.
     @param player The player pointer.
     @param eventType The player event type. See AVPEventType.
     */
    -(void)onPlayerEvent:(AliPlayer*)player eventType:(AVPEventType)eventType {
        switch (eventType) {
            case AVPEventPrepareDone: {
                // The player is prepared.
            }
                break;
            case AVPEventAutoPlayStart:
                // Autoplay starts.
                break;
            case AVPEventFirstRenderedStart:
                // The first frame is rendered.
                break;
            case AVPEventCompletion:
                // Playback is complete.
                break;
            case AVPEventLoadingStart:
                // Buffering starts.
                break;
            case AVPEventLoadingEnd:
                // Buffering is complete.
                break;
            case AVPEventSeekEnd:
                // Seeking is complete.
                break;
            case AVPEventLoopingStart:
                // Loop playback starts.
                break;
            default:
                break;
        }
    }
    /**
     @brief Callback for the current playback position.
     @param player The player pointer.
     @param position The current playback position.
     */
    - (void)onCurrentPositionUpdate:(AliPlayer*)player position:(int64_t)position {
        // Update the progress bar.
    }
    /**
     @brief Callback for the video's buffered position.
     @param player The player pointer.
     @param position The current buffered position.
     */
    - (void)onBufferedPositionUpdate:(AliPlayer*)player position:(int64_t)position {
        // Update the buffer progress.
    }
    /**
     @brief Callback for track information.
     @param player The player pointer.
     @param info An array of track stream information. See AVPTrackInfo.
     */
    - (void)onTrackReady:(AliPlayer*)player info:(NSArray<AVPTrackInfo*>*)info {
        // Get information about multi-bitrate streams.
    }
    /**
     @brief Callback for displaying subtitles.
     @param player The player pointer.
     @param trackIndex The index of the subtitle stream.
     @param subtitleID The subtitle ID.
     @param subtitle The string to be displayed as subtitle.
     */
    - (void)onSubtitleShow:(AliPlayer*)player trackIndex:(int)trackIndex subtitleID:(long)subtitleID subtitle:(NSString *)subtitle {
        // Display the subtitles.
    }
    /**
     @brief Callback for hiding subtitles.
     @param player The player pointer.
     @param trackIndex The index of the subtitle stream.
     @param subtitleID The subtitle ID.
     */
    - (void)onSubtitleHide:(AliPlayer*)player trackIndex:(int)trackIndex subtitleID:(long)subtitleID {
        // Hide the subtitles.
    }
    /**
     @brief Callback for taking a snapshot.
     @param player The player pointer.
     @param image The image.
     */
    - (void)onCaptureScreen:(AliPlayer *)player image:(UIImage *)image {
        // Preview and save the snapshot.
    }
    /**
     @brief Callback for when a track switch is complete.
     @param player The player pointer.
     @param info The information of the new track. See AVPTrackInfo.
     */
    - (void)onTrackChanged:(AliPlayer*)player info:(AVPTrackInfo*)info {
        // Notification for bitrate switching result.
    }
    //...
  3. Set the preload count.

    Setting a reasonable preload count can effectively improve startup speed.

    self.listPlayer.preloadCount = 2;
  4. Add or remove playback sources.

    List playback supports two source types: VidSts and UrlSource. Url is the playback URL. Vid is the audio/video ID (VideoId) for on-demand videos.

    • UrlSource: A playback URL from ApsaraVideo VOD or a third-party service.

      You can retrieve a URL for a media asset in ApsaraVideo VOD by calling the GetPlayInfo operation. We recommend integrating the server-side SDK of ApsaraVideo VOD to retrieve playback URLs. This simplifies the process by handling URL signing automatically. For an example, see OpenAPI Explorer.

    • Vid: The ID of the audio or video file. You can obtain this ID from the console (path: Media Library > Audio/Video) or by calling a server-side API (Search media information) after the file is uploaded.

    // Add a VidSts source.
    [self.listPlayer addVidSource:videoId uid:UUIDString];
    // Add a UrlSource.
    [self.listPlayer addUrlSource:URL uid:UUIDString];
    // Remove a source.
    [self.listPlayer removeSource:UUIDString];
    Note
    • The UID is a unique identifier for a video. It distinguishes whether videos are identical. If UIDs match, the videos are considered identical. If videos play out of order, check whether the same UID is set for different videos. UIDs have no format restrictions and can be any string.

  5. Set the display view.

    If the source contains video content, set a view in the player to display it.

    self.listPlayer.playerView = self.simplePlayScrollView.playView;
  6. Play a video source.

    After you add one or more video sources, calling moveTo enables autoplay for a specific video source. The following example shows how to do this:

    // Use this API for UrlSource playback.
    - (BOOL) moveTo:(NSString*)uid;
    // Use this API for VidSts playback. You must pass the temporary STS credential and temporary AccessKey pair. Get them in advance. For more information, see Create a RAM role and perform STS temporary authorization.
    - (BOOL) moveTo:(NSString*)uid accId:(NSString*)accId accKey:(NSString*)accKey token:(NSString*)token region:(NSString*)region;
  7. Play the previous or next video.

    After you call moveTo to play a video source, call moveToPrev or moveToNext to play the previous or next video, using the video source from the moveTo call as an anchor. The following is an example:

    Note

    When you use the same view and call moveTo or moveToNext to switch video sources, the screen may flicker or briefly turn black. To prevent this, set the clearShowWhenStop field of PlayerConfig to false when you initialize listPlayer and call setConfig to apply the change.

    UrlSource playback source

    //Move to the next video.
    - (BOOL) moveToNext;
    //Move to the previous video.
    - (BOOL) moveToPre;

    VidSts Playback Source

    // Move to the next video.
    - (BOOL) moveToNext:(NSString*)accId accKey:(NSString*)accKey token:(NSString*)token region:(NSString*)region;
    // Move to the previous video.
    - (BOOL) moveToPre:(NSString*)accId accKey:(NSString*)accKey token:(NSString*)token region:(NSString*)region;
Note

For an enhanced list playback experience, use our short-form drama solution. For more information, see Mini-Drama Client Development.

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

Using MP4 videos with transparency for gift effects delivers better animation quality, smaller file sizes, higher compatibility, and greater development efficiency. This enables gift effects to be displayed more effectively to users, enhancing the user experience.

  1. Better animation quality: MP4 videos preserve original animation details and colors more accurately than other formats.

  2. Smaller file size: MP4 video files compress more effectively than other formats, such as APNG or IXD, which results in faster load times and lower network bandwidth consumption.

  3. Higher compatibility: The MP4 format is widely supported across devices and browsers.

  4. Using MP4 videos for gift effects improves development efficiency. This technical solution is straightforward, freeing developers from researching and implementing complex parsing and rendering logic so they can focus on other features.

Sample code

Use the alphaRenderMode property to set the position of the alpha channel in the video material (top, bottom, left, or right). The default value is None.

Note
  • The position of the alpha channel in the video asset must match the alphaRenderMode setting.

  • The size of the view must be proportional to the resolution of the material.

/**
 @brief Alpha rendering mode. Supports alpha at the right, left, top, or bottom. The default value is none.
 @see AVPAlphaRenderMode
 */
/****
 @brief Set a rendering mode. Support alpha at right, left, top and bottom. Default value is none.
 @see AVPAlphaRenderMode
 */
@property(nonatomic) AVPAlphaRenderMode alphaRenderMode;
//--------------View usage-------------
// For the player's view, set a clear background color.
@property (weak, nonatomic) IBOutlet UIView *mediaPlayerView;
[self.aliplayerview setBackgroundColor:UIColor.clearColor];

//-----------AliPlayer usage-----------
// Set the alpha mode.
[self.player setAlphaRenderMode:AVP_RENDERMODE_ALPHA_AT_LEFT];
// Set the material corresponding to the alpha mode.
AVPUrlSource *source = [[AVPUrlSource alloc] urlWithString:@"https://alivc-player.oss-cn-shanghai.aliyuncs.com/video/%E4%B8%9A%E5%8A%A1%E9%9C%80%E6%B1%82%E6%A0%B7%E6%9C%AC/alpha%E9%80%9A%E9%81%93/alpha_left.mp4"];
[self.player setUrlSource:source];

// Optional: Clear the screen after playback completion to prevent visual artifacts.
#pragma mark -- AVPDelegate
- (void)onPlayerEvent:(AliPlayer *)player eventType:(AVPEventType)eventType {
    switch (eventType) {
        case AVPEventCompletion:
        {
            [player clearScreen];
        }
            break;
        //...
    }
}

[self.player setAutoPlay: YES];
[self.player prepare];

Metal rendering

The ApsaraVideo Player SDK for iOS supports video rendering using the Metal framework.

Note

Currently, only setting the background color, scaling mode, and Picture-in-Picture (PiP) are supported with Metal rendering.

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 examples

AVPConfig *config = [self.player getConfig];
// Enable Metal rendering.
config.videoRenderType = 1;
[self.player setConfig:config];
[self.player prepare];

External subtitles

Note

For a detailed code example, see the ExternalSubtitle module in the API-Example project. This project is based on Objective-C and demonstrates core SDK integration for the ApsaraVideo Player SDK for iOS.

The ApsaraVideo Player SDK for iOS supports adding and switching external subtitles in SRT, SSA, ASS, and VTT formats.

Examples:

  1. 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];
  2. 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];
    }
  3. Add a subtitle track.

    [self.player addExtSubtitle:URL];
  4. Switch a subtitle track.

    [self.player selectExtSubtitle:trackIndexenable:YES];

External subtitles (custom rendering with rendering components)

Full support for WebVTT external subtitles is implemented using AliVttSubtitleView and AliVttRenderImpl, enabling flexible customization of font size, color, and specific fonts.

Note

Use cases:

  • Customize WebVTT subtitle styles such as font, color, and size.

  • Integrate ApsaraVideo Player SDK 7.11.0 and use AliVttSubtitleView.

  • Support multilingual subtitles (such as Arabic, Chinese, Japanese, and Korean) with automatic font matching.

Important

Prerequisites:

  • Font files (.ttf) are added to the Xcode project.

  • Subtitle listeners are added and WebVTT content can be retrieved.

  • The loadFontFromBundle method successfully loads fonts.

Steps to customize subtitle styles

  1. 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
  2. (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);
        }
    }
  3. 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 font
        [impl loadCustomFontFromBundle:@"LongCang-Regular"];
        
        return impl;
    }];
    
    // Associate with player
    [player setExternalSubtitleView:subtitleView];
  4. 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

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 a toggle: enableHardwareDecoder. This toggle is enabled by default, and the SDK automatically switches to software decoding if hardware decoding initialization fails, ensuring normal video playback. The following example shows this configuration:

// Enable hardware decoding. It is enabled by default.
self.player.enableHardwareDecoder = YES;

If the player automatically switches from hardware decoding to software decoding, a notification is sent through the onPlayerEvent callback. The following is an example:

-(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 in 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.

Note
  • This feature is enabled only after you activate the cloud-native adaptive decoding value-added 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

Note

The iOS Player SDK supports adaptive bitrate HLS and DASH video streams. After the prepare method completes successfully, you can retrieve information for each bitrate stream by calling getMediaInfo, which retrieves TrackInfo objects. The following example shows how to do this:

AVPMediaInfo *info = [self.player getMediaInfo];
NSArray<AVPTrackInfo*>* tracks = info.tracks;

During playback, you can switch the playing stream by calling the player's selectTrack method. When the value is SELECT_AVPTRACK_TYPE_VIDEO_AUTO, adaptive bitrate streaming is enabled. The following example shows this:

// Switch to a specific bitrate.
[self.player selectTrack:track.trackIndex];
// Enable adaptive bitrate switching.
[self.player selectTrack:SELECT_AVPTRACK_TYPE_VIDEO_AUTO];

The result of the switch is returned in the onTrackChanged callback. The following is an example:

- (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 switch the playback stream to adaptive bitrate streaming, you can set an upper limit for the definition in adaptive bitrate (ABR) switching through config to prevent automatic switching to an unexpectedly high bitrate. Example: (We recommend calling the following code before the player calls the prepare method or the list 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 method to take a screenshot of the current video. This method captures the raw data and returns it as a bitmap. The callback method is onCaptureScreen. The following is an example:

// Snapshot callback.
- (void)onCaptureScreen:(AliPlayer *)player image:(UIImage *)image {
    // Process the snapshot.
}
// Take a snapshot of the current frame.
[self.player snapShot];
Note

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) playback. For configuration instructions, see Preview videos.

After you configure the preview feature, use the setPreviewTime method of the VidPlayerConfigGen interface to set the preview duration. The following example uses the VidSts playback method:

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.

Note

VidPlayerConfigGen supports setting various server-side request parameters. See Request parameter descriptions.

Set the Referer

The iOS Player SDK supports setting the Referer. When used together with the Referer blacklists and whitelists in the console, it can control access permissions. You can set the Referer of the request using the AVPConfig method. The following is an example of iOS Player SDK configuration:

// 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 (UA) header. After you set this header, the player includes the UA header in its HTTP requests. The following example demonstrates this:

// 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 is 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];
Note
  • 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 onError event is triggered with AVPErrorModel.code set to ERROR_LOADING_TIMEOUT.

  • If you set networkRetryCount to 0, the player triggers the onPlayerEvent callback with eventWithString set to EVENT_PLAYER_NETWORK_RETRY when a network retry times out. You can then call the player’s reload method to reload the network or perform other actions.

Configure cache and latency control

For a player, cache control is critical. Proper configuration can effectively improve startup speed and reduce stuttering. The iOS player SDK provides a control interface for configuring cache and latency through AVPConfig. The following example shows how to do this:

// 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];
Important
  • 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. For example:

// 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

Note

For detailed code examples, see the PictureInPicture module in the API-Example project. This project is based on Objective-C and demonstrates core SDK integration for the ApsaraVideo Player SDK for iOS.

Note
  • PiP requires iOS 15 or later and the ApsaraVideo Player SDK for iOS 5.4.9.0 or later.

  • For versions of the 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 you enable the Picture-in-Picture (PiP) feature, the video continues to play in a small window when the application is moved to the background. When the application is brought back to the foreground, the video resumes its original playback format and continues to play. The PiP feature is controlled by the setPictureInPictureEnable switch and must be enabled when the player is in the AVPEventPrepareDone state. The following example shows how to enable the PiP feature:

- (void)onPlayerEvent:(AliPlayer *)player eventType:(AVPEventType)eventType {
    switch (eventType) {
        case AVPEventPrepareDone:
        {
            [self.player setPictureInPictureEnable:YES];
        }
            break;
        default:
            break;
    }
}
Note

When you call stop to stop playback, you must first disable Picture-in-Picture (PiP) by calling setPictureInPictureEnable, and then call stop.

Set the PiP delegate

This section provides common code examples for interaction between Picture-in-Picture (PiP) windows and player windows. These examples include the logic for displaying PiP's pause, playback, fast forward, fast backward, and replay buttons. For details about the delegate methods, see the Player SDK Demo, specifically the AliPlayerPictureInPictureDelegate.h header file in the AliyunPlayer.framework folder.

  1. Set the PiP delegate.

    /**
    * @brief Set the PiP delegate.
    */
    -(void) setPictureinPictureDelegate:(id<AliPlayerPictureInPictureDelegate>)delegate;
    
    
    // Set the PiP delegate.
    [self.player setPictureinPictureDelegate:self];
  2. Add variables and implement the delegate interface.

    1. Add global variables to manage the player and PiP state.

      #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;
      
      @end
      Note

      You 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.

    2. 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];
         }
      }
    3. When you listen for playback event callbacks, call the following method to update the Picture-in-Picture (PiP) controller's status.

      - (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];
          }
        }
      }
    4. 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);
            }
        }
      • Callback for monitoring whether Picture-in-Picture (PiP) is 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;
        }
        Note

        This 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

Note

For a detailed code example, see the RtsLiveStream module in the API-Example project. This project is based on Objective-C and demonstrates core SDK integration for the ApsaraVideo Player SDK for iOS.

For more information, see RTS live playback.

Switch left and right sound channels

In the iOS player SDK, you can use the outputAudioChannel property to set the output audio channel. If the input source is stereo, you can use the methods described below to switch to the left or right audio channel. This setting has no effect if the input source is mono.

Note

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

You can use the Player SDK for iOS to set the background color for rendering. The API and its usage are as follows:

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 a list of supported fields, see GetPlayInfo. The interface and usage instructions are as follows:

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

  1. Use the Player or all-in-one SDK V7.6.0 or later.

  2. You have completed authorization of your Professional Edition license. For more information, see Obtaining a Player SDK License.

  3. ApsaraVideo Player with the H.266 decoding plug-in supports only H.266 videos encoded by ApsaraVideo Transcoding.

Integrate the plugin

Player SDK

CocoaPods (recommended)

Add the dependency to your Podfile.

Note

For the latest version of the iOS SDK, see Release notes for ApsaraVideo Player SDK for iOS.

// x.x.x must be the same as the version number of ApsaraVideo Player SDK.
pod 'AliPlayerSDK_iOS_VVC_CODEC_PLUGIN', 'x.x.x'

Local integration

Download the latest iOS ApsaraVideo Player SDK. Add vvcCodecPlugin.framwork to Frameworks, Libraries, and Embedded Content. Set Embed to Embed & Sign. Configure Framework Search Paths. For details, see Local integration.

All-in-one SDK

CocoaPods (recommended)

Add the dependency to your Podfile.

// x.x.x must be the same as the version number of the integrated SDK you are using.
pod 'AliVCSDK_Standard/AliPlayerSDK_iOS_VVC_CODEC', 'x.x.x'

Local integration

Download the latest iOS all-in-one package. Extract it and add plugins/vvcCodecPlugin.framework to Frameworks, Libraries, and Embedded Content. Set Embed to Embed & Sign. Configure Framework Search Paths. For details, see Local integration.

Activate the plugin

Note

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 continuous and smooth playback.

Prerequisites

  1. Use the Player or all-in-one SDK V7.9.0 or later.

  2. Use VidAuth sources or configure URL signing.

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 video playback.

 @param callback The callback block triggered when the VidAuth source expires.
 You can use this callback to return a valid `VidAuth` object 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

Function composition

/**
 @protocol AVPSourceRefreshCallback
 @brief A protocol for handling playback source refresh results, which developers need to implement.

 This protocol notifies developers when the player requests playback source refresh, such as when a resource
 has expired or needs updating. The methods in this protocol are called to provide the refresh results to the developer,
 including success or failure.

 @note This protocol applies to URL source, VidAuth source, and similar scenarios requiring refresh logic.
 */
 /****
 @brief A protocol for handling playback source refresh results, which developers need to implement.

 This protocol notifies developers when the player requests playback source refresh, such as when a resource
 has expired or needs updating. The methods in this protocol are called to provide the refresh results to the developer,
 including success or failure.

 @note This protocol applies to URL source, VidAuth source, and similar scenarios requiring refresh logic.
 */
@protocol AVPSourceRefreshCallback <NSObject>

/**
 @brief Called by the player when the refresh operation succeeds.
 @param newSource The new playback source object containing the updated information.

 This method indicates that the refresh operation has been successfully completed. Developers need to pass
 the updated `newSource` back to the player so that it can load the latest resource.
 */
 /****
 @brief Called by the player when the refresh operation succeeds.
 
 @param newSource The new playback source object containing the updated information.

 This method indicates that the refresh operation has been successfully completed. Developers need to pass
 the updated `newSource` back to the player so that it can load the latest resource.
 */
- (void)onSuccess:(id)newSource;

/**
 @brief Called by the player when the refresh operation fails.
 @param errorMsg A string describing the reason for the failure.

 This method indicates that the refresh operation has failed. Developers can use `errorMsg` to capture failure
 details and handle subsequent processing accordingly.
 */
 /****
 @brief Called by the player when the refresh operation fails.
 
 @param errorMsg A string describing the reason for the failure.

 This method indicates that the refresh operation has failed. Developers can use `errorMsg` to capture failure
 details and handle subsequent processing accordingly.
 */
- (void)onError:(NSString *)errorMsg;

@end

Usage

You can retrieve 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 starts -------------------
        // 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 use `callback` to return the new URL source, ensuring uninterrupted video 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 use this callback to provide a valid `URLSource` object 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

Function composition

/**
 @protocol AVPSourceRefreshCallback
 @brief A protocol for handling playback source refresh results, which developers need to implement.

 This protocol notifies developers when the player requests playback source refresh, such as when a resource
 has expired or needs updating. The methods in this protocol are called to provide the refresh results to the developer,
 including success or failure.

 @note This protocol applies to URL source, VidAuth source, and similar scenarios requiring refresh logic.
 */
 /****
 @brief A protocol for handling playback source refresh results, which developers need to implement.

 This protocol notifies developers when the player requests playback source refresh, such as when a resource
 has expired or needs updating. The methods in this protocol are called to provide the refresh results to the developer,
 including success or failure.

 @note This protocol applies to URL source, VidAuth source, and similar scenarios requiring refresh logic.
 */
@protocol AVPSourceRefreshCallback <NSObject>

/**
 @brief Called by the player when the refresh operation succeeds.
 @param newSource The new playback source object containing the updated information.

 This method indicates that the refresh operation has been successfully completed. Developers need to pass
 the updated `newSource` back to the player so that it can load the latest resource.
 */
 /****
 @brief Called by the player when the refresh operation succeeds.
 
 @param newSource The new playback source object containing the updated information.

 This method indicates that the refresh operation has been successfully completed. Developers need to pass
 the updated `newSource` back to the player so that it can load the latest resource.
 */
- (void)onSuccess:(id)newSource;

/**
 @brief Called by the player when the refresh operation fails.
 @param errorMsg A string describing the reason for the failure.

 This method indicates that the refresh operation has failed. Developers can use `errorMsg` to capture failure
 details and handle subsequent processing accordingly.
 */
 /****
 @brief Called by the player when the refresh operation fails.
 
 @param errorMsg A string describing the reason for the failure.

 This method indicates that the refresh operation has failed. Developers can use `errorMsg` to capture failure
 details and handle subsequent processing accordingly.
 */
- (void)onError:(NSString *)errorMsg;

@end

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, consider 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 authKey
        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 validTime; 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. Callback handling
        if (newAuthUrl) {
            [callback onSuccess:resultSource];
        } else {
            [callback onError:@"REFRESH_ERROR:refresh fail"];
        }
    }
}];

Utility functions

For example, using signing method A.

Utility functions

#import "CdnAuthUtil.h"
#import <CommonCrypto/CommonDigest.h>

@implementation CdnAuthUtil

#pragma mark - Auth Method A
+ (NSString *)aAuthWithUri:(NSString *)uri key:(NSString *)key exp:(NSTimeInterval)exp {
    NSDictionary *components = [self matchUri:uri];
    if (!components) return nil;

    NSString *scheme = components[@"scheme"];
    NSString *host = components[@"host"];
    NSString *path = components[@"path"];
    NSString *args = components[@"args"];

    NSString *rand = @"0";
    NSString *uid = @"0";

    NSString *sstring = [NSString stringWithFormat:@"%@-%lld-%@-%@-%@", path, (long long)exp, rand, uid, key];
    NSString *hashvalue = [self md5sum:sstring];
    NSString *authKey = [NSString stringWithFormat:@"%lld-%@-%@-%@", (long long)exp, rand, uid, hashvalue];

    if (args.length > 0) {
        return [NSString stringWithFormat:@"%@%@%@%@&auth_key=%@", scheme, host, path, args, authKey];
    } else {
        return [NSString stringWithFormat:@"%@%@%@%@?auth_key=%@", scheme, host, path, args, authKey];
    }
}

#pragma mark - Private Helper: MD5
+ (NSString *)md5sum:(NSString *)src {
    const char *cStr = [src UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(cStr, (unsigned int)strlen(cStr), result);

    NSMutableString *hexString = [NSMutableString string];
    for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        [hexString appendFormat:@"%02x", result[i]];
    }
    return hexString.copy;
}

#pragma mark - Private Helper: Regex Match
+ (NSDictionary *)matchUri:(NSString *)uri {
    NSError *error = nil;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^(https?://)?([^/?]+)(/[^?]*)?(\\?.*)?$"
                                  options:0
                                  error:&error];
    if (error) {
        NSLog(@"Regex error: %@", error.localizedDescription);
        return nil;
    }

    NSTextCheckingResult *match = [regex firstMatchInString:uri
                                   options:0
                                   range:NSMakeRange(0, uri.length)];
    if (!match) return nil;

    __block NSString *scheme = nil, *host = nil, *path = nil, *args = nil;

    void (^setStringFromRange)(NSInteger, NSString**) = ^(NSInteger idx, NSString **outStr) {
        NSRange range = [match rangeAtIndex:idx];
        if (range.location != NSNotFound && range.length > 0) {
            *outStr = [uri substringWithRange:range];
        } else {
            *outStr = nil;
        }
    };

    setStringFromRange(1, &scheme);
    setStringFromRange(2, &host);
    setStringFromRange(3, &path);
    setStringFromRange(4, &args);

    // Default value handling
    if (!scheme) scheme = @"http://";
    if (!path) path = @"/";

    return @{
        @"scheme": scheme,
        @"host": host,
        @"path": path,
        @"args": args ?: @""
        };
}
@end

Performance

Set the playback scenario

Setting the playback scenario automatically configures optimal parameters (including buffer settings and feature toggles) while preserving custom settings made via the setConfig interface (custom settings take precedence).

Note
  • After setting the playback scenario, use the getConfig interface to view the parameter configuration.

API example

/**
 @brief Set player scenario.
 @param scene Player scenario.
 @see AVPScenario
 */
/****
 @brief Set player scene.
 @param scene Player scene.
 @see AVPScene
 */
-(void) setPlayerScene:(AVPScene)scene;

Playback scenarios

typedef enum _AVPScene {
    /**
     * Scenario: None
     */
    /****
     * scene none
     */
    SceneNone,
    /**
     * Long-video scenario: Applies to videos longer than 30 minutes
     */
    /****
     * long scene: apply to more than 30min
     */
    SceneLong,
    /**
     * Medium-video scenario: Applies to videos 5–30 minutes long
     */
    /****
     * middle scene: apply to 5min-30min
     */
    SceneMedium,
    /**
     * Short-video scenario: Applies to videos up to 5 minutes long
     */
    /****
     * short scene: apply to 0s-5min
     */
    SceneShort,
    /**
     * Live-streaming scenario
     */
    /****
     * live scene
     */
    SceneLive,
    /**
     * Ultra-low-latency live-streaming scenario
     */
    /****
     * RTS live scene
     */
    SceneRTSLive
} AVPScene;

Usage

// Set short-video scenario
[self.player setPlayerScene:SceneShort];

// Set medium-video scenario
[self.player setPlayerScene:SceneMedium]; 

// Set long-video scenario
[self.player setPlayerScene:SceneLong];  

// Set live-streaming scenario
[self.player setPlayerScene:SceneLive];   

Pre-rendering

The ApsaraVideo Player SDK for iOS supports quickly rendering the first frame before playback starts, improving startup speed.

Note
  1. This feature is disabled by default.

  2. You must set the View before calling Prepare to ensure the frame is ready for rendering on the View.

  3. When enabled, this feature changes the order of the preparation success and first-frame rendering events: Without it, preparation success fires first, then first-frame rendering. With it, first-frame rendering may fire before preparation success, depending on decoding and rendering speed. This does not affect playback.

Example:

[self.player setOption:ALLOW_PRE_RENDER valueInt:1];

Local cache

Note

For detailed code examples, see the PreloadUrl module in the API-Example project. This project is based on Objective-C and demonstrates core SDK integration for the ApsaraVideo Player SDK for iOS.

The ApsaraVideo Player SDK for iOS provides local caching to improve startup speed, seek speed, and reduce stuttering for repeated video playback. It also saves bandwidth.

Enable local cache

The local caching feature is disabled by default. To use this feature, you must enable it manually. You can control this feature in AliPlayerGlobalSettings using enableLocalCache. The following is an example:

/**
 * Enable local cache. After enabling, it will cache to local files.
 * @param enable: Local cache feature switch. true: enable, false: disable. Default is disable.
 * @param maxBufferMemoryKB: Deprecated since V5.4.7.1. No effect.
 * @param localCacheDir: Must be set. 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];
Note
  • If the playback URL of a video file contains authentication parameters, the values of the authentication parameters change during the local caching and playback of the video file. You can call the setCacheUrlHashCallback operation to calculate the MD5 hash value after you remove the authentication parameters. For example, http://****.mp4?aaa is the playback URL of a video file that contains authentication parameters. In this case, the URL http://****.mp4 is used to calculate the MD5 hash value when the video file is loaded. However, if you calculate the MD5 hash value after you remove the authentication parameters in the key URL of an encrypted M3U8 video, the playback fails because different videos are hit by the same key URL. Solution: Remove the authentication parameters only from the playback URL http(s)://xxxxx.m3u8?aaaa but not the key URL http(s)://yyyyy?bbbb in the setCacheUrlHashCallback callback.进阶功能-本地缓存.png

  • If the server supports both HTTP and HTTPS protocols but points to the same media file, remove or unify the request headers before computing the MD5 value. For example:

    • If the video playback URLs are https://****.mp4 and http://****.mp4, use ****.mp4 to calculate the MD5 value.

    • If the video playback URL is https://****.mp4, unify it to http://****.mp4 before you calculate the MD5 value.

  • For Player SDK 5.5.4.0 and later, if the video playback URL contains authentication parameters and the playback protocol is HLS, you can set the AVPConfig.enableStrictAuthMode field to select a different authentication mode (The default value is false for earlier versions. The default value is true for 7.13.0 and later.):

    • Non-strict authentication (false): Authentication is cached. If only part of the media was cached previously, the player uses the cached authentication to request non-cached parts. If the URL authentication validity period is short, or playback resumes long after pausing, authentication may expire. Combine with the auto-refresh playback sources feature to handle expired authentication during resume.

    • Strict authentication (true): Authentication is not cached. Authentication occurs on every startup, causing startup failure without network connectivity.

Enable or disable local cache for a single URL

If you want to disable the local cache feature for a single URL, you can set this in the player config. The following is an example:

// Get the configuration first.
AVPConfig *config = [self.player getConfig];
// Whether to enable local cache for the playback URL. Default is true. When local cache is enabled in AliPlayerGlobalSettings and also enabled here (set to true), the local cache for this URL takes effect. If set to false here, 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 AliPlayerGlobalSettings as follows.

[AliPlayerGlobalSettings enableLocalCache:true];

Preloading

The ApsaraVideo Player SDK for iOS provides preloading, an upgrade to local caching that improves startup speed by downloading part of a video into the cache before playback begins.

Preloading limits:

  • Supports single media files such as MP4, MP3, FLV, and HLS.

Note

By default, the SDK schedules preload network requests to avoid interfering 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];
  1. Enable local cache as described in Local cache.

  2. 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];
  3. Set task parameters.

    Note

    This applies only to multi-bitrate videos. You can choose any one of setDefaultBandWidth, setDefaultResolution, or setDefaultQuality.

    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];
  4. Add a task listener.

    Expand to view the code

    @interface YourViewController () <OnPreloadListener>
    
    @property(nonatomic,strong) AliMediaLoaderV2* vodMedialoader; // Preloader
    @property(nonatomic,strong) AVPVidAuthSource* vidSource; // vidAuth data source
    @property(nonatomic,strong) AVPUrlSource* urlSource; // url data source
    @property(nonatomic,strong) AVPVidStsSource* vidStsSource; // vidSts data source
    
    @end
    
    @implementation YourViewController
    
    - (void)onCompleted:(NSString *)taskId urlOrVid:(NSString *)urlOrVid {
        NSLog(@"Current task (%@) completed:%@", taskId,urlOrVid);
    }
    
    - (void)onError:(NSString *)taskId urlOrVid:(NSString *)urlOrVid errorModel:(AVPErrorModel *)errorModel {
        NSLog(@"An exception occurred:%@", urlOrVid);
    }
    
    - (void)onCanceled:(NSString *)taskId urlOrVid:(NSString *)urlOrVid {
        NSLog(@"Task canceled:%@", urlOrVid);
    }
    
    @end
  5. Build the task, add it to the MediaLoaderV2 instance, 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];
  6. 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.
  7. 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.

Expand to view the code

// Enable recommended configuration and dynamic preloading.
[self.listPlayer setScene:AVP_SHORT_VIDEO];

// Configure the base preload duration.
// Set the preload duration to 1000 ms.
AVPPreloadConfig *config = [[AVPPreloadConfig alloc] init];
config.preloadDuration = 1000;
[self.listPlayer updatePreloadConfig:config];

// Configure the number of items to preload. Supports both directions.
// 1 is the number of items to preload backward, 3 is the number of items to preload forward.
[self.listPlayer setPreloadCount:1 nextCount:3];

// Configure the decreasing offset for dynamic preloading.
[self.listPlayer enableStrategy:AVP_STRATEGY_DYNAMIC_PRELOAD enable:true];
[self.listPlayer setStrategyParam:AVP_STRATEGY_DYNAMIC_PRELOAD strategyParam:@"{\"algorithm\": \"sub\",\"offset\": \"200\"}"];

Preload multi-bitrate HLS videos

For multi-bitrate HLS videos in listPlayer, you can preload a stream that matches the current playback definition and select a preload mode.

Expand to view supported preload modes

typedef enum AVPMultiBitratesMode : NSUInteger {
    /**
     * Default configuration. Play and preload the default bitrate.
     */
    /****
     * default mode, play and preload default bitrate of a stream
     */
    AVPMultiBitratesMode_Default = 0,
    /**
     * First frame priority configuration. The video starts playing at the bitrate that has finished preloading.
     */
    /****
     * First frame cost (FC) priority, decrease first frame cost. only play bitrate of the hls stream which has been preloaded.
     */
    AVPMultiBitratesMode_FCPrio = 1,
    /**
     * Balances first frame and smooth playback. The video bitrate is consistent before and after switching (moveToNext), and first frame performance is also considered.
     */
    /****
     * First frame and play smooth, play the same bitrate before and after moveToNext
     */
    AVPMultiBitratesMode_FC_AND_SMOOTH = 2,
    /**
     * Smooth playback priority configuration. The video starts playing at the bitrate of the previous video.
     */
    /****
     * Play Smooth priority, play the same bitrate before and after moveToNext.
     */
    AVPMultiBitratesMode_SmoothPrio = 3,
} AVPMultiBitratesMode;

Expand to view the integration code

// Select multi-bitrate loading mode.
[self.listPlayer->SetMultiBitratesMode(preLoadMode)];

// (Optional) Select the startup bitrate.
[self.listPlayer setDefaultBandWidth:defaultBandWidth];

// (Optional) In the preparedone callback, select the ABR mode.
-(void)onPlayerEvent:(AliPlayer*)player eventType:(AVPEventType)eventType {
    switch (eventType) {
        case AVPEventPrepareDone: {
            [self.listPlayer selectTrack:-1];
        }
            break;
        case AVPEventFirstRenderedStart: {
        }
            break;
        default:
            break;
    }
}

Get the download speed

Retrieve 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

The HTTPDNS feature uses DNS resolution technology to send domain name resolution requests to a specific HTTPDNS server and obtain resolution results quickly and stably. This prevents DNS hijacking.

ApsaraVideo Player SDK provides HTTPDNS services for domain names accelerated by Alibaba Cloud CDN. You can use the enhanced HTTPDNS feature to implement precise scheduling and ensure that real-time domain resolution results immediately take effect. This improves network performance.

Enhanced HTTPDNS usage example

You can use the enhanced HTTPDNS feature only for accelerated domain names. Before you use the feature, make sure that an accelerated domain name is added and configured. For more information about how to add and configure a domain name for CDN in ApsaraVideo VOD, see Add an accelerated domain name. For more information about accelerated domain names, see What is Alibaba Cloud CDN?.

// Enable enhanced HTTPDNS.
[AliPlayerGlobalSettings enableEnhancedHttpDns:YES];
// Optional. Add a domain for HTTPDNS pre-resolution.
[[AliDomainProcessor shareInstance] addPreResolveDomain:@"player.***alicdn.com"];

HTTP/2

Note

The ApsaraVideo Player SDK for iOS enables HTTP/2 by default starting from V5.5.0.0.

The ApsaraVideo Player SDK for iOS supports HTTP/2. This protocol uses multiplexing to avoid head-of-line blocking and improve playback performance.

[AliPlayerGlobalSettings setUseHttp2:true];

HTTP pre-established TCP connections

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 domains 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

Note

For detailed code examples, see the Download module in the API-Example project. This project is based on Objective-C and demonstrates core SDK integration for the ApsaraVideo Player SDK for iOS.

The ApsaraVideo Player SDK for iOS 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

  • This feature is only for VidSts and VidAuth sources.

  • Enable and configure the download mode in the ApsaraVideo VOD console. For more information, see Offline download.

  • You can resume video downloads from a breakpoint.

Procedure

  1. Optional: Configure the encryption verification file for secure download. Configure this file only for secure download. Standard download does not require it.

    Note

    Ensure the encryption verification file matches your 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.

    You need to configure this only once in the application. The following is an example:

    NSString *encrptyFilePath = [[NSBundle mainBundle] pathForResource:@"encryptedApp" ofType:@"dat"];
    [AliPrivateService initKey:encrptyFilePath];
  2. Create and set up the downloader.

    Example:

    AliMediaDownloader *downloader = [[AliMediaDownloader alloc] init];
    [downloader setSaveDirectory:self.downLoadPath];
    [downloader setDelegate:self];
  3. Set event listeners.

    The download object 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.
    }
  4. Prepare the download source.

    Call the prepare method to prepare a download source. Supported source types include VidStsSource and VidAuthSource. Examples follow:

    • 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];
    Note

    If 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.

  5. Select a download item.

    After preparation succeeds, the onPrepared method is called. The returned TrackInfo includes information such as the definition of each video stream. Select a track to download. The following is 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];
    }
  6. 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];
  7. After the download succeeds or fails, release the downloader.

    After the download succeeds, invoke destroy to release the downloader.

    [self.downloader destroy];
    self.downloader = nil;

Encrypted playback

ApsaraVideo VOD supports HLS standard encryption, Alibaba Cloud proprietary encryption, and 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-based stream pulling on iOS.

References