This topic describes how to create an iOS player instance and provides examples of how to use basic playback features, such as setting the volume, enabling video seeking, listening for playback states, enabling loop playback, setting the playback speed, and switching audio tracks.
To run the demo, download it, and then compile and run it. For more information, see Run the demo.
Set the playback source (DataSource)
The ApsaraVideo Player SDK for iOS supports four playback methods for video-on-demand (VOD): VidAuth (recommended for ApsaraVideo VOD users), VidSts, UrlSource, and encrypted playback.
The ApsaraVideo Player SDK for iOS supports two playback methods for live streaming: UrlSource and encrypted playback.
VOD playback
VOD playback using VidAuth (Recommended)
To play a VOD video using VidAuth, set the vid property of the player to the video ID and the playauth property to the playback credential.
Video ID: You can obtain the video ID from the ApsaraVideo VOD console (Media Library > Audio/Video) or by calling the SearchMedia API operation after the video is uploaded.
Playback credential: You can obtain the playback credential by calling the GetVideoPlayAuth API operation. We recommend that you integrate the ApsaraVideo VOD server-side SDK to obtain playback credentials. This eliminates the need to sign requests. For an example of how to call this API operation, see API Explorer.
We recommend that ApsaraVideo VOD users use this playback method. Compared to the STS method, the PlayAuth method is more secure and easier to use. For a detailed comparison, see Comparison between the credential-based method and the STS-based method.
If you enable HLS encryption parameter pass-through in the ApsaraVideo VOD console, the default parameter name is MtsHlsUriToken. For more information, see HLS encryption parameter pass-through. In this case, set the MtsHlsUriToken value in the VOD source as shown in the following code.
AVPVidAuthSource *authSource = [[AVPVidAuthSource alloc] init];
authSource.vid = @"Vid information"; // Required. The video ID (VideoId).
authSource.playAuth = @"<yourPlayAuth>"; // Required. The playback credential. You must call the GetVideoPlayAuth operation of ApsaraVideo VOD to generate the credential.
authSource.region = @"The region where ApsaraVideo VOD is activated"; // For ApsaraVideo Player SDK V5.5.5.0 and later, this parameter is deprecated. You do not need to set the region because the player automatically parses it. For versions earlier than V5.5.5.0, this parameter is required. The region where ApsaraVideo VOD is activated. Default value: cn-shanghai.
// authSource.authTimeout = 3600; // The validity period of the playback URL in seconds. This value overwrites the validity period of URL signing that you set in the ApsaraVideo VOD console. If you do not specify this parameter, the default value 3600 is used. If you set this parameter, make sure that the validity period is longer than the video duration to prevent the playback URL from expiring before the playback is complete.
// If you enable HLS encryption parameter pass-through in the ApsaraVideo VOD console and the default parameter name is MtsHlsUriToken, you must set the config and pass it to the vid. See the following code.
// If you do not enable HLS encryption parameter pass-through in the ApsaraVideo VOD console, you do not need to integrate the following code.
VidPlayerConfigGenerator* vp = [[VidPlayerConfigGenerator alloc] init];
[vp setHlsUriToken:yourMtsHlsUriToken];
authSource.playConfig = [vp generatePlayerConfig];
[self.player setAuthSource:authSource];VOD playback using VidSts
To play a VOD video using VidSts, you must use a temporary Security Token Service (STS) credential instead of an ApsaraVideo VOD playback credential. You must obtain an STS token and a temporary AccessKey pair (AccessKeyId and AccessKeySecret) in advance. 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 HLS encryption parameter pass-through. In this case, set the MtsHlsUriToken value in the VOD source as shown in the following code.
AVPVidStsSource *source = [[AVPVidStsSource alloc] init];
source.vid = @"Vid information"; // Required. The video ID (VideoId).
source.region = @"The region where ApsaraVideo VOD is activated"; // Required. The region where ApsaraVideo VOD is activated. Default value: cn-shanghai.
source.securityToken = @"<yourSecurityToken>"; // Required. The STS token. You must call the AssumeRole operation of STS to generate the token.
source.accessKeySecret = @"<yourAccessKeySecret>"; // Required. The AccessKey secret of the temporary AccessKey pair. You must call the AssumeRole operation of STS to generate the secret.
source.accessKeyId = @"<yourAccessKeyId>"; // Required. The AccessKey ID of the temporary AccessKey pair. You must call the AssumeRole operation of STS to generate the ID.
// source.authTimeout = 3600; // The validity period of the playback URL in seconds. This value overwrites the validity period of URL signing that you set in the ApsaraVideo VOD console. If you do not specify this parameter, the default value 3600 is used. If you set this parameter, make sure that the validity period is longer than the video duration to prevent the playback URL from expiring before the playback is complete.
// If you enable HLS encryption parameter pass-through in the ApsaraVideo VOD console and the default parameter name is MtsHlsUriToken, you must set the config and pass it to the vid. See the following code.
// If you do not enable HLS encryption parameter pass-through in the ApsaraVideo VOD console, you do not need to integrate the following code.
VidPlayerConfigGenerator* vp = [[VidPlayerConfigGenerator alloc] init];
[vp setHlsUriToken:yourMtsHlsUriToken];
source.playConfig = [vp generatePlayerConfig];
// Set the playback source.
[self.player setStsSource:source]VOD playback using UrlSource
To play a VOD video using UrlSource, set the source property of the player to the playback URL.
Playback URL in ApsaraVideo VOD: You can call the GetPlayInfo API operation to obtain the URL. We recommend that you integrate the ApsaraVideo VOD server-side SDK to obtain playback URLs. This eliminates the need to sign requests. For an example of how to call this API operation, see API Explorer.
Local video URL: Ensure that you have the required access permissions. You can call a system API to retrieve the full path of an accessible local video file, such as
/sdcard/xxx/xxx/xxx.mp4orcontent://xxx/xxx/xx.mp4.
AVPUrlSource *urlSource = [[AVPUrlSource alloc] urlWithString:url]; // Required. The playback URL. The URL can be a third-party VOD URL, a playback URL in ApsaraVideo VOD, or a local video URL.
[self.player setUrlSource:urlSource]; Encrypted VOD playback
VOD supports HLS encryption, Alibaba Cloud proprietary cryptography, and DRM encryption. For more information about encrypted playback, see Play encrypted videos on iOS.
Live stream playback
For more information, see Standard live stream playback.
UrlSource uses a URL for playback. VidSts and VidAuth use a video ID (VID) for playback.
For information about how to set the region, see VOD regions.
Control playback
The ApsaraVideo Player SDK for iOS supports common operations such as starting, pausing, and seeking.
Prepare for playback
Call the prepare interface to prepare for video playback. The following code provides an example:
[self.player prepare];Start playback
Call the start interface to start video playback. The following code provides an example:
[self.player start];Start playback from a specific time
Call the seekToTime interface to start playback from a specific time. This is suitable for scenarios where a user drags the progress bar or resumes playback from a specific time. The following code provides an example:
// The position parameter specifies the time. Unit: milliseconds. The seekMode parameter can be set to accurate or inaccurate mode.
// Accurate seek
[self.player seekToTime:position seekMode:AVP_SEEKMODE_ACCURATE];
// Inaccurate seek
[self.player seekToTime:position seekMode:AVP_SEEKMODE_INACCURATE];Start playback from a specific position. This is suitable for scenarios where a user starts playback from a specific time. For this to take effect, call this interface once before each prepare call. The following code provides an example:
// Set the start time in milliseconds for the next prepare call of the player. This setting is valid only for the immediately following prepare call.
// After prepare is called, this value is automatically cleared. If this method is not called again before the next prepare call, playback starts in the normal way.
// The seekMode can be set to accurate or inaccurate mode.
[self.player setStartTime:time seekMode:seekMode];Pause playback
Call the pause interface to pause video playback. The following code provides an example:
[self.player pause];Resume playback
Call the start interface to resume video playback. The following code provides an example:
[self.player start];Stop playback
Call the stop interface to stop video playback. The following code provides an example:
[self.player stop];Destroy the player
You can destroy a player instance synchronously or asynchronously. The following code provides an example:
// Synchronous destruction. The stop interface is automatically called internally.
[self.player destroy];
// Asynchronous destruction. The stop interface is automatically called internally.
[self.player destroyAsync];The synchronous destruction interface returns a response only after all player resources are released. If high interface response speed is required, we recommend that you use the asynchronous destruction interface. Note the following points:
Do not perform any other operations on the player object during asynchronous destruction.
You do not need to manually stop the player before calling the asynchronous destruction interface because the destruction process includes an asynchronous stop procedure.
Listen for player states
The ApsaraVideo Player SDK for iOS lets you set a player listener and listen for playback states.
Set a player listener
The player supports multiple listeners.
The
onPlayerEventandonErrorcallbacks are important. We recommend that you set them.
@interface SimplePlayerViewController ()<AVPDelegate>
@end
- (void)viewDidLoad {
self.player = [[AliPlayer alloc] init];
self.player.playerView = self.avpPlayerView.playerView;
self.player.delegate = self;
//...
}
/**
@brief Callback for errors.
@param player The player pointer.
@param errorModel The error description. For more information, see AliVcPlayerErrorModel.
*/
- (void)onError:(AliPlayer*)player errorModel:(AVPErrorModel *)errorModel {
// Reports an error and stops the playback.
}
/**
@brief Callback for player events.
@param player The player pointer.
@param eventType The event type. For more information, see AVPEventType.
*/
-(void)onPlayerEvent:(AliPlayer*)player eventType:(AVPEventType)eventType{
switch(eventType){
case AVPEventPrepareDone:{
// The player is prepared.
}
break;
case AVPEventAutoPlayStart:
// The autoplay starts.
break;
case AVPEventFirstRenderedStart:
// The first frame is rendered.
break;
case AVPEventCompletion:
// The 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 {
// Updates the progress bar.
}
/**
@brief Callback for the buffered position.
@param player The player pointer.
@param position The current buffered position.
*/
- (void)onBufferedPositionUpdate:(AliPlayer*)player position:(int64_t)position {
// Updates the buffering progress.
}
/**
@brief Callback for track information.
@param player The player pointer.
@param info An array of track information. For more information, see AVPTrackInfo.
*/
- (void)onTrackReady:(AliPlayer*)player info:(NSArray<AVPTrackInfo*>*)info {
// Obtains information about multiple bitrates.
}
/**
@brief Callback for displaying captions.
@param player The player pointer.
@param index The index of the displayed caption.
@param subtitle The string of the displayed caption.
*/
- (void)onSubtitleShow:(AliPlayer*)player index:(int)index subtitle:(NSString *)subtitle {
// Obtains and displays the captions.
}
/**
@brief Callback for hiding captions.
@param player The player pointer.
@param index The index of the displayed caption.
*/
- (void)onSubtitleHide:(AliPlayer*)player index:(int)index {
// Hides the captions.
}
/**
@brief Callback for snapshots.
@param player The player pointer.
@param image The image.
*/
- (void)onCaptureScreen:(AliPlayer *)player image:(UIImage *)image {
// Previews and saves the snapshot.
}
/**
@brief Callback for track switching completion.
@param player The player pointer.
@param info The information after switching. For more information, see AVPTrackInfo.
*/
- (void)onTrackChanged:(AliPlayer*)player info:(AVPTrackInfo*)info {
// Notification for the result of bitrate switching.
}Listen for playback states
You can listen for the state of the player. The onPlayerStatusChanged callback provides the current state of the player. The following code provides an example:
- (void)onPlayerStatusChanged:(AliPlayer*)player oldStatus:(AVPStatus)oldStatus newStatus:(AVPStatus)newStatus {
switch (newStatus) {
case AVPStatusIdle:{
// Idle.
}
break;
case AVPStatusInitialzed:{
// Initialized.
}
break;
case AVPStatusPrepared:{
// Prepared.
}
break;
case AVPStatusStarted:{
// Playing.
}
break;
case AVPStatusPaused:{
// Paused.
}
break;
case AVPStatusStopped:{
// Stopped.
}
break;
case AVPStatusCompletion:{
// Playback is complete.
}
break;
case AVPStatusError:{
// Error.
}
break;
default:
break;
}
}Set the display mode
The ApsaraVideo Player SDK for iOS supports display settings such as fill, rotate, and mirror.
Fill
You can set one of the following three fill modes: aspect fit, aspect fill, and stretch to fill. Call the scalingMode interface to set the fill mode. The following code provides an example:
// Sets the aspect ratio to fit. The video is scaled down to fit within the view without distortion.
self.player.scalingMode = AVP_SCALINGMODE_SCALEASPECTFIT;
// Sets the aspect ratio to fill. The video is scaled up to fill the view without distortion.
self.player.scalingMode = AVP_SCALINGMODE_SCALEASPECTFILL;
// Sets the mode to stretch and fill. If the aspect ratio of the video is different from that of the view, the video may be distorted.
self.player.scalingMode = AVP_SCALINGMODE_SCALETOFILL;The fill mode setting does not take effect for Picture-in-Picture (PiP).
Rotate
Call the rotateMode interface to rotate the video by a specified angle. The following code provides an example:
// Rotates the video 0 degrees clockwise.
self.player.rotateMode = AVP_ROTATE_0;
// Rotates the video 90 degrees clockwise.
self.player.rotateMode = AVP_ROTATE_90;
// Rotates the video 180 degrees clockwise.
self.player.rotateMode = AVP_ROTATE_180;
// Rotates the video 270 degrees clockwise.
self.player.rotateMode = AVP_ROTATE_270;Mirror
You can enable horizontal mirroring, vertical mirroring, or no mirroring. Call the mirrorMode interface to set the mirror mode. The following code provides an example:
// Disables mirroring.
self.player.mirrorMode = AVP_MIRRORMODE_NONE;
// Enables horizontal mirroring.
self.player.mirrorMode = AVP_MIRRORMODE_HORIZONTAL;
// Enables vertical mirroring.
self.player.mirrorMode = AVP_MIRRORMODE_VERTICAL;Obtain playback information
The ApsaraVideo Player SDK for iOS lets you obtain the current playback progress, playback duration, and buffering progress.
Obtain the current playback progress
You can obtain the current playback time. The position is returned in the onCurrentPositionUpdate callback. The following code provides an example:
- (void)onCurrentPositionUpdate:(AliPlayer*)player position:(int64_t)position {
// The position parameter indicates the current playback progress in milliseconds.
NSString *position = [NSString stringWithFormat:@"%lld, position"];
}Obtain the playback duration
You can obtain the total duration of the video. You can retrieve the duration only after the video is loaded, for example, after the onPrepared callback is invoked. Unit: milliseconds. The following code provides an example:
-(void)onPlayerEvent:(AliPlayer*)player eventType:(AVPEventType)eventType {
switch (eventType) {
case AVPEventPrepareDone: {
if (self.player.duration >= 0) {
NSString *duration = self.player.duration;
}
}
break;
default:
break;
}
}Obtain the actual playback duration
You can obtain the actual playback duration in real time. The retrieved duration does not include the time spent on pauses or stuttering during playback. The following code provides an example:
NSString *duration = [player getPlayedDuration];Obtain the buffering progress
You can obtain the current buffering progress of the video. The position is returned in the onBufferedPositionUpdate callback. The following code provides an example:
- (void)onBufferedPositionUpdate:(AliPlayer*)player position:(int64_t)position {
NSString *bufferPosition = position;
}Obtain the real-time rendering frame rate, audio and video bitrates, and network download bitrate
The following code provides an example:
// Obtains the current rendering frame rate. Data type: Float.
[self.player getOption:AVP_OPTION_RENDER_FPS]
// Obtains the bitrate of the video being played. Data type: Float. Unit: bps.
[self.player getOption:AVP_OPTION_VIDEO_BITRATE]
// Obtains the bitrate of the audio being played. Data type: Float. Unit: bps.
[self.player getOption:AVP_OPTION_AUDIO_BITRATE]
// Obtains the current network download bitrate. Data type: Float. Unit: bps.
[self.player getOption:AVP_OPTION_DOWNLOAD_BITRATE]Set the volume
You can adjust the volume and mute the video.
Adjust the volume
You can adjust the volume. The valid range is 0 to 2. If the volume is set to a value greater than 1, noise may occur. We recommend that you do not set the volume to a value greater than 1. Call the volume interface to adjust the volume. After you set the volume, you can also retrieve the volume information. The following code provides an example:
// The value of volume is a real number from 0 to 2.
self.player.volume = 1.0f;
// Obtains the volume information.
self.player.volumeMute the video
Call the muted interface to mute the video. The following code provides an example:
self.player.muted = YES;Set the playback speed
The ApsaraVideo Player SDK for iOS lets you set the playback speed. Using the rate method, you can play the video at a speed from 0.5× to 5× the original speed without changing the pitch. The following code provides an example:
// Sets the playback speed. You can set the playback speed to a value from 0.5 to 5. We recommend that you set the value to a multiple of 0.5, such as 0.5, 1, or 1.5.
self.player.rate = 1.0f;Configure multiple definitions
For detailed code examples, see the MultiResolution module in API-Example. This project is an Objective-C-based demo for the ApsaraVideo Player SDK for iOS. This project helps developers quickly integrate the core features of the SDK.
Live streaming with UrlSource
For more information, see Standard live stream playback.
VOD playback using Vid (VidAuth or VidSts)
If you use the Vid method (VidAuth or VidSts) for playback, no extra configuration is required. The ApsaraVideo Player SDK for iOS retrieves the definition list from ApsaraVideo VOD. The ApsaraVideo Player SDK for iOS lets you obtain and switch the definition. The UrlSource method does not support this setting.
Obtain the definition
After the video is loaded, you can retrieve the video definition. The onTrackReady listener returns the info object in the callback. You can then retrieve the trackBitrate of the definition from this object.
- (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
To switch the definition, call the selectTrack method and pass the index of the corresponding TrackInfo.
[self.player selectTrack:index];Notification for definition switching
The onTrackChanged callback is invoked after the definition is switched.
- (void)onTrackChanged:(AliPlayer*)player info:(AVPTrackInfo*)info {
// The definition is switched.
}Quick switching
After you enable quick switching mode, you receive a quick response every time you manually call selectTrack.
AVPConfig *config = [self.player getConfig];
config.selectTrackBufferMode = 1;
[self.player setConfig:config];Loop playback
The ApsaraVideo Player SDK for iOS supports loop playback. You can set the loop property to enable this feature. After playback is complete, the video automatically restarts from the beginning. For example:
self.player.loop = YES;The AVPEventLoopingStart callback is returned at the start of a loop. The following code provides an example:
- (void)onPlayerEvent:(AliPlayer*)player eventType:(AVPEventType)eventType {
switch (eventType) {
case AVPEventLoopingStart:
break;
}
}Switch audio tracks
The ApsaraVideo Player SDK for iOS provides a feature to switch audio tracks. This feature is suitable for scenarios in which users can switch the audio language when watching videos with multi-language audio.
Usage notes
You can switch audio tracks in streams that are not used for list playback such as MP4 streams, single-bitrate mixed HLS streams, audio tracks in single-bitrate HLS streams, and substreams in multi-bitrate mixed HLS streams. The following table describes different types of video streams.
Type | Video stream suffix | Bitrate quantity | M3U8 file quantity | Substream type | Description |
Non-list stream (such as MP4 stream) | .mp4 | 1 | - | A stream that contains a video track, multiple audio tracks, and multiple subtitle tracks. | You can switch between audio tracks. |
Single-bitrate mixed HLS stream | .m3u8 | 1 | 1 | A stream that contains a video track, multiple audio tracks, and multiple subtitle tracks. | You can switch between audio tracks. |
Single-bitrate HLS stream | .m3u8 | 1 | n | An M3U8 stream that contains only video tracks, audio tracks, or subtitle tracks. | You can switch between audio tracks. |
Multi-bitrate mixed HLS stream | .m3u8 | n | n | An M3U8 stream that contains a video track, multiple audio tracks, and multiple subtitle tracks. The bitrate of the substreams are different. | You can switch between different substreams. You cannot switch between the audio tracks of a substream. |
Examples
Set a callback.
// The onSubTrackReady callback usually occurs before the prepare callback. - (void)onSubTrackReady:(AliPlayer*)player info:(NSArray<AVPTrackInfo*>*)info { // Call getSubMediaInfo to obtain the MediaInfo information. You can call this method only after you receive the onSubTrackReady callback. Otherwise, the value is empty. AVPMediaInfo* subMediaInfo = [player getSubMediaInfo]; // Traverse. for (int i=0; i<subMediaInfo.tracks.count; i++) { AVPTrackInfo* track = [mediaInfo.tracks objectAtIndex:i]; // Obtains the corresponding track. } }Switch the audio track.
[self.player selectTrack:myTrack.trackIndex accurate:YES]
Use thumbnails
For detailed code examples, see the Thumbnail module in API-Example. This project is an Objective-C-based demo for the ApsaraVideo Player SDK for iOS. This project helps developers quickly integrate the core features of the SDK.
Before you use thumbnails in the ApsaraVideo Player SDK, ensure that you have configured thumbnails for the video. This means that a sprite has been generated for the video. To do this, you must create a sprite screenshot template in the ApsaraVideo VOD console and use a workflow to process the video with the template. For more information, see Video screenshots. The following code shows how to use thumbnails in the ApsaraVideo Player SDK:
/**
Specifies whether the current track has a thumbnail. If not, the thumbnail is not displayed.
*/
@property (nonatomic,assign)BOOL trackHasThumbnai;
/**
Creates a custom view to display the thumbnail.
*/
@property (nonatomic,strong)UIImageView *thumbnaiView;
/**
@brief: Callback for track information.
@param player: The player pointer.
@param info: An array of track information. For more information, see AVPTrackInfo.
*/
- (void)onTrackReady:(AliPlayer*)player info:(NSArray<AVPTrackInfo*>*)info {
AVPMediaInfo* mediaInfo = [player getMediaInfo];
if ((nil != mediaInfo.thumbnails) && (0 < [mediaInfo.thumbnails count])) {
[self.player setThumbnailUrl:[mediaInfo.thumbnails objectAtIndex:0].URL];
self.trackHasThumbnai = YES;
}else {
self.trackHasThumbnai = NO;
}
}
/**
Callback for progress bar changes.
@param playerView playerView
@param value: The progress value.
*/
- (void)AVPPlayerView:(AVPPlayerView *)playerView progressSliderValueChanged:(CGFloat)value {
if (self.trackHasThumbnai) {
[self.player getThumbnail:self.player.duration*value];
}
}
/**
@brief: Callback for successful thumbnail retrieval.
@param positionMs: The specified thumbnail position.
@param fromPos: The start position of the thumbnail.
@param toPos: The end position of the thumbnail.
@param image: The thumbnail image pointer. For macOS, it is an NSImage pointer. For iOS, it is a UIImage pointer.
*/
- (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 for failed thumbnail retrieval.
@param positionMs: The specified thumbnail position.
*/
- (void)onGetThumbnailFailed:(int64_t)positionMs {
self.thumbnaiView.hidden = YES;
}Note: If you use URL-based playback, the preceding code cannot directly display thumbnails because the onTrackReady callback does not support MediaInfo for URL-based playback. In this case, we recommend that you specify the thumbnail URL directly.
/**
Specifies whether the current track has a thumbnail. If not, the thumbnail is not displayed.
*/
@property (nonatomic,assign)BOOL trackHasThumbnai;
/**
Creates a custom view to display the thumbnail.
*/
@property (nonatomic,strong)UIImageView *thumbnaiView;
/**
onPrepare
*/
- (void)onPlayerStatusChanged:(AliPlayer*)player oldStatus:(AVPStatus)oldStatus newStatus:(AVPStatus)newStatus {
if(newStatus == AVPStatusPrepared){
[self.player setThumbnailUrl:[URL];// Generate a specific thumbnail URL based on the console API.
self.trackHasThumbnai = YES;
}
}
/**
Callback for progress bar changes.
@param playerView playerView
@param value: The progress value.
*/
- (void)AVPPlayerView:(AVPPlayerView *)playerView progressSliderValueChanged:(CGFloat)value {
if (self.trackHasThumbnai) {
[self.player getThumbnail:self.player.duration*value];
}
}
/**
@brief: Callback for successful thumbnail retrieval.
@param positionMs: The specified thumbnail position.
@param fromPos: The start position of the thumbnail.
@param toPos: The end position of the thumbnail.
@param image: The thumbnail image pointer. For macOS, it is an NSImage pointer. For iOS, it is a UIImage pointer.
*/
- (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 for failed thumbnail retrieval.
@param positionMs: The specified thumbnail position.
*/
- (void)onGetThumbnailFailed:(int64_t)positionMs {
self.thumbnaiView.hidden = YES;
}Obtain SDK logs
While the ApsaraVideo Player SDK is running, it generates detailed log information that includes the status of network requests, the results of system calls, and the status of permission requests. Developers can view these logs to debug code or troubleshoot issues and improve development efficiency.
Method 1: Obtain SDK logs from the console of the development tool
This method is suitable for scenarios in which you can reproduce the issue and capture logs on your local machine.
Enable logging and set the log level.
// Enables logging. [AliPlayer setEnableLog:YES]; // Sets the log level. Default value: LOG_LEVEL_INFO. To troubleshoot issues, set the level to LOG_LEVEL_TRACE. [AliPlayer setLogCallbackInfo:LOG_LEVEL_INFO callbackBlock:nil];Set frame-level logging.
// Sets frame-level log printing. // A value of 0 disables the feature. A value of 1 enables the feature. [AliPlayer setLogOption:FRAME_LEVEL_LOGGING_ENABLED value:value];NoteThe frame-level logging feature is mainly used for troubleshooting.
Collect logs.
Method 1: View logs in the console
After you reproduce the issue, you can retrieve the logs from the console of your development tool, such as Xcode.
Method 2: Output logs to a file in a custom path
After you enable logging, specify a custom path for the log file in the sandbox path before you create a player instance.
NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES); NSString *documentDirectory = [paths objectAtIndex:0]; // The logFilePath is an example path. You can create a custom file, such as an xxxx.log file, in the sandbox path. NSString *logFilePath = [documentDirectory stringByAppendingPathComponent:@"xxxx.log"];Inject log information into the custom file.
freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding],"a+", stdout); freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding],"a+", stderr);After you reproduce the issue, you can retrieve the generated
.logfile from the custom path.
Method 2: Listen for SDK output logs through LogCallback
This method is suitable for scenarios in which the issue occurs on the user side and you cannot reproduce it and capture logs on your local machine. You can listen for SDK output logs through LogCallback and automatically output them to your app's log channel.
Enable logging and set the log level.
// Enables logging. [AliPlayer setEnableLog:YES]; // Sets the log level. Default value: LOG_LEVEL_INFO. To troubleshoot issues, set the level to LOG_LEVEL_TRACE. [AliPlayer setLogCallbackInfo:LOG_LEVEL_INFO callbackBlock:^(AVPLogLevel logLevel, NSString *strLog) { NSLog(@"strLog:%@", strLog); }];Collect logs.
After you reproduce the issue, the logs are automatically output to your app's log file through your app's log channel.