This topic describes how to use the basic features of the ApsaraVideo Player SDK for iOS. You will learn how to configure playback sources, adjust volume and playback speed, switch resolutions and audio tracks, and more.
To run and test the demo, download ApsaraVideo Player SDK and follow the instructions to compile and run it.
Configure a video source
The ApsaraVideo Player SDK for iOS supports both video-on-demand (VOD) and live streaming playback.
VOD playback methods: VidAuth (recommended for ApsaraVideo VOD users), VidSts, UrlSource, and encrypted playback.
Live stream playback methods: UrlSource and encrypted playback.
UrlSource plays media from a URL. VidSts and VidAuth play media by media ID (Vid).
For information about supported regions, see ApsaraVideo VOD region IDs.
VOD playback
VidAuth (Recommended)
To play a VOD video by using VidAuth, set the vid property to the media ID and the playAuth property to the playback credential.
Media ID: You can obtain the media ID after you upload a media file. In the ApsaraVideo VOD console, choose Media Files > Audio/Video. You can also call the SearchMedia API.
Playback credential: Call the GetVideoPlayAuth operation to obtain the playback credential. We recommend that you integrate the ApsaraVideo VOD server-side SDK to avoid manual signature generation. For examples, see OpenAPI Explorer.
We recommend VidAuth over VidSts for ApsaraVideo VOD users because VidAuth provides better usability and security. For more information, see Credential method vs. STS method.
If you enable HLS encryption parameter pass-through in the ApsaraVideo VOD console, the default parameter name is MtsHlsUriToken. For more information, see Parameter pass-through for HLS encryption.
AVPVidAuthSource *authSource = [[AVPVidAuthSource alloc] init];
authSource.vid = @"Vid"; // Required. The video ID (VideoId).
authSource.playAuth = @"<yourPlayAuth>"; // Required. The playback credential from GetVideoPlayAuth.
authSource.region = @"regionID"; // Deprecated for SDK V5.5.5.0 and later. The player automatically parses the region. For earlier versions, this parameter is required. Default: cn-shanghai.
// authSource.authTimeout = 3600; // Optional. Set the validity period of the playback URL in seconds. This value overwrites the validity period configured in the ApsaraVideo VOD console. Default: 3600. Make sure that the value is greater than the video duration to prevent URL expiration during playback.
// If you enable HLS encryption parameter pass-through in the ApsaraVideo VOD console and the default parameter is MtsHlsUriToken, configure it as follows:
VidPlayerConfigGenerator* vp = [[VidPlayerConfigGenerator alloc] init];
[vp setHlsUriToken:yourMtsHlsUriToken];
authSource.playConfig = [vp generatePlayerConfig];
[self.player setAuthSource:authSource];VidSts
VidSts playback uses temporary STS credentials instead of VOD playback credentials. Before you play VOD videos by using VidSts, obtain an STS token and an AccessKey pair (AccessKey ID and AccessKey secret). For more information, see Obtain an STS token.
If you enable HLS encryption parameter pass-through in the ApsaraVideo VOD console, the default parameter name is MtsHlsUriToken. For more information, see Parameter pass-through for HLS encryption.
AVPVidStsSource *source = [[AVPVidStsSource alloc] init];
source.vid = @"Vid"; // Required. The video ID (VideoId).
source.region = @"regionID"; // Required. The ApsaraVideo VOD region. Default: cn-shanghai.
source.securityToken = @"<yourSecurityToken>"; // Required. The STS token from AssumeRole.
source.accessKeySecret = @"<yourAccessKeySecret>"; // Required. The temporary AccessKey secret from STS (AssumeRole).
source.accessKeyId = @"<yourAccessKeyId>"; // Required. The temporary AccessKey ID from STS (AssumeRole).
// source.authTimeout = 3600; // Optional. Set the validity period of the playback URL in seconds. This value overwrites the validity period configured in the ApsaraVideo VOD console. Default: 3600. Make sure that the value is greater than the video duration to prevent URL expiration during playback.
// If you enable HLS encryption parameter pass-through in the ApsaraVideo VOD console and the default parameter is MtsHlsUriToken, configure it as follows:
VidPlayerConfigGenerator* vp = [[VidPlayerConfigGenerator alloc] init];
[vp setHlsUriToken:yourMtsHlsUriToken];
source.playConfig = [vp generatePlayerConfig];
// Set the playback source.
[self.player setStsSource:source]UrlSource
To play a VOD video by using UrlSource, pass the playback URL directly.
You can call the GetPlayInfo operation to obtain playback URLs from ApsaraVideo VOD. We recommend that you integrate the ApsaraVideo VOD server-side SDK. For examples, see OpenAPI Explorer.
For local files, make sure that you have permission to access the file. Use full paths such as
/sdcard/video/sample.mp4orcontent://media/video/123.
AVPUrlSource *urlSource = [[AVPUrlSource alloc] urlWithString:url]; // Required. A VOD URL, third-party URL, or local file path.
[self.player setUrlSource:urlSource]; Encrypted playback
VOD videos support HLS encryption, Alibaba Cloud video encryption, and DRM encryption. For playback, see Play an encrypted video.
Live stream playback
For live stream playback, see Standard live stream playback.
Control playback
The ApsaraVideo Player SDK for Android provides methods to start, pause, stop, and seek playback.
Prepare for playback
Call the prepare method to prepare the video for playback.
[self.player prepare];The onPlayerEvent callback with AVPEventPrepareDone is invoked when preparation is complete.
Start playback
Call the start method to begin playing the video:
[self.player start];Pause playback
Call the pause method to pause the video:
[self.player pause];Resume playback
Call the start method to resume playback after pausing:
[self.player start];Seek to a specific position
Call seekToTime to jump to a specific position. This method is useful when users drag the progress bar or resume playback from a saved position.
// Seek to a specific position (in milliseconds)
// Accurate seek
[self.player seekToTime:position seekMode:AVP_SEEKMODE_ACCURATE];
// Inaccurate seek
[self.player seekToTime:position seekMode:AVP_SEEKMODE_INACCURATE];Seek modes:
Accurate seek (
AVP_SEEKMODE_ACCURATE): Seeks to the exact position. Slower but more precise.Inaccurate seek (
AVP_SEEKMODE_INACCURATE): Seeks to the nearest keyframe. Faster but less precise.
Start playback from a specific position
To start playback from a specific position (rather than seeking during playback), call setStartTime before calling prepare:
// Set the start time for the next prepare call (in milliseconds).
// This setting is only valid for the immediately following prepare call. The start time is automatically cleared after prepare is called.
// seekMode: accurate seek (AVP_SEEKMODE_ACCURATE) or inaccurate seek (AVP_SEEKMODE_INACCURATE).
[self.player setStartTime:time seekMode:seekMode];Stop playback
Call the stop method to stop playback:
[self.player stop];Destroy the player
You can destroy the player synchronously or asynchronously to release resources.
// Synchronous destroy. Blocks until player resources are released. Automatically calls stop.
[self.player destroy];
// Asynchronous destroy. Returns immediately. Automatically calls stop.
[self.player destroyAsync];Recommendations:
Use
destroyAsyncif you need fast UI response times.Do not perform any operations on the player object during asynchronous destruction.
You do not need to call
stopbeforedestroyAsyncbecause the destruction process includes an asynchronous stop operation.
Listen for player events
The ApsaraVideo Player SDK provides delegate callbacks to monitor player state changes, playback progress, errors, and other events.
Set the player delegate
Implement the AVPDelegate protocol in your view controller to receive player callbacks.
Important: Implement the onError and onPlayerEvent callbacks to handle errors and monitor playback state changes.
@interface SimplePlayerViewController ()<AVPDelegate>
@end
- (void)viewDidLoad {
self.player = [[AliPlayer alloc] init];
self.player.playerView = self.avpPlayerView.playerView;
self.player.delegate = self;
//...
}
/**
@brief Delegate callback for player errors.
@param player The player instance.
@param errorModel Contains the error details.
*/
- (void)onError:(AliPlayer*)player errorModel:(AVPErrorModel *)errorModel {
// Handle the error (e.g., show an alert) and stop playback.
}
/**
@brief Delegate callback for player events.
@param player The player instance.
@param eventType The type of the event. See AVPEventType.
*/
-(void)onPlayerEvent:(AliPlayer*)player eventType:(AVPEventType)eventType{
switch(eventType){
case AVPEventPrepareDone:{
// Triggered when the media has been prepared and is ready to play.
}
break;
case AVPEventAutoPlayStart:
// Triggered when autoplay begins.
break;
case AVPEventFirstRenderedStart:
// Triggered when the first frame is rendered.
break;
case AVPEventCompletion:
// Triggered when playback completes.
break;
case AVPEventLoadingStart:
// Triggered when buffering starts.
break;
case AVPEventLoadingEnd:
// Triggered when buffering finishes.
break;
case AVPEventSeekEnd:
// Triggered when a seek operation completes.
break;
case AVPEventLoopingStart:
// Triggered when a new loop begins.
break;
default:
break;
}
}
/**
@brief Callback for the current playback position.
@param player The player instance.
@param position The current playback position in milliseconds.
*/
- (void)onCurrentPositionUpdate:(AliPlayer*)player position:(int64_t)position {
// Update the progress bar.
}
/**
@brief Callback for the current buffered position.
@param player The player instance.
@param position The current buffered position in milliseconds.
*/
- (void)onBufferedPositionUpdate:(AliPlayer*)player position:(int64_t)position {
// Update the buffer progress indicator.
}
/**
@brief Callback for when track information is ready.
@param player The player instance.
@param info An array of AVPTrackInfo objects for the available streams.
*/
- (void)onTrackReady:(AliPlayer*)player info:(NSArray<AVPTrackInfo*>*)info {
// Retrieve information for available bitrates/tracks.
}
/**
@brief Callback for when a subtitle should be displayed.
@param player The player instance.
@param index The index of the subtitle entry.
@param subtitle The subtitle text to be displayed.
*/
- (void)onSubtitleShow:(AliPlayer*)player index:(int)index subtitle:(NSString *)subtitle {
// Get and display the subtitle text.
}
/**
@brief Callback for when a subtitle should be hidden.
@param player The player instance.
@param index The index of the subtitle entry that was shown.
*/
- (void)onSubtitleHide:(AliPlayer*)player index:(int)index {
// Hide the subtitle.
}
/**
@brief Callback for a screen capture request.
@param player The player instance.
@param image The captured screenshot as a UIImage.
*/
- (void)onCaptureScreen:(AliPlayer *)player image:(UIImage *)image {
// Preview or save the captured image.
}
/**
@brief Callback for when a track change is complete.
@param player The player instance.
@param info The AVPTrackInfo object for the new, active track.
*/
- (void)onTrackChanged:(AliPlayer*)player info:(AVPTrackInfo*)info {
// Notification that the bitrate/track has changed.
}Listen for player state changes
The onPlayerStatusChanged callback is invoked when the player state changes:
- (void)onPlayerStatusChanged:(AliPlayer*)player oldStatus:(AVPStatus)oldStatus newStatus:(AVPStatus)newStatus {
switch (newStatus) {
case AVPStatusIdle:{
// Player is idle
}
break;
case AVPStatusInitialzed:{
// Player is initialized
}
break;
case AVPStatusPrepared:{
// Player prepared
}
break;
case AVPStatusStarted:{
// Playback started
}
break;
case AVPStatusPaused:{
// Playback paused
}
break;
case AVPStatusStopped:{
// Playback stopped
}
break;
case AVPStatusCompletion:{
// Playback completed
}
break;
case AVPStatusError:{
// Player error occurred
}
break;
default:
break;
}
}Configure video display
Configure how the video is scaled, rotated, and mirrored during playback.
Scaling modes
The SDK supports three scaling modes:
// Scale to fit the view while maintaining the aspect ratio (letterboxing).
self.player.scalingMode = AVP_SCALINGMODE_SCALEASPECTFIT;
// Scale to fill the view while maintaining the aspect ratio (cropping).
self.player.scalingMode = AVP_SCALINGMODE_SCALEASPECTFILL;
// Stretch to fill the view. The aspect ratio is not maintained. Image distortion may occur.
self.player.scalingMode = AVP_SCALINGMODE_SCALETOFILL;Scaling mode settings do not apply to Picture-in-Picture (PiP) mode.
Rotation
Rotate the video clockwise by a specified angle:
// No rotation
self.player.rotateMode = AVP_ROTATE_0;
// Rotate 90 degrees clockwise
self.player.rotateMode = AVP_ROTATE_90;
// Rotate 180 degrees clockwise
self.player.rotateMode = AVP_ROTATE_180;
// Rotate 270 degrees clockwise
self.player.rotateMode = AVP_ROTATE_270;Mirroring
Call setMirrorMode to mirror the video. The SDK supports horizontal and vertical mirroring:
// No mirroring
self.player.mirrorMode = AVP_MIRRORMODE_NONE;
// Horizontal mirroring
self.player.mirrorMode = AVP_MIRRORMODE_HORIZONTAL;
// Vertical mirroring
self.player.mirrorMode = AVP_MIRRORMODE_VERTICAL;Obtain playback information
You can obtain the playback progress, duration, and buffering progress during playback.
Playback progress
The current playback position is returned in the onCurrentPositionUpdate callback:
- (void)onCurrentPositionUpdate:(AliPlayer*)player position:(int64_t)position {
// position is in milliseconds
NSString *position = [NSString stringWithFormat:@"%lld, position"];
}Total duration
Retrieve the total duration of the video after it has been loaded (e.g., after the AVPEventPrepareDone event):
-(void)onPlayerEvent:(AliPlayer*)player eventType:(AVPEventType)eventType {
switch (eventType) {
case AVPEventPrepareDone: {
if (self.player.duration >= 0) {
NSString *duration = self.player.duration;
}
}
break;
default:
break;
}
}Actual playback duration
Retrieve the actual playback duration in real time. This value excludes the time when playback is paused or buffering.
NSString *duration = [player getPlayedDuration];Buffering progress
The current buffering progress is returned in the onBufferedPositionUpdate callback:
- (void)onBufferedPositionUpdate:(AliPlayer*)player position:(int64_t)position {
NSString *bufferPosition = position;
}Real-time rendering and bitrate metrics
Obtain the rendering frame rate, audio and video bitrate, and network downstream bitrate in real time.
// Video rendering frame rate. Returns a float value.
[self.player getOption:AVP_OPTION_RENDER_FPS]
// Video bitrate. Returns a float value in bit/s.
[self.player getOption:AVP_OPTION_VIDEO_BITRATE]
// Audio bitrate. Returns a float value in bit/s.
[self.player getOption:AVP_OPTION_AUDIO_BITRATE]
// Network downstream bitrate. Returns a float value in bit/s.
[self.player getOption:AVP_OPTION_DOWNLOAD_BITRATE]Manage volume
Control the playback volume and mute the audio.
Adjust the volume
Call volume to change the volume. Valid values range from 0 to 2, where 1 is the original volume. Values greater than 1 amplify the audio and may introduce noise. We recommend that you do not set the volume to a value greater than 1.
// Set the volume. Valid values: 0 to 2.
self.player.volume = 1.0f;
// Get the current volume.
self.player.volumeMute the video
Mute or unmute the audio:
self.player.muted = YES;Set the playback speed
Adjust the playback speed from 0.5× to 5× the normal speed without changing the pitch:
// We recommend using multiples of 0.5 (e.g., 0.5, 1.0, 1.5, 2.0)
self.player.rate = 1.0f;Switch resolutions
For detailed code examples, see the MultiResolution module in the API-Example project.
VidAuth or VidSts-based playback
If you use VidAuth or VidSts for VOD playback, the SDK automatically retrieves video definitions from ApsaraVideo VOD. No additional configuration is required.
Query available definitions
After the video is loaded, retrieve the available definitions (trackBitrate) in the onTrackReady callback:
- (void)onTrackReady:(AliPlayer*)player info:(NSArray<AVPTrackInfo*>*)info {
for (int i=0; i<info.count; i++) {
AVPTrackInfo* track = [info objectAtIndex:i];
switch (track.trackType) {
case AVPTRACK_TYPE_VIDEO: {
int trackBitrate = track.trackBitrate;
}
break;
}
}
}Switch the definition
Call the selectTrack method with the index of the desired track:
[self.player selectTrack:index];Listen for definition switching events
The onTrackChanged callback is invoked after the definition is switched:
- (void)onTrackChanged:(AliPlayer*)player info:(AVPTrackInfo*)info {
// Definition switched.
}Enable quick switching
Enable quick switching mode to receive faster responses when manually switching definitions:
AVPConfig *config = [self.player getConfig];
config.selectTrackBufferMode = 1;
[self.player setConfig:config];UrlSource-based live streaming
For details, see Standard live stream playback.
Enable loop playback
Enable loop playback to automatically restart the video from the beginning when playback is complete:
self.player.loop = YES;The AVPEventLoopingStart event is triggered at the start of each loop:
- (void)onPlayerEvent:(AliPlayer*)player eventType:(AVPEventType)eventType {
switch (eventType) {
case AVPEventLoopingStart:
break;
}
}Switch audio tracks
The ApsaraVideo Player SDK for iOS supports audio track switching, which lets you switch between audio tracks in different languages during playback.
Supported stream types
You can switch audio tracks in the following stream types. The switching behavior varies based on the stream type.
Stream type | Extension | Bitrate count | Substream type | Switching behavior |
Non-list stream (MP4) | .mp4 | 1 | One video track, multiple audio and subtitle tracks | You can switch between audio tracks. |
Single-bitrate mixed HLS | .m3u8 | 1 | One video track, multiple audio and subtitle tracks | You can switch between audio tracks. |
Single-bitrate HLS | .m3u8 | 1 | Separate video, audio, and caption substreams | You can switch between audio tracks. |
Multi-bitrate mixed HLS | .m3u8 | n | Substreams with different bitrates, each with one video and multiple audio tracks | You can switch between substreams only, not audio tracks within a substream. |
Get available audio tracks
The onSubTrackReady callback is invoked when audio track information is available:
// onSubTrackReady. Typically triggered before the AVPEventPrepareDone event.
- (void)onSubTrackReady:(AliPlayer*)player info:(NSArray<AVPTrackInfo*>*)info {
// Call getSubMediaInfo after this callback is triggered. Calling it before this callback returns an empty result.
AVPMediaInfo* subMediaInfo = [player getSubMediaInfo];
// Iterate through available audio tracks
for (int i=0; i<subMediaInfo.tracks.count; i++) {
AVPTrackInfo* track = [mediaInfo.tracks objectAtIndex:i];
// Find the target audio track from the track list.
}
}Switch the audio track
Call the selectTrack method to switch to a different audio track:
[self.player selectTrack:myTrack.trackIndex accurate:YES]Use thumbnails
For detailed code examples, see the Thumbnail module in the API-Example project.
Video thumbnails (sprite sheets) allow users to preview video content when scrubbing through the timeline.
Before you use thumbnails, configure sprite snapshots for your video. In the ApsaraVideo VOD console, create a snapshot template with Image Sprite as the snapshot type, and then create a workflow to process the video. For more information, see Video snapshots.
/**
A flag indicating whether the current track has thumbnails. If false, thumbnail previews will not be displayed during seeking.
*/
@property (nonatomic,assign)BOOL trackHasThumbnai;
/**
The custom UIImageView used to display the thumbnail preview image.
*/
@property (nonatomic,strong)UIImageView *thumbnaiView;
/**
onPrepare
*/
- (void)onPlayerStatusChanged:(AliPlayer*)player oldStatus:(AVPStatus)oldStatus newStatus:(AVPStatus)newStatus {
if(newStatus == AVPStatusPrepared){
[self.player setThumbnailUrl:[URL];// When the player is prepared, set the thumbnail URL.
self.trackHasThumbnai = YES;
}
}
/**
Callback triggered when the progress slider's value changes.
@param playerView The player view instance.
@param value The new progress value.
*/
- (void)AVPPlayerView:(AVPPlayerView *)playerView progressSliderValueChanged:(CGFloat)value {
if (self.trackHasThumbnai) {
[self.player getThumbnail:self.player.duration*value];
}
}
/**
@brief: Callback triggered upon successful retrieval of a thumbnail.
@param positionMs: The requested time position for the thumbnail, in milliseconds.
@param fromPos: The start time of the segment this thumbnail represents, in milliseconds.
@param toPos: The end time of the segment this thumbnail represents, in milliseconds.
@param image: The retrieved thumbnail image (`UIImage` on iOS, `NSImage` on macOS).
*/
- (void)onGetThumbnailSuc:(int64_t)positionMs fromPos:(int64_t)fromPos toPos:(int64_t)toPos image:(id)image {
self.thumbnaiView.hidden = NO;
[self.thumbnaiView setImage:(UIImage *)image];
}
/**
@brief: Callback triggered when thumbnail retrieval fails.
@param positionMs: The time position for which the thumbnail request failed, in milliseconds.
*/
- (void)onGetThumbnailFailed:(int64_t)positionMs {
self.thumbnaiView.hidden = YES;
}Get SDK logs
SDK logs contain detailed information such as request status, invocation results, and permission requests. You can use these logs to debug issues during development. The SDK provides two methods to obtain logs.
Method 1: View logs in the development tool console
This method is suitable for scenarios where you can reproduce the issue locally.
Enable logging and set the log level:
// Enable SDK logging [AliPlayer setEnableLog:YES]; // Set the log level (default: LOG_LEVEL_INFO). Use LOG_LEVEL_TRACE for detailed troubleshooting. [AliPlayer setLogCallbackInfo:LOG_LEVEL_INFO callbackBlock:nil];Enable frame-level logging (optional):
// Enable frame-level logging for detailed troubleshooting // 0 = disabled, 1 = enabled [AliPlayer setLogOption:FRAME_LEVEL_LOGGING_ENABLED value:value];NoteFrame-level logging generates a large volume of logs and is primarily used for troubleshooting playback issues.
Collect logs:
Option A: View logs in the console
After reproducing the issue, retrieve the logs from your development tool console, such as XCode.
Option B: Write logs to a file
Set the full path for your log file within the application's sandbox.
NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES); NSString *documentDirectory = [paths objectAtIndex:0]; // Define your custom log file path. For example, create a file named 'xxxx.log'. NSString *logFilePath = [documentDirectory stringByAppendingPathComponent:@"xxxx.log"];Redirect logs to a custom file in the app's sandbox:
freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding],"a+", stdout); freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding],"a+", stderr);After reproducing the issue, retrieve the
.logfile from the custom directory.
Method 2: Set LogCallback to receive logs programmatically
Use this method when you cannot reliably reproduce the issue on your device. The callback exports logs to your application's log channel.
Enable logging and set the log level.
// Enable SDK logging [AliPlayer setEnableLog:YES]; // Set the log level. Default value: LOG_LEVEL_INFO. For troubleshooting, set it to LOG_LEVEL_TRACE. [AliPlayer setLogCallbackInfo:LOG_LEVEL_INFO callbackBlock:^(AVPLogLevel logLevel, NSString *strLog) { NSLog(@"strLog:%@", strLog); }];Collect logs:
After reproducing the issue, the logs are automatically forwarded to your app's logging system.
Troubleshooting
Common issues
Issue | Possible cause | Solution |
Video does not play | Invalid playback source | Verify the video ID or URL is correct |
Black screen | Player view not set | Ensure |
Playback credential expired | Token expired | Regenerate the playback credential and retry |
Audio but no video | Unsupported codec | Check the video format and codec compatibility |
Stuttering playback | Poor network | Enable adaptive bitrate streaming or reduce quality |
References
Advanced features: Learn about advanced features such as Picture-in-Picture (PiP), time shifting, and adaptive bitrate streaming.
API reference: Explore the complete API reference for the ApsaraVideo Player SDK for iOS.
Mobile error codes: Refer to this topic for troubleshooting.