文档

iOS播放器常见问题

更新时间:

本文介绍iOS播放器SDK在使用过程中的常见问题及解决方案。

License相关问题

报错License is invalid!!!

问题现象:使用5.4.7.1及之后版本的播放器时,出现如下报错。license

解决方法:

  • 请先确认您是否已申请License授权并在已配置License,5.4.7.1及之后版本播放器SDK需要配置License之后才能正常使用,具体操作,请参见License说明

    说明

    当您使用组件化、多工程维护的代码工程,且已根据License说明配置好License后,如果使用AliListPlayer播放,仍然报错License is invalid!!!,则建议您使用5.5.0.0及以上版本的播放器SDK。

  • 请确认您配置的License是否正确,判断方法请参见如何判断License是否正确

如何判断License是否正确

  1. 确认您申请的License授权与实际需要使用的SDK是否匹配,例如:仅申请了短视频SDK的授权,未申请播放器SDK的授权等。

  2. 排查您的License是否正确集成。集成方式,请参见快速集成

使用iOS Xcode14打包提交到App Store审核时报错

出现包含bitcode的错误

问题现象:使用iOS Xcode14打包APP并提交到App Store审核时出现包含bitcode的错误,报错示例如下:

 ITMS-90482: Invalid Executable - The executable 'xxx.app/Frameworks/alivcffmpeg.framework/alivcffmpeg' contains bitcode.

处理方法:您可以通过xcrun bitcode_strip手动去除对应的framework的bitcode。如下示例中,${framework_path}是framework的二进制文件路径。

xcrun bitcode_strip ${framework_path} -r -o ${framework_path}

出现使用curl的错误

问题现象:当使用iOS Xcode14打包APP并提交到App Store审核时出现使用curl的错误,报错示例如下:

ITMS-90338: Non-public API usage - The app references non-public symbols in Frameworks/AliyunPlayer.framework/AliyunPlayer: _curl_multi_poll, _curl_multi_wakeup. If method names in your source code match the private Apple APIs listed above, altering your method names will help prevent this app from being flagged in future submissions. In addition, note that one or more of the above APIs may be located in a static library that was included with your app. If so, they must be removed. For further information, visit the Technical Support Information at http://developer.apple.com/support/technical/

处理方法:

  • 如果您的项目中只集成了播放器SDK(AliPlayerSDK_iOS),则建议您升级到5.4.9.2以上版本。

  • 如果您的项目中既集成了播放器SDK(AliPlayerPartSDK_iOS),同时还集成了短视频SDK,则建议播放器SDK升级到5.4.9.2以上版本,alivcffmpeg(QuCore-ThirdParty)升级到4.3.6版本,短视频SDK升级到3.26以上版本。

出现非公开方法报错

问题现象:当使用iOS Xcode14打包APP并提交到App Store审核时出现非公开方法的错误,报错示例如下:xcode报错

处理方法:上述报错为Xcode14构建的警告,通常情况下,只要工程能构建出来,即便有警告也不影响正常发布;如果不能正常发布,则建议优先使用Xcode13系列进行发布。

出现引入mpf_filter.framework、vfi_filter.framework等插帧、锐化后处理插件相关报错

问题现象:当使用iOS Xcode14打包APP并提交到App Store审核时出现引入mpf_filter.framework、vfi_filter.framework等插帧、锐化后处理插件相关的错误,报错示例如下:xcode报错2

处理方法:

  • 如果您的工程中没有使用到报错提及的插件,则建议您删除报错的插件,不仅不会影响播放器的能力,还可以减小包的体积。

  • 如果您的工程中必须使用报错提及的插件,则可以暂时在该framework路径下的Info.plist文件中的"Bundle identifier"键值对中,将值字符串中的"_"手动去掉,然后再进行编译构建工程。

  • 可升级至5.5.2.0及以上版本,已修正命名。

IOS Demo 编译运行碰到Xcode Error PhaseScriptExecution failed with a nonzero exit code 该怎么办?

操作流程如下: 1. 进入项目目录。 2. 执行 pod deintegrate。

3. 执行 pod install。

在iOS系统上集成阿里云播放器SDK后,是否支持在Xcode模拟器上调试运行?

  • iOS播放器SDK

    建议您使用iPhone真机进行调试运行。目前仅5.4.7.1以上版本的iOS播放器SDK支持在iPhone模拟器上调试,且不支持在M1芯片的Mac模拟器上调试运行。

  • Flutter播放器SDK

    建议使用iPhone真机调试运行。如果使用Xcode14在iphone模拟器上编译如下图的报错,您可以注释掉AliPlayerFactory.m文件中的setFilterConfig:updateFilterConfig:setFilterInvalid:这三个接口方法,并一同注释掉在Flutter播放器SDK中调用到这三个接口方法的代码。ios常见问题3

播放HLS视频流并配置本地缓存后,播放失败报错403

问题现象:当以VidAuth播放方式,播放HLS(M3U8)协议的视频流时,开启本地缓存后,出现播放失败并报错403。

问题原因:由于开启本地缓存后,如果在没有充分缓存的状态下退出播放,当下一次起播时,未缓存的部分因仍然使用上一次过期的Vid鉴权信息请求,从而导致鉴权失败报错403。

处理方法:针对5.5.4.0及以后版本的播放器SDK,如果视频播放URL带有鉴权参数且播放协议为HLS,可以通过设置AVPConfig.enableStrictAuthMode字段,进行不同鉴权模式的选择(默认值为false)。

  • 非严格鉴权(false):鉴权也缓存,若上一次只缓存了部分媒体,下次播放至非缓存部分时,播放器会用缓存的鉴权发起请求,如果URL鉴权设置的有效期很短,会导致播放异常。

  • 严格鉴权(true):鉴权不缓存,每次起播都进行鉴权,无网络下会导致起播失败。

音频抢占导致iOS播放器SDK无法正常播放

问题现象:如果您的代码工程中既使用了阿里云iOS播放器SDK,同时还使用了其它音频播放控件,使用阿里云iOS播放器SDK播放视频时,视频出现无声、画面卡住等无法正常播放的现象。

问题原因:iOS系统的音频控件AVAudioSession是单例,多个音频播放控件如果不统一设置,则可能造成音频抢占的问题,从而造成无法使用阿里云iOS播放器SDK正常播放视频。

处理方法:您可以在工程中适当的位置,进行统一设置AVAudioSession。例如:将应用的音频会话配置为播放类别,并允许与其他应用混音。再如,将应用的音频会话配置为PlayAndRecord类别,用于录制+播放的场景。如果操作过程中有任何错误,错误信息将被存储在err变量中。

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&err];

同时,在阿里云iOS播放器SDK侧通过自定义设置AVAudioSession的代理,不使用SDK内部定义好的AVAudioSession逻辑,从而规避阿里云iOS播放器SDK侧可能造成的音频抢占风险。阿里云iOS播放器SDK侧的配置示例如下:

  1. 设置代理。

    [AliPlayer setAudioSessionDelegate:self];
  2. 设置代理的监听。

    return TRUE表示SDK内部不再对AVAudioSession进行设置。

    #pragma mark CicadaAudioSessionDelegate
    - (BOOL)setActive:(BOOL)active error:(NSError **)outError
    {
        return YES;
    }
    
    - (BOOL)setCategory:(NSString *)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError
    {
          return YES;
    }
    
    - (BOOL)setCategory:(AVAudioSessionCategory)category mode:(AVAudioSessionMode)mode routeSharingPolicy:(AVAudioSessionRouteSharingPolicy)policy options:(AVAudioSessionCategoryOptions)options error:(NSError **)outError
    {
        return YES;
    }

iOS播放器SDK运行时出现指向SDK的堆栈崩溃

当您在使用iOS播放器SDK时出现指向SDK的堆栈崩溃,您可以通过如下方法解决:

  1. 若您使用的iOS播放器SDK不是最新版本,建议您升级至最新版本。iOS播放器SDK在不断的推出新版本优化提升稳定性,最新版SDK的获取,请参见播放器SDK

  2. 如果升级到最新版本后仍然出现相关崩溃,建议您将全量崩溃信息提供给阿里云技术支持。获取技术支持,请参见获取技术支持

iOS播放器SDK是否支持边下载边播放?

不支持。iOS播放器SDK支持在播放的过程中通过开启本地缓存功能缓存下载视频文件,下次再播放时,直接播放缓存好的视频文件;目前不支持将放在文件目录下的本地缓存视频文件单独拿出来进行播放。

iOS播放器SDK是否支持获取播放视频的缓冲进度?

支持。iOS播放器SDK支持获取播放视频的缓冲速度、实时渲染帧率、音视频码率、网络下行码率。详细信息,请参见获取播放信息

如何获取当前播放进度

播放器SDK默认每500 ms回调一次播放进度。您可以修改回调间隔时间,通过将间隔时间缩短,以更高频率地获取当前播放进度,示例代码如下:

AVPConfig *config = [self.player getConfig];
config.positionTimerIntervalMs = 100; // 修改回调间隔时间,单位:ms。
[self.player setConfig:config];

/**
 @brief:视频当前播放位置回调。
 @param player:播放器player指针。
 @param position:视频当前播放位置。
 */
- (void)onCurrentPositionUpdate:(AliPlayer*)player position:(int64_t)position {
    // 当前播放进度。
    long currentPosition = position;
}

如何获取视频的宽高

可通过如下三种方式进行获取:

  • 方式一:通过iOS播放器AliPlayer实例执行完prepare方法,当处于准备完成状态后(AVPEventPrepareDone),可以直接获取AliPlayer实例的宽(width)和高(height)。

    -(void)onPlayerEvent:(AliPlayer*)player eventType:(AVPEventType)eventType {
        if (eventType == AVPEventPrepareDone) {
          NSLog(@"视频的宽:%d,高:%d", player.width, player.height);
        }
    }
  • 方式二:通过监听视频大小变化回调的方法,直接返回视频的宽(width)和高(height)。

    - (void)onVideoSizeChanged:(AliPlayer*)player width:(int)width height:(int)height rotation:(int)rotation {
        NSLog(@"视频的宽:%d,高:%d", width, height);
    }
  • 方式三:通过监听获取track信息回调的方法,根据info数组返回的AVPTrackInfo,获取视频的宽(videoWidth)和高(videoHeight)。

    说明

    监听获取track信息回调,由于是从网络请求,其成功获取到视频的宽高信息依赖网络质量,建议使用方式一和方式二的方法获取视频的宽高信息更为可靠。

    - (void)onTrackReady:(AliPlayer*)player info:(NSArray<AVPTrackInfo*>*)info {
        for (int i=0; i<info.count; i++) {
          AVPTrackInfo *trackInfo = info[i];
          NSLog(@"视频的宽:%d,高:%d", trackInfo.videoWidth, trackInfo.videoHeight);
      }
    }

播放器运行过程中发生crash

可通过以下步骤排查问题产生原因:

  1. 确认crash是否产生在播放器SDK。

    查看是否有带AliyunPlayer前缀的崩溃堆栈,如果有,则说明问题产生在播放器SDK。

  2. 升级至最新版播放器SDK并验证,确认问题是否已经修复。

  3. 如果问题依然存在,请准备相关的崩溃文件(包含全部线程)、崩溃日志、崩溃场景等信息,如何获取问题日志

V5.4.6.0版本播放器SDK运行过程中发生程序初始化、调用预加载相关crash

建议升级到V5.4.7.1以上版本的播放器SDK。如果需要保持V5.4.6.0版本的稳定性,也可以使用修复版本pod 5.4.6.0-25587639

视频播放相关问题

如何实现全屏播放

iOS播放器SDK不提供全屏播放的API,需要您根据系统自行实现。iOS播放器SDK Demo从5.5.0.0版本开始已经适配了iOS 16.0以上系统的全屏方法。

实现方法示例如下:

说明

执行系统全屏方法后,需要同时将Aliplayer实例设置的playerView的frame根据屏幕进行调整。

UIInterfaceOrientation orientation = UIInterfaceOrientationLandscapeLeft; // 要旋转为全屏
......

// iOS 16.0以上的系统
if (@available(iOS 16.0, *)) {
    @try {
            NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects];
      UIWindowScene *ws = (UIWindowScene *)array[0];
        Class GeometryPreferences = NSClassFromString(@"UIWindowSceneGeometryPreferencesIOS");
      id geometryPreferences = [[GeometryPreferences alloc]init];
      UIInterfaceOrientationMask orientationMask = UIInterfaceOrientationMaskLandscapeRight;
      if (orientation == UIInterfaceOrientationPortrait) {
          orientationMask = UIInterfaceOrientationMaskPortrait;
      }
      [geometryPreferences setValue:@(orientationMask) forKey:@"interfaceOrientations"];
      SEL sel_method = NSSelectorFromString(@"requestGeometryUpdateWithPreferences:errorHandler:");
      void (^ErrorBlock)(NSError *err) = ^(NSError *err){
            NSLog(@"屏幕旋转出错:%@", [err debugDescription]);
      };
      if ([ws respondsToSelector:sel_method]) {
          (((void (*)(id, SEL,id,id))[ws methodForSelector:sel_method])(ws, sel_method,geometryPreferences,ErrorBlock));
      }
  } @catch (NSException *exception) {
      NSLog(@"屏幕旋转出错:%@", exception.reason);
  } @finally {
  }
} else { // iOS16.0以下的系统
  if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
      SEL selector = NSSelectorFromString(@"setOrientation:");
      NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
      [invocation setSelector:selector];
      [invocation setTarget:[UIDevice currentDevice]];
      [invocation setArgument:&Orientation atIndex:2];
      invocation invoke];
  }
  [[UIApplication sharedApplication]setStatusBarOrientation:orientation animated:YES];
}

视频播放时画面有黑边

可通过以下步骤排查问题产生原因:

  1. 检查视频源本身是否存在黑边问题。

  2. 可通过如下接口调节播放器的缩放模式。

    /*
    AVP_SCALINGMODE_SCALEASPECTFILL:按比例填充,画面会有裁剪。
    AVP_SCALINGMODE_SCALEASPECTFIT:按比例缩放,会有黑边。
    AVP_SCALINGMODE_SCALETOFILL:不按比例填充,画面会变形。
    */
    self.player.scalingMode = AVP_SCALINGMODE_SCALETOFILL;
  3. 若缩放模式依然无法满足需求,则可以调节设置self.player.playerView的自定义View的宽和高(通过修改self.player.playerViewframe实现)。

播放视频时有声音无画面,日志报log[AFVTBDecoder] :IOS8VT: throw frame

可通过以下步骤排查问题产生原因:

  1. 使用其他播放器播放,检查视频是否是纯音频。

  2. 使用其他播放器播放时播放正常且出现视频源长宽变化,则可以设置成软解码方式,设置方法如下:

    player.enableHardwareDecoder = NO

IOS端应用处于后台时或未启动时,通过通知进入时就会出现有声音无画面的状况。

解决方法:可去除UIApplicationStateActive == [[UIApplication sharedApplication] applicationState]

- (AliPlayer *)aliPlayer{
    if (!_aliPlayer && UIApplicationStateActive == [[UIApplication sharedApplication] applicationState]) {
        _aliPlayer = [[AliPlayer alloc] init];
        _aliPlayer.scalingMode =  AVP_SCALINGMODE_SCALEASPECTFIT;
        _aliPlayer.rate = 1;
        _aliPlayer.delegate = self;
        _aliPlayer.playerView = self.playerView;
    }
    return _aliPlayer;
}

播放直播流时,日志报标准错误-5,IO错误(Input/Output (I/O))

播放直播流时,建议缓存和延迟控制设置(AVPConfig中的startBufferDurationhighBufferDurationmaxBufferDuration)都保持默认值,不进行自定义配置。请参见配置缓存和延迟控制排查是否自定义了配置缓存和延迟控制。

暂停后返回继续播放,日志报声音相关的错误Deactivating an audio session that has running I/O.All I/O should be stopped or paused prior to deactivating the audio session.

问题现象:在视频播放页面暂停播放并跳转到其他有声音的播放页面,返回时无法继续播放,日志报声音相关的错误Deactivating an audio session that has running I/O.All I/O should be stopped or paused prior to deactivating the audio session.

解决方法:排查是否存在声音设置(AudioSession属性)的冲突,例如当从其他有声页面退出时未及时恢复对声音的占用(未及时关闭相关的录音或者声音播放)。

使用列表播放器AliListPlayer播放HLS(m3u8)视频报错

V5.4.5.0及之前版本的播放器SDK不支持使用列表播放器AliListPlayer播放HLS(m3u8)格式的视频。从V5.4.5.0之后版本开始支持播放HLS(m3u8)格式的视频,但是需要开启本地缓存,开启本地缓存的方法请参见本地缓存

无法实现在后台播放视频

问题现象:iOS播放器SDK无法支持后台播放视频(即按home键以后还能继续播放视频),用Demo测试也无法实现后台播放。

解决方法:

  1. 在Xcode中开启后台采集数据功能。示例如下:DuCXfvnsZJMUdeDiGjnX.png

  2. 如果实现了程序前后台监听方法,则需要注释掉相关的暂停、重新播放方法。

    // 添加检测APP进入后台的观察者
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationEnterBackground) name: UIApplicationWillResignActiveNotification object:nil];
    // APP从后台进入前台时会调用该方法
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive) name: UIApplicationDidBecomeActiveNotification object:nil];
    
    // 需注释掉的暂停方法
    - (void)applicationEnterBackground {
       // [self.player pause];
    }
    // 需注释掉的重新播放方法
    - (void)applicationDidBecomeActive {
       // [self.player start];
    }

seek相关问题

seek后,进度条异常回跳

问题原因:播放器默认使用不精准seek。seek后播放器会从seek点附近的关键帧开始播放。

解决方法:切换为精准seek模式。

如何切换精准seek和非精准seek模式

切换seek模式的示例代码如下:

//切换为非精准seek。
[self.player seekToTime:1000 seekMode:AVP_SEEKMODE_INACCURATE];
//切换为精准seek。
[self.player seekToTime:1000 seekMode:AVP_SEEKMODE_ACCURATE];

使用精准seek模式后,进度条也会异常回跳

问题原因:由于精准seek耗时比非精准seek耗时更长,当seek点距离关键帧间隔过大,超过精准seek的最大间隔时,播放器SDK会自动切换成非精准seek,导致进度条回跳。

解决方法:可以通过接口设置精准seek的最大间隔,将精准seek的最大间隔调大,降低精准seek被切换成非精准seek的频率,以提高seek精准度,但当seek的点距离关键帧间隔太长时,耗时也将更长,请根据业务特点合理设置精准seek的最大间隔。示例代码如下:

//单位:ms。
[self.player setMaxAccurateSeekDelta:100];

使用边播边缓存(CacheConfig)时缓存失败

可以在onPlayerEvent回调中,获取缓存失败的原因。onPlayerEvent回调的示例代码如下:

/**
 @brief:播放器事件回调。
 @param player:播放器player指针。
 @param eventWithString:播放器事件类型。
 @param description:播放器事件说明。
 @see AVPEventType
 */
-(void)onPlayerEvent:(AliPlayer*)player eventWithString:(AVPEventWithString)eventWithString description:(NSString *)description {
    if (eventWithString == EVENT_PLAYER_CACHE_SUCCESS) { // 边播边缓存成功。

    } else if (eventWithString == EVENT_PLAYER_CACHE_ERROR) { // 边播边缓存失败。
        NSString *errorMsg = description;
    }
}

常见的失败原因如下:

  • CacheConfig中设置的大小和时长与视频不匹配导致缓存失败。

  • 在播放过程中,stop或者seek到buffer外导致缓存失败。

说明

播放器SDK V5.4.4.0版本,新增支持的预加载和本地缓存能力,可以完全替代边播边缓存的使用场景。建议使用新增加的本地缓存能力,更多内容请参见进阶功能

视频缓存时报错encrypt check fail

缓存即下载,如果设置了安全下载,请确认加密校验文件与App信息是否匹配(即需要将离线下载中生成的加密校验文件下载并保存到播放器SDK中,详细内容请参见视频下载),否则会导致缓存或下载失败。

获取音视频源数据

获取音视频源数据的示例代码如下:

// 设置渲染回调。
self.player.renderingDelegate = self;

// 监听渲染回调。
- (BOOL)onRenderingFrame:(CicadaFrameInfo*) frameInfo {
    if (frameInfo.frameType == Cicada_FrameType_Video) { // 底层视频数据。

    } else if (frameInfo.frameType == Cicada_FrameType_Audio) { // 底层音频数据。

    }
    return NO;
}

自动码率切换逻辑

当开启自动码率切换,即调用了[self.player selectTrack:SELECT_AVPTRACK_TYPE_VIDEO_AUTO];接口后,播放器SDK内部会统计当前网速,当10秒内网速达到下一个码率时,就会切换到下一个码率。若10秒内网速未达到下一个码率,则不切换。

  • 从高码率切换到低码率的场景,当10秒内网速达到下一个码率时,会将已缓存的高码率内容播放完成后才切换。

  • 从低码率切换到高码率的场景,当10秒内网速达到下一个码率时,会直接切换。

自定义重试逻辑

在网络重试场景下,播放器SDK默认重试次数为2次,网络超时时间为15秒,当重试失败后会触发Error回调。

可以自定义重试逻辑,当触发重试时,将重试事件通知到外部,由外部决定具体的重试逻辑。示例代码如下:

AVPConfig *config = [self.player getConfig];
config.networkRetryCount = 0; // 设置重试次数,此处以设置为0为例。
[self.player setConfig:config];

/**
 @brief:播放器事件回调。
 @param player:播放器player指针。
 @param eventWithString:播放器事件类型。
 @param description:播放器事件说明。
 @see AVPEventType
 */
-(void)onPlayerEvent:(AliPlayer*)player eventWithString:(AVPEventWithString)eventWithString description:(NSString *)description {
    if (eventWithString == EVENT_PLAYER_NETWORK_RETRY) { // 网络失败,需要重试。
        // TODO做相应的逻辑处理。
    }
}

播放RTS流时,报错协议不支持

可通过以下步骤排查报错原因:

  1. 检查3个SDK(AliPlayerSDK_iOS、AliPlayerSDK_iOS_ARTC、RtsSDK)是否全部都已集成。

    使用阿里云播放器播放RTS流,需要集成3个SDK:AliPlayerSDK_iOS、AliPlayerSDK_iOS_ARTC、RtsSDK。集成操作可参见阿里云播放器SDK集成Native RTS SDK实现说明

  2. 检查Native RTS SDK(RtsSDK)和阿里云播放器SDK(AliPlayerSDK_iOS)的版本是否配套。

    Native RTS SDK和阿里云播放器SDK有版本配套关系,需要集成对应的版本,版本配套关系请参见SDK下载

  3. 检查AliPlayerSDK_iOS和AliPlayerSDK_iOS_ARTC的版本是否一致,需保持一致。

缩略图使用

在播放器SDK中使用缩略图前,请确保已为视频配置缩略图,即视频已生成雪碧截图(在视频点播控制台创建类型为雪碧图的截图模板,通过工作流将视频用该雪碧图的截图模板处理后,生成雪碧图数据),详细内容请参见视频截图。播放器SDK中使用缩略图的示例代码如下:

/**
 当前Track是否有缩略图,如果没有,不展示缩略图。
 */
@property (nonatomic,assign)BOOL trackHasThumbnai;

/**
 创建自定义显示缩略图的视图。
 */
@property (nonatomic,strong)UIImageView *thumbnaiView;

/**
 @brief:获取track信息回调。
 @param player:播放器player指针。
 @param info:track流信息数组,可参考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;
    }
}

/**
 进度条改变进度回调。
 @param playerView playerView
 @param value:进度值。
 */
- (void)AVPPlayerView:(AVPPlayerView *)playerView progressSliderValueChanged:(CGFloat)value {
    if (self.trackHasThumbnai) {
        [self.player getThumbnail:self.player.duration*value];
    }
}

/**
 @brief:获取缩略图成功回调。
 @param positionMs:指定的缩略图位置。
 @param fromPos:此缩略图的开始位置。
 @param toPos:此缩略图的结束位置。
 @param image:缩图略图像指针,对于mac是NSImage,iOS平台是UIImage指针。
 */
- (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:获取缩略图失败回调。
 @param positionMs:指定的缩略图位置。
 */
- (void)onGetThumbnailFailed:(int64_t)positionMs {
    self.thumbnaiView.hidden = YES;
}

请注意:如果用户使用的是URL方式的播放,使用上述代码并不能直接显示缩略图,因为onTrackReady并不支持URL播放的MediaInfo回调,建议用户直接指定缩略图URL。

/**
 当前Track是否有缩略图,如果没有,不展示缩略图。
 */
@property (nonatomic,assign)BOOL trackHasThumbnai;

/**
 创建自定义显示缩略图的视图
 */
@property (nonatomic,strong)UIImageView *thumbnaiView;

/**
  onPrepare
 */
- (void)onPlayerStatusChanged:(AliPlayer*)player oldStatus:(AVPStatus)oldStatus newStatus:(AVPStatus)newStatus {
  if(newStatus == AVPStatusPrepared){
       [self.player setThumbnailUrl:[URL];// 具体的缩略图url 请根据控制台api生成
       self.trackHasThumbnai = YES;
  }
}
/**
 进度条改变进度回调。
 @param playerView playerView
 @param value:进度值。
 */
- (void)AVPPlayerView:(AVPPlayerView *)playerView progressSliderValueChanged:(CGFloat)value {
    if (self.trackHasThumbnai) {
        [self.player getThumbnail:self.player.duration*value];
    }
}

/**
 @brief:获取缩略图成功回调。
 @param positionMs:指定的缩略图位置。
 @param fromPos:此缩略图的开始位置。
 @param toPos:此缩略图的结束位置。
 @param image:缩图略图像指针,对于mac是NSImage,iOS平台是UIImage指针。
 */
- (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:获取缩略图失败回调。
 @param positionMs:指定的缩略图位置。
 */
- (void)onGetThumbnailFailed:(int64_t)positionMs {
    self.thumbnaiView.hidden = YES;
}

清晰度相关问题

视频转码了多个清晰度,播放器SDK默认会播放视频的哪个清晰度?

默认清晰度播放顺序:FD、LD、SD、HD、2K、4K、OD,清晰度的定义请参见清晰度:Definition。播放器SDK会从左到右依次查找,找到哪个清晰度就播放哪个清晰度。

如何指定视频播放默认清晰度?

示例代码如下:

//以VidSts播放方式为例。
AVPVidStsSource *stsSource = [[AVPVidStsSource alloc] init];
stsSource.vid = @"<vid>";
stsSource.accessKeyId = @"<accessKeyId>";
stsSource.securityToken = @"<securityToken>";
stsSource.accessKeySecret = @"<accessKeySecret>";
stsSource.quality = @""; // 期望播放的清晰度,取值为FD、LD、SD、HD、2K、4K、OD。
stsSource.forceQuality = NO; // 是否强制使用期望播放的清晰度播放。NO:不强制使用期望的清晰度播放,按播放器SDK的默认清晰度播放顺序查找播放;YES:强制使用设置的期望清晰度播放,如果找不到期望播放的清晰度就不播放。

如果同一个清晰度有多个码流,播放器SDK会播放哪个码流?

当同一个清晰度有多个码流时,播放器SDK会播放最新的码流。

如何设置同一个视频,在播放时无水印,下载后带水印?

将视频转码多个清晰度,播放时播放无水印的清晰度,下载时下载有水印的清晰度。

横屏无法生效

iOS播放器SDK本身不提供实现横屏的方法,您需要根据iOS系统API实现,注意实现横屏时合理设置aliplayer.playerViewframe

如何获取问题日志

当您向阿里云获取技术支持时,请将您的问题日志一并提交,以便更高效地为您解决问题。问题日志的获取方法如下:

  1. 获取问题日志。

    建议将日志级别设置为LOG_LEVEL_TRACE后再获取问题日志。具体方法请参见获取SDK日志

  2. 将生成的日志提供给阿里云技术支持。

    详情请参见获取技术支持