文档首页 > > 播放器SDK> iOS播放器> SDK使用

SDK使用

分享
更新时间:2020/09/17 GMT+08:00

实现播放功能

  1. 根据APP需求设置options参数,设置规则请参考IJKFFOptions类

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    IJKFFOptions *options = [IJKFFOptions optionsByDefault]; 
    [options setPlayerOptionIntValue:30 forKey:@"max-fps"]; 
    [options setPlayerOptionIntValue:30 forKey:@"r"]; 
    //跳帧开关
    [options setPlayerOptionIntValue:1 forKey:@"framedrop"]; 
    [options setPlayerOptionIntValue:0 forKey:@"start-on-prepared"]; 
    [options setPlayerOptionIntValue:0 forKey:@"http-detect-range-support"]; 
    [options setPlayerOptionIntValue:48 forKey:@"skip_loop_filter"]; 
    [options setPlayerOptionIntValue:0 forKey:@"packet-buffering"]; 
    [options setPlayerOptionIntValue:2000000 forKey:@"analyzeduration"]; 
    [options setPlayerOptionIntValue:25 forKey:@"min-frames"]; 
    [options setPlayerOptionIntValue:1 forKey:@"start-on-prepared"]; 
    [options setCodecOptionIntValue:8 forKey:@"skip_frame"]; 
    [options setFormatOptionValue:@"nobuffer" forKey:@"fflags"]; 
    [options setFormatOptionValue:@"8192" forKey:@"probsize"];
    //自动转屏开关
    [options setFormatOptionIntValue:0 forKey:@"auto_convert"]; 
    //重连次数
    [options setFormatOptionIntValue:1 forKey:@"reconnect"]; 
    //开启硬解码
    [options setPlayerOptionIntValue:1 forKey:@"videotoolbox"];
    

  2. 初始化播放器

    1
    2
    3
    self.player = [[IJKFFMoviePlayerController alloc] initWithContentURL:self.url withOptions:options];
    //设置是否自动播放
    self.player.shouldAutoplay = YES;
    
    • self.url:播放地址。
    • options:设置参数。

  3. 设置播放区域。

    1
    2
    3
    4
    5
    6
    self.playView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, ScreenWidth, ScreenHeight)];
    self.playView.backgroundColor = [UIColor blackColor]; 
    [self.view addSubview:self.playView]; 
    UIView *playingView = [self.player view]; 
    playingView.frame = self.playView.bounds; 
    [self.playView insertSubview:playingView atIndex:1];
    

  4. 开始播放

    1
    2
    3
    4
    5
    [self.player setScalingMode:IJKMPMovieScalingModeFill];
    [self installMovieNotificationObservers]; 
    if(![self.player isPlaying]){
    [self.player prepareToPlay];
     }
    

  5. 暂停播放

    1
    2
    3
    if ([self.player isPlaying]) {
            [self.player pause];
    }
    

  6. 执行播放

    1
    2
    3
    if (![self.player isPlaying]) {
            [self.player play];
    }
    

  7. 倍速播放。

    1
    2
    3
     (void)setRate:(float)rate{
        self.player.playbackRate = rate;
    }
    

  8. 停止播放

    1
    2
    3
    if ([self.player isPlaying]) {
            [self.player stop];
    }
    

  9. 释放播放资源

    该步骤会停止播放器并释放播放器视图资源。

    1
    2
    3
    4
    5
    if (self.player) {
            [self.player shutdown];
            [self.player.view removeFromSuperview];
            self.player=nil;
        }
    

外挂字幕功能

iOS外挂字幕功能支持“.ass”“.srt”格式的字幕文件,支持同时显示中文和英文字幕,支持随时调整字幕时间以实现字幕和视频的同步。

  1. 初始化。

    1
    2
    3
    4
    5
    IJKSubtitleView *subtitleView = [[IjKSubtitleView alloc] initWithFrame:CGRectMake(0,0,375,40)];
    [subtitleView configurationSubtitleViewWithContenPath:[[NSBundle main] pathForResource:@"shame" ofType:@"ass"]];
    /// 也可以在视频播放时改动
    subtitleView.changeTime = 8;
    [self.Play.view addsubView:subtitleView];
    

  2. 链接播放器。

    1
    [subtitleView setPlay:self.delegatePlayer]
    

    可以在播放器对象创建成功后再进行链接,若播放器传入为空,则会造成字幕显示出错或者无法显示。

  3. 销毁字幕。

    1
    [subtitleView destroySubtitle];
    

    每次结束播放时需要调用stop方法,并在stop方法中执行字幕销毁方法。

重连播放

iOS播放器SDK可以实现如下情况下的重连播放。

  • 当主播由于网络等问题导致推流中断时,若在有效时间内重新推流,并且播放器端未播放新的直播流,则可以重新播放。
  • 当观众观看直播时因网络原因中断时,若在有效时间内重新连接网络,则播放器可以恢复重新播放。
通过播放器的hook协议即可实现重连播放,当前重连功能暂只支持RTMP和HTTP协议。
1
2
3
4
5
6
7
NSString *url = @"rtmp://kitplay.hwcloudlive.com/live1/pushLiveSdkDemo";
    if ([url containsString:@"http"] || [url containsString:@"https"]) {
        url = [NSString stringWithFormat:@"ijkhttphook:%@",url];
    } else if ([url containsString:@"rtmp"] || [url containsString:@"rtsp"])
    {
        url = [NSString stringWithFormat:@"ijklivehook:%@",url];
    }

弹幕功能

iOS播放器SDK的弹幕功能是通过开源弹幕渲染库“BarrageRenderer”实现的。

  1. 下载“BarrageRenderer”弹幕渲染库,
  2. “BarrageRenderer”文件夹中的全部资源导入到Xcode项目中。

    图1 弹幕资源文件

  3. 初始化。

    1
    2
    3
    4
    5
    6
        _renderer = [[BarrageRenderer alloc]init];
        _renderer.delegate = self;
        _renderer.redisplay = YES; 
        [self.view addSubview:_renderer.view];
        [self.view sendSubviewToBack:_renderer.view];
        [self.renderer start];
    

  4. 添加弹幕。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    #pragma mark - 弹幕描述符生产方法
    //生成精灵描述 - 延时文字弹幕
    - (BarrageDescriptor *)walkTextSpriteDescriptorWithDelay:(NSTimeInterval)delay{
        BarrageDescriptor * descriptor = [[BarrageDescriptor alloc]init];
        descriptor.spriteName = NSStringFromClass([BarrageWalkTextSprite class]);
        descriptor.params[@"text"] = [NSString stringWithFormat:@"延时弹幕(延时%.0f秒)",delay];
        descriptor.params[@"textColor"] = [UIColor blueColor];
        descriptor.params[@"speed"] = @(100 * (double)random()/RAND_MAX+50);
        descriptor.params[@"direction"] = @(1);
        descriptor.params[@"delay"] = @(delay);
        return descriptor;
    }
    // 图文混排精灵弹幕 - 过场图文弹幕A
    - (BarrageDescriptor *)walkImageTextSpriteDescriptorAWithDirection:(NSInteger)direction{
        BarrageDescriptor * descriptor = [[BarrageDescriptor alloc]init];
        descriptor.spriteName = NSStringFromClass([BarrageWalkTextSprite class]);
        descriptor.params[@"text"] = [NSString stringWithFormat:@"AA-图文混排/::B过场弹幕:%@",@"华为视频云"];
        descriptor.params[@"textColor"] = [UIColor greenColor];
        descriptor.params[@"speed"] = @(100 * (double)random()/RAND_MAX+50);
        descriptor.params[@"direction"] = @(direction);
        return descriptor;
    }
    // 图文混排精灵弹幕 - 过场图文弹幕B
    - (BarrageDescriptor *)walkImageTextSpriteDescriptorBWithDirection:(NSInteger)direction{
        BarrageDescriptor * descriptor = [[BarrageDescriptor alloc]init];
        descriptor.spriteName = NSStringFromClass([BarrageWalkTextSprite class]);
        descriptor.params[@"text"] = [NSString stringWithFormat:@"AA-图文混排/::B过场弹幕:%@",@"华为视频云"];
        descriptor.params[@"textColor"] = [UIColor greenColor];
        descriptor.params[@"speed"] = @(100 * (double)random()/RAND_MAX+50);
        descriptor.params[@"direction"] = @(BarrageWalkDirectionL2R);    NSTextAttachment * attachment = [[NSTextAttachment alloc]init];
        attachment.image = [[UIImage imageNamed:@"icon_cutout"]
        barrageImageScaleToSize:CGSizeMake(25.0f, 25.0f)];
        NSMutableAttributedString * attributed = [[NSMutableAttributedString alloc]initWithString:[NSString stringWithFormat:@"BB-图文混排过场弹幕:%@",@"华为视频云"]];
        [attributed insertAttributedString:[NSAttributedString attributedStringWithAttachment:attachment] atIndex:7];    descriptor.params[@"attributedText"] = attributed;
        descriptor.params[@"textColor"] = [UIColor magentaColor];
        descriptor.params[@"speed"] = @(100 * (double)random()/RAND_MAX+50);
        descriptor.params[@"direction"] = @(BarrageWalkDirectionL2R);
        descriptor.params[@"delay"] = @(direction);
        return descriptor;
    }
       [self.view insertSubview:_renderer.view aboveSubview:self.player.view];
        NSInteger const number = 100;
        NSMutableArray * descriptors = [[NSMutableArray alloc]init];
        for (NSInteger i = 0; i < number; i++) {
            [descriptors addObject:[self walkTextSpriteDescriptorWithDelay:i*2+1]];
            [descriptors addObject:[self walkImageTextSpriteDescriptorBWithDirection:i*2]];
        }
        [_renderer load:descriptors];
    

  5. 暂停弹幕。

    1
    [self.renderer pause];
    

  6. 停止弹幕。

    1
     [self.renderer stop];
    

播放器优化

  • 丢帧处理

    默认音视频处理方案是视频同步音频,当CPU处理视频速度过慢时,会导致音频播放快于视频导致丢帧现象。

    优化方案:通过修改framedrop进行优化,在CPU无法正常处理视频时,丢弃视频非关键帧达到与音频同步的效果,ijkplayer默认为1,可根据实际需求进行修改。

    1
    [options setPlayerOptionIntValue:0 forKey:@"framedrop"]; // 跳帧开关。
    

    如果CPU解码能力不足,可以设置成5,否则会引起音视频不同步,也可以通过设置跳帧达到倍速播放。

  • 降码率

    如果使用硬编码,在网络环境较差的情况下,为了使直播画面更为流畅,可以实时改变硬编码率,进行丢帧处理,在丢帧的同时也可降低音频的码率。

    1
    [options setOptionIntValue:1 forKey:@"videotoolbox" ofCategory:kIJKFFOptionCategoryPlayer]; // 开启硬编码videotoolbox(解码模式 0:软解码;1:硬解码)。
    
  • 软硬编解码的选择
    表1 软硬编解码说明

    名称

    描述

    优点

    缺点

    软编解码

    主要使用CPU进行编解码,通常情况下使用FFmpeg进行编码和解压音视频数据。

    • 在不同的设备、系统版本中兼容性极高。
    • 解码时,色彩还原度更高。
    • 编解码过程可扩展性强。

    CPU占用高,手机易发热,耗电量大。

    硬编解码

    主要使用非CPU进行编解码,如GPU等,通常情况下直接调用系统API进行音视频编解码处理。

    系统占用少,执行效率高。

    • 兼容性低,需根据硬件厂商和系统版本单独适配。
    • 可控性比较差。
    • iOS硬件芯片为统一的videoToolBox解码后的NV12数据格式。
    • Android使用的mediacodec解码的数据格式跟手机硬件厂商有关,无法统一mediacodec解码出来的数据格式。

    综合以上情况,在推流方面,iOS系统和硬件设备统一性高,使用全硬编方案效果更好;Android因机型繁杂,支持程度不一,推荐4.3以上版本使用硬编。在播放解码方面,iOS硬解和软解支持性都较高,软解功耗更高,但是在部分细节方面表现较优,可控性强,具体视项目情况选择;Android推荐4.1版本以上使用硬解,4.1以下版本使用软解。

  • 直播与点播建议设置参数如下所示。
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    if (_isLive) {         
    // Param for living         
    [options setPlayerOptionIntValue:3000 forKey:@"max_cached_duration"];   // 最大缓存大小是3秒,可以根据实际需求进行修改         
    [options setPlayerOptionIntValue:1 forKey:@"infbuf"];  // 无限读         
    [options setPlayerOptionIntValue:0 forKey:@"packet-buffering"];  //  关闭播放器缓冲     
    } else {         
    // Param for playback         
    [options setPlayerOptionIntValue:0 forKey:@"max_cached_duration"];         
    [options setPlayerOptionIntValue:0 forKey:@"infbuf"];         
    [options setPlayerOptionIntValue:1 forKey:@"packet-buffering"];     
    }
    
  • 累积延迟
    • RTMP到达CDN时存在4.0到5.0秒的延迟,可以通过设置IJKPlayer相关参数进行优化。
      表2 参数说明

      参数

      说明

      skip_loop_filter

      对所选帧进行跳过环路滤波。

      skip_frame

      编解码器丢弃所有非关键帧。

    • 优化延迟问题还可以从推流端将编码器调低GOP,如1秒一个GOP,这样可以减小延迟时长,但会导致编码器压缩率降低,图像质量下降,并且会加大服务端的数据压力。
    • 导致延迟还有一个主要原因是ffplay默认的帧率控制没有追帧策略,若网络发生抖动,延时会累加。优化策略就是调整帧率控制部分,保障流畅度和实时性。
分享:

    相关文档

    相关产品

文档是否有解决您的问题?

提交成功!非常感谢您的反馈,我们会继续努力做到更好!
反馈提交失败,请稍后再试!

*必选

请至少选择或填写一项反馈信息

字符长度不能超过200

提交反馈 取消

如您有其它疑问,您也可以通过华为云社区问答频道来与我们联系探讨

智能客服提问云社区提问