直播云

  • 概述

    最近更新时间:2017-12-21 11:19:58

    1 概述

    PLMediaStreamingKit 是一个适用于 iOS 的 RTMP 直播推流 SDK,可高度定制化和二次开发。SDK 提供 RTMP 推流的全套解决方案,包括采集,处理(美颜,水印等),编码,封包,发送。特色是支持 H.264 硬编码,以及支持 AAC-LC 硬编码;同时,还根据移动网络环境的多变性,实现了一套可供开发者灵活选择的编码参数集合。

    1.1 SDK 下载地址

    PLMediaStreamingKit

    1.2 功能以及版本

    功能 描述 版本
    支持硬件编码 更低的 CPU 占用及发热量 v1.0.0(+)
    支持 ARM7, ARM64 指令集 为最新设备优化 v1.0.0(+)
    提供音视频配置分离 配置解耦 v1.0.0(+)
    支持推流时码率变更 更方便定制流畅度/清晰度策略 v1.0.0(+)
    支持弱网丢帧策略 不必担心累计延时,保障实时性 v1.0.0(+)
    支持模拟器运行 不影响模拟器快速调试 v1.0.0(+)
    支持 RTMP 协议直播推流 保证秒级实时性 v1.0.0(+)
    支持后台推流 轻松实现边推流边聊天等操作 v1.0.0(+)
    提供多码率可选 更自由的配置 v1.1.2(+)
    提供 H.264 视频编码 多种 profile level 可设定 v1.1.2(+)
    支持多分辨率编码 更可控的清晰度 v1.1.2(+)
    提供 AAC 音频编码 当前采用 AAC-LC v1.1.2(+)
    提供 HeaderDoc 文档 开发中使用 Quick Help 及时阅读文档 v1.1.3(+)
    支持美颜滤镜 轻松实现更美真人秀 v1.7.0(+)
    支持水印功能 彰显自身特色 v1.7.0(+)
    提供内置音效及音频文件播放功能 轻松实现各种音效 v2.1.0(+)
    支持返听功能 唱歌更易把握节奏 v2.1.0(+)
    支持截屏功能 轻松分享美好瞬间 v2.1.2(+)
    支持 iOS 10 ReplayKit 录屏 方便分享游戏过程 v2.1.4(+)
    支持苹果 ATS 安全标准 安全性更高 v2.1.6(+)
    支持后台推图片功能 观看体验更佳 v2.2.1(+)

    2 阅读对象

    本文档为技术文档,需要阅读者:

    • 具有基本的 iOS 开发能力
    • 准备接入七牛云直播

    3 开发准备

    3.1 设备以及系统

    • 设备要求:iPhone 5 及以上
    • 系统要求:iOS 8 及以上

    3.2 前置条件

    • 已注册七牛账号
    • 通过 pili@qiniu.com 申请并已开通直播权限

    4 快速开始

    4.1 开发环境配置

    4.2 导入 SDK

    4.2.1 使用 CocoaPods 导入

    推荐使用 CocoaPods 的方式导入,步骤如下:

    • 在工作目录中创建名称为 Podfile 的文件
    • 在 Podfile 中添加如下一行
    pod 'PLMediaStreamingKit'
    
    • 在终端中运行
    $ pod install
    

    到此,你已完成了 PLMediaStreamingKit 的添加。

    此外,如果你希望将 PLMediaStreamingKit 从旧版本升级到新版本,可以在终端中运行

    $ pod update
    

    4.2.2 手动导入

    我们建议使用 CocoaPods 导入,如果由于特殊原因需要手动导入,可以按照如下步骤进行:

    • 将 Pod 目录下的文件加入到工程中;
    • https://github.com/qiniu/happy-dns-objc HappyDNS 目录下的所有文件加入到工程中;
    • https://github.com/pili-engineering/pili-librtmp Pod 目录下的所有文件加入到工程中;
    • https://github.com/qiniu/iOS-netdiag Pod 目录下的所有文件加入到工程中;
    • 在工程对应 TARGET 中,右侧 Tab 选择 "Build Phases",在 "Link Binary With Libraries" 中加入 UIKit、AVFoundation、CoreGraphics、CFNetwork、CoreMedia、AudioToolbox 这些 framework,并加入 libc++.tdb、libz.tdb 及 libresolv.tbd;
    • 在工程对应 TARGET 中,右侧 Tab 选择 "Build Settings",在 "Other Linker Flags" 中加入 "-ObjC" 选项;

    4.3 初始化推流逻辑

    4.3.1 添加引用并初始化 SDK 使用环境

    AppDelegate.m 中添加引用

    #import <PLMediaStreamingKit/PLMediaStreamingKit.h>
    

    并在 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 中添加如下代码:

    [PLStreamingEnv initEnv];
    

    然后在 ViewController.m 中添加引用

    #import <PLMediaStreamingKit/PLMediaStreamingKit.h>
    

    4.3.2 添加 session 属性

    添加 session 属性在 ViewController.m

    @property (nonatomic, strong) PLMediaStreamingSession *session;
    

    4.4 创建流对象

    4.4.1 创建视频和音频的采集和编码配置对象

    当前使用默认配置,之后可以深入研究按照自己的需求作更改

    PLVideoCaptureConfiguration *videoCaptureConfiguration = [PLVideoCaptureConfiguration defaultConfiguration];
    PLAudioCaptureConfiguration *audioCaptureConfiguration = [PLAudioCaptureConfiguration defaultConfiguration];
    PLVideoStreamingConfiguration *videoStreamingConfiguration = [PLVideoStreamingConfiguration defaultConfiguration];
    PLAudioStreamingConfiguration *audioStreamingConfiguration = [PLAudioStreamingConfiguration defaultConfiguration];
    

    4.4.2 创建推流 session 对象

    self.session = [[PLMediaStreamingSession alloc] initWithVideoCaptureConfiguration:videoCaptureConfiguration audioCaptureConfiguration:audioCaptureConfiguration videoStreamingConfiguration:videoStreamingConfiguration audioStreamingConfiguration:audioStreamingConfiguration stream:nil];
    

    4.5 预览摄像头拍摄效果

    将预览视图添加为当前视图的子视图

    [self.view addSubview:self.session.previewView];
    

    4.6 添加推流操作

    取一个最简单的场景,就是点击一个按钮,然后触发发起直播的操作。

    4.6.1 添加触发按钮

    我们在 view 上添加一个按钮吧。 我们在 - (void)viewDidLoad 方法最后添加如下代码

    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
    [button setTitle:@"start" forState:UIControlStateNormal];
    button.frame = CGRectMake(0, 0, 100, 44);
    button.center = CGPointMake(CGRectGetMidX([UIScreen mainScreen].bounds), CGRectGetHeight([UIScreen mainScreen].bounds) - 80);
    [button addTarget:self action:@selector(actionButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
    

    ###4.6.2 创建推流地址 在实际开发过程中,为了您的 App 有更好的用户体验,建议提前从服务器端获取推流地址

    NSURL *pushURL = [NSURL URLWithString:@"your push url"];
    

    4.6.3 实现按钮动作

    - (void)actionButtonPressed:(id)sender {
        [self.session startStreamingWithPushURL:pushURL feedback:^(PLStreamStartStateFeedback feedback) {
                if (feedback == PLStreamStartStateSuccess) {
                    NSLog(@"Streaming started.");
                }
                else {
                    NSLog(@"Oops.");
                }
         }];
    }
    

    4.6.3 完成首次推流操作

    Done,没有额外的代码了,现在可以开始一次推流了。 如果运行后,点击按钮提示 Oops.,就要检查一下你之前创建 PLStream 对象时填写的 StreamJson 是否有漏填或者填错的内容。

    4.7 查看推流内容

    4.7.1 登录 pili.qiniu.com 查看内容

    • 登录 pili.qiniu.com
    • 登录 streamJson 中使用的 hub
    • 查看 stream 属性
    • 点击属性中的播放 URL 后的箭头,即可查看内容。

    4.8 DEMO下载

    5 功能使用

    当你要深入理解 SDK 的一些参数及有定制化需求时,可以从高级功能部分中查询阅读,以下小节无前后依赖。

    5.1 音视频采集和编码配置

    PLMediaStreamingKit 中通过不同的 configuration 设置不同的采集或编码配置信息,对应的有:

    • PLVideoCaptureConfiguration 视频采集配置
    • PLAudioCaptureConfiguration 音频采集配置
    • PLVideoStreamingConfiguration 视频编码配置
    • PLAudioStreamingConfiguration 音频编码配置

    可以通过如下途径来设置 configuration:

    • PLMediaStreamingSession init 时传递对应的 configuration
    • 在推流前、推流中、推流结束后调用 - (void)reloadVideoStreamingConfiguration:(PLVideoStreamingConfiguration *)videoStreamingConfiguration; 重置视频编码配置
    • 对于视频采集配置,可以直接设置 PLMediaStreamingSession 相关的属性;

    需要注意的是,通过 reload 方法重置 configuration 时,需要确保传递的 configuration 与当前 session 已经持有的不是一个对象。

    5.1.1 视频采集参数

    1.自定义视频采集参数

    当前的 PLVideoCaptureConfiguration 中可自行设定的参数有

    • videoFrameRate
      • 即 FPS,每一秒所包含的视频帧数
    • sessionPreset
      • 即采集时的画幅分辨率大小
    • previewMirrorFrontFacing
      • 是否在使用前置摄像头采集的时候镜像预览画面
    • previewMirrorRearFacing
      • 是否在使用后置摄像头采集的时候镜像预览画面
    • streamMirrorFrontFacing
      • 是否在使用前置摄像头采集的时候镜像编码画面
    • streamMirrorRearFacing
      • 是否在使用后置摄像头采集的时候镜像编码画面
    • position
      • 开启 PLMediaStreamingSession 的时候默认使用前置还是后置摄像头
    • videoOrientation
      • 开启 PLMediaStreamingSession 的时候默认使用哪个旋转方向

    需要注意的是指定分辨率的 sessionPreset 例如 AVCaptureSessionPreset1920x1080 并非所有机型的所有摄像头均支持,在设置相应的采集分辨率之前请务必保证做过充分的机型适配测试,避免在某些机型使用该机型摄像头不支持的 sessionPreset。另外,如果使用只指定采集质量的 sessionPreset,例如 AVCaptureSessionPresetMedium,那系统会根据当前摄像头的支持情况使用相应质量等级的分辨率进行采集。

    5.1.2 音频采集参数

    自定义音频采集参数

    当前的 PLAudioCaptureConfiguration 中可自行设定的参数有

    • channelsPerFrame

      • 采集时的声道数,默认为 1,并非所有采集设备都支持多声道数据的采集,可以通过检查 [AVAudioSession sharedInstance].maximumInputNumberOfChannels 得到当前采集设备支持的最大声道数。
    • acousticEchoCancellationEnable

      • 回声消除开关,默认为 NO。普通直播用到回声消除的场景不多,当用户开启返听功能,并且使用外放时,可打开这个开关,防止产生尖锐的啸叫声。

    5.1.3 视频编码参数

    当不确定视频编码具体的参数该如何设定时,你可以选择 SDK 内置的几种视频编码质量。

    Quality 的对比

    Quality VideoSize FPS ProfileLevel Video BitRate(Kbps)
    kPLVideoStreamingQualityLow1 272x480 24 Baseline AutoLevel 128
    kPLVideoStreamingQualityLow2 272x480 24 Baseline AutoLevel 256
    kPLVideoStreamingQualityLow3 272x480 24 Baseline AutoLevel 512
    kPLVideoStreamingQualityMedium1 368x640 24 High AutoLevel 512
    kPLVideoStreamingQualityMedium2 368x640 24 High AutoLevel 768
    kPLVideoStreamingQualityMedium3 368x640 24 High AutoLevel 1024
    kPLVideoStreamingQualityHigh1 720x1280 24 High AutoLevel 1024
    kPLVideoStreamingQualityHigh2 720x1280 24 High AutoLevel 1280
    kPLVideoStreamingQualityHigh3 720x1280 24 High AutoLevel 1536

    自定义编码参数

    当前的 PLVideoStreamingConfiguration 中可自行设定的参数有

    • videoProfileLevel
      • H.264 编码时对应的 profile level 影响编码压缩算法的复杂度和编码耗能。设置的越高压缩率越高,算法复杂度越高,相应的可能带来发热量更大的情况
    • videoSize
      • 编码的分辨率,对于采集到的图像,编码前会按照这个分辨率来做拉伸或者裁剪
    • expectedSourceVideoFrameRate
      • 预期视频的编码帧率,这个数值对编码器的来说并不是直接限定了 fps, 而是给编码器一个预期的视频帧率,最终编码的视频帧率,是由实际输入的数据决定的
    • videoMaxKeyframeInterval
      • 两个关键帧的帧间隔,一般设置为 FPS 的三倍
    • averageVideoBitRate
      • 平均的编码码率,设定后编码时的码率并不会是恒定不变,静物较低,动态物体会相应升高
    • videoEncoderType
      • H.264 编码器类型,默认采用 PLH264EncoderType_AVFoundation 编码方式,在 iOS 8 及以上的系统可采用 PLH264EncoderType_VideoToolbox,编码效率更高

    PLMediaStreamingKit 为了防止编码参数设定失败而导致编码失败,出现推流无视频的情况,依据 videoProfileLevel 限定了其他参数的范围,该限定范围针对 Quality 生成的配置同样有效。参见以下表格:

    ProfileLevel Max VideoSize Max FPS Max Video BitRate(Mbps)
    Baseline 30 (720, 480) 30 10
    Baseline 31 (1280, 720) 30 14
    Baseline 41 (1920, 1080) 30 50
    Main 30 (720, 480) 30 10
    Main 31 (1280, 720) 30 14
    Main 32 (1280, 1024) 30 20
    Main 41 (1920, 1080) 30 50
    High 40 (1920, 1080) 30 25
    High 41 (1920, 1080) 30 62.5

    码率、fps、分辨对清晰度及流畅度的影响

    对于码率(BitRate)、FPS(frame per second)、分辨率(VideoSize)三者的关系,有必要在这里做一些说明,以便你根据自己产品的需要可以有的放矢的调节各个参数。

    一个视频流个人的感受一般来说会有卡顿、模糊等消极的情况,虽然我们都不愿意接受消极情况的出现,但是在 UGC 甚至 PGC 的直播场景中,都不可避免的要面对。因为直播推流实时性很强烈,所以为了保证这一实时性,在网络带宽不足或者上行速度不佳的情况下,都需要做出选择。

    要么选择更好的流程度但牺牲清晰度(模糊),要么选择更好的清晰度但牺牲流畅度(卡顿),这一层的选择大多由产品决定。

    一般来说,当选定了一个分辨率后,推流过程中就不会对分辨率做变更,但可以对码率和 FPS 做出调节,从而达到上述两种情况的选择。

    效果 码率 FPS
    流畅度 负相关 正相关
    清晰度 正相关 负相关

    通过这个关联,我们就可以容易的知道该如何从技术层面做出调整。在追求更好的流畅度时,我们可以适当降低码率,如果 FPS 已经较高(如 30)时,可以维持 FPS 不变更,如果此时因为码率太低而画面无法接受,可以再适当调低 FPS;在追求更清晰的画质时,可以提高码率,FPS 调节至 24 左右人眼大多还会识别为流畅,如果可以接受有轻微卡顿,那么可以将 FPS 设置的更低,比如 20 甚至 15。

    总之,这三者之间一起构建其了画面清晰和视频流畅的感觉,但最终参数是否能满意需要自己不断调整和调优,从而满足产品层面的需求。

    5.1.4 音频编码参数

    相比于视频繁杂的参数,当前 PLAudioStreamingConfiguration 可配置的参数较为简单,目前提供音频码率和编码器的配置,音频编码可选择 AAC-LC 或者 HE-AAC。

    各 Quality 的对比:

    Quality Audio BitRate(Kbps)
    kPLAudioStreamingQualityHigh1 64
    kPLAudioStreamingQualityHigh2 96
    kPLAudioStreamingQualityHigh3 128

    5.1.5 切换视频配置

    为了满足推流中因网络变更,网络拥塞等情况下对码率、FPS 等参数的调节,PLMediaStreamingSession 提供了重置编码参数的方法,因为在重置编码器时会重新发送编码参数信息,可能触发播放器重置解码器或者清除缓存的操作(依据播放器自身行为而定),所以推流中切换编码参数时,观看短可能出现短暂(但视觉可感知)的卡顿。因此建议不要频繁的切换编码参数,避免因此带来的播放端体验问题。

    • 在推流前、推流中、推流结束后调用 - (void)reloadVideoStreamingConfiguration:(PLVideoStreamingConfiguration *)videoStreamingConfiguration; 来重置 configuration

    需要注意的是,通过 reload 方法重置 configuration 时,需要确保传递的 configuration 与当前 session 已经持有的不是一个对象。

    5.1.6 建议编码参数

    提示:以下为建议值,可根据产品需求自行更改调节。

    UGC 场景,因为主播方所在的网络环境参差不齐,所以不易将码率设置的过高,此处我们给出建议设定

    • WiFi: video Medium2 或者自定义编码参数时设定码率为 600~800Kbps
    • 3G/4G: video Medium1 或者自定义编码参数时设定码率为 400~600Kbps

    PGC 场景,因为主播方所在网络一般都会有较高的要求,并且主播网络质量大多可以保障带宽充足,此处我们给出建议设定

    • WiFi: video High1 或者自定义编码参数时设定码率为 1000~1200Kbps
    • 3G/4G: video Medium2 或者自定义编码参数时设定码率为 600~800Kbps

    对于 PGC 中的 3G/4G 场景,假定 PGC 时会配备较好的外置热点保证上行带宽充足。

    5.1.7 如何只推音频

    当你只需要推送音频时,并不需要额外的增加代码,只需要在创建 PLMediaStreamingSession 时,只传入 PLAudioStreamingConfigurationPLAudioCaptureConfiguration 对象即可,这样 PLMediaStreamingSession 就不会在内部创建视频采集和编码的相关内容,推流时也只会发音频配置信息和音频数据。

    5.1.8 返听

    返听又被称之为耳返,指声音通过主播的麦克风被录入之后,立即从主播的耳机中播出来。返听功能如果搭配音效功能一起使用,可以让主播听到经音效处理后(如加入混响效果)的自己的声音,会有一种独特感觉。

    返听功能可通过 PLMediaStreamingSessionplayback 属性进行开启或关闭。注意,只有在推流进行时,返听功能才会起作用。因为只有开始推流之后,SDK 才会打开麦克风并开始录音。

    此外,建议通过业务逻辑禁止主播在没有插上耳机的情况下使用返听功能。虽然 SDK 允许用户即便没有插入耳机却照样可以开启返听,但那并不意味着我们建议你这么做。因为在 iPhone 没有接入耳机的时候开启返听,iPhone 的麦克风录入的声音会从 iPhone 的扬声器中立即播放出来,从而再次被麦克风录入,如此反复几秒后将变成尖锐的电流音。想象一下你在 KTV 把话筒凑到音响附近后听到的令人不快的刺耳声音吧。因此,我们强烈建议开发者在业务逻辑层进行判定,当主播开启返听功能时,如果拔掉耳机, 请将 playback 属性设为 NO 以关闭返听功能。

    5.1.9 音效

    SDK 内置的音效模块会对主播通过麦克风录入的声音进行处理,从而让人听起来有不一样的感觉。例如加入 “回声” 音效后,主播的声音听起来就好像置身于空旷的讲堂一般;加入 “混响” 音效后,主播的声音听起来则更浑厚有力。

    音效会影响返听功能,经过音效处理后的声音将被主播自己的耳机播放,音响产生的效果也会被推流出去,从而被观众听到。

    SDK 的音效功能是对 iOS 的 Audio Unit 进行的封装,使开发者可以抽身于 Audio Unit 复杂的 API 泥潭。音效的添加、修改、删除都可以通过操作下面这个属性进行:

    @property (nonatomic, strong) NSArray<PLAudioEffectConfiguration *> *audioEffectConfigurations;
    

    这是一个由 PLAudioEffectConfiguration 对象构成的数组,每一个 PLAudioEffectConfiguration 对象对应一种音效。如果你需要同时开启多个音效,只需像如下示例把它们全部放在一个数组中即可:

    mediaStreamingSession.audioEffectConfigurations = @[effect0, effect1, effect2, ...];
    

    如果你想删除某个音效,只需要重新构造一个数组,令它唯独不包含那个你想要删除的音效,然后再重新赋值该属性即可。如果你想关闭音效功能,只需要设置一个空数组,或设置 nil 即可。注意,对音效的操作是立即生效的,不需要重启推流。

    构成数组的元素必须是 PLAudioEffectConfiguration 对象或它的子类的对象。SDK 提供了众多的配置对象供你选择,这些配置对象全部都是 PLAudioEffectConfiguration 的子类对象。每一种配置对象往往对应一种 kAudioUnitType_Effect 类型的 Audio Unit。如果你熟悉 Audio Unit,你会发现每一种 kAudioUnitType_Effect 的子类型,SDK 中都有一种配置类与之对应。 例如,sub type 为 kAudioUnitSubType_Reverb2 的 Audio Unit 在 SDK 中对应的配置类为 PLAudioEffectReverb2Configuration。而 Reverb2 的所有可使用的属性都可以在 PLAudioEffectReverb2Configuration 的成员变量中找到。你可以通过

    id effect = [PLAudioEffectReverb2Configuration defaultConfiguration];
    

    来构造一个所有成员变量都取默认值的配置对象。然后,通过类似

    ...
    
    effect.gain = 0.8; 
    effect.decayTimeAt0Hz = 1.2; 
    
    ...
    

    来设置构造好的配置对象的属性。

    至此,你应该已经明白了如何构造任何你想要的音效配置了。

    • 首先,你需要查找 Apple 的 Audio Unit 的 API 文档,在所有 type 为 kAudioUnitType_Effect 的 Audio Unit 中挑选一个 sub type,作为你想要的音效,然后根据 sub type 的名字找到 SDK 中对应的配置类。例如,在之前的例子中,sub type 为 kAudioUnitSubType_Reverb2,因此配置类的名字为 PLAudioEffectReverb2Configuration。
    • 之后调用 [PLAudioEffectXXXConfiguration defaultConfiguration] 来 构造一个全部属性为默认值的配置对象。
    • 调整属性的值,来得到你想要的音效效果。
    • 重复之前的步骤,直到构造出所有你需要的音效配置对象,并全部装入一个 数组。
    • 通过设置 mediaStreamingSession.audioEffectConfigurations = @[...]; 来让你之前准备的音效配置生效。

    除了与 Audio Unit 一一对应的音效配置类,我们还提供了预设的音效类,PLAudioEffectModeConfiguration。你可以通过如下三个方法获取三种预设混响音效配置

    [PLAudioEffectModeConfiguration reverbLowLevelModeConfiguration];
    
    [PLAudioEffectModeConfiguration reverbMediumLevelModeConfiguration];
    
    [PLAudioEffectModeConfiguration reverbHeightLevelModeConfiguration];
    

    mediaStreamingSession.audioEffectConfigurations 这个数组里的音效配置对象是有顺序的,这个顺序最终将和 Audio Unit 在 AUGraph 中的顺序保持一致。如果你不了解 Audio Unit 在 AUGraph 中的顺序对最终产生的音效有什么影响,其实也无妨,实际上你随意地将音频对象排列最终产生的效果用肉耳听起来差别也不大(若你有更高的追求,那么你需要理解这个顺序的意义)。

    5.1.10 混音

    当前版本的 SDK 允许主播在推流的同时,播放本地音频文件。主播麦克风录入的声音,在经过音效处理(如果有)后,会与音频文件的内容混合,然后推流出去让观众听到。同时,如果主播开启了返听功能,亦可以从耳机听到音频文件播放出的声音。

    场景举例:直播中,主播唱歌,通过播放音频文件来获得伴奏。结合返听功能,主播可以从耳机听到伴奏音乐以及自己的唱出的歌声。同时观众最终听到的也是混合了伴奏的主播的歌声。

    要开启音频文件播放功能,首先需要构造播放器实例,通过如下方法构造

    PLAudioPlayer *player = [mediaStreamingSession audioPlayerWithFilePath:@"audio file path"];
    

    之后,所有与音频文件播放相关的功能就都基于 player 进行了。

    当你播放完音频文件之后,且不打算再使用该功能时,需要释放掉 player,可通过调用

    [mediaStreamingSession closeCurrentAudio];
    

    来释放之前获取的播放器实例。

    注意:播放器使用完必须关闭,否则它将一直占用着资源(例如音频文件的句柄)。

    每当音频文件播放完毕,会回调如下方法询问你是否把该音频文件重新播放一遍

    - (BOOL)didAudioFilePlayingFinishedAndShouldAudioPlayerPlayAgain:(PLAudioPlayer *)audioPlayer
    

    该方法可以让你知道音频文件什么时候播放完毕,同时通过返回一个 BOOL 值,来控制播放器的行为。例如,如果你想做单曲循环效果,可以如此实现该方法

    - (BOOL)didAudioFilePlayingFinishedAndShouldAudioPlayerPlayAgain:(PLAudioPlayer *)audioPlayer {
        return YES; 
    }
    

    如果你想实现顺序播放效果,可以如此实现该方法

    - (BOOL)didAudioFilePlayingFinishedAndShouldAudioPlayerPlayAgain:(PLAudioPlayer *)audioPlayer {
        audioPlayer.audioFilePath = @"/path/to/next/audio/file/name.mp3";
        return YES; 
    }
    

    5.2 DNS 优化

    在大陆一些地区或特别的运营商线路,存在较为普遍的 DNS 劫持问题,而这对于依赖 DNS 解析 rtmp 流地址的 PLMediaStreamingKit 来说是很糟糕的情况,为了解决这一问题,我们引入了 HappyDNS 这个库,以便可以实现 httpDNS,localDNS 等方式解决这类问题。

    5.2.1 HappyDNS

    你可以点击这里 跳转到 HappyDNS 的 GitHub 主页,在那里查看更详细的介绍和使用。

    默认情况下,你所创建的 PLMediaStreamingSession 对象,内部持有一个 HappyDNS 对应的 manager 对象,来负责处理 DNS 解析。

    如果你期望按照不同的规则来做 DNS 解析,那么你可以在创建 PLMediaStreamingSession 前,创建好自己的 QNDnsManager 对象,我们在 PLMediaStreamingSession 中提供了一个 init 方法满足这类需求,你可以传递自己的 QNDnsManager 对象给 PLMediaStreamingSession,从而定制化 DNS 解析。

    5.3 流状态获取

    PLMediaStreamingKit 中,通过反馈 PLMediaStreamingSession 的状态来反馈流的状态。我们定义了几种状态,确保 PLMediaStreamingSession 对象在有限的几个状态间切换,并可以较好的反应流的状态。

    状态名 含义
    PLStreamStateUnknow 初始化时指定的状态,不会有任何状态会跳转到这一状态
    PLStreamStateConnecting RTMP 流链接中的状态
    PLStreamStateConnected RTMP 已连接成功时的状态
    PLStreamStateDisconnecting RTMP 正常断开时,正在断开的状态
    PLStreamStateDisconnected RTMP 正常断开时,已断开的状态
    PLStreamStateAutoReconnecting 正在等待自动重连状态
    PLStreamStateError 因非正常原因导致 RTMP 流断开,如包发送失败、流校验失败等

    5.3.1 state 状态回调

    state 状态对应的 Delegate 回调方法是

    - (void)mediaStreamingSession:(PLMediaStreamingSession *)session streamStateDidChange:(PLStreamState)state;
    

    只有在正常连接,正常断开的情况下跳转的状态才会触发这一回调。所谓正常连接是指通过调用 -startStreamingWithFeedback: 方法使得流连接的各种状态,而所谓正常断开是指调用 -stopStreaming 方法使得流断开的各种状态。所以只有以下四种状态会触发这一回调方法。

    • PLStreamStateConnecting
    • PLStreamStateConnected
    • PLStreamStateDisconnecting
    • PLStreamStateDisconnected

    5.3.2 error 状态回调

    error 状态对应的 Delegate 回调方法是

    - (void)mediaStreamingSession:(PLMediaStreamingSession *)session didDisconnectWithError:(NSError *)error;
    

    除了调用 -stopStreaming 之外的所有导致流断开的情况,都被归属于非正常断开的情况,此时就会触发该回调。对于错误的处理,我们不建议触发了一次 error 后就停掉,最好可以在此时尝试有限次数的重连,详见重连小节。

    5.3.3 status 状态回调

    除了 state 作为流本身状态的切换,我们还提供了流实时情况的反馈接口

    - (void)mediaStreamingSession:(PLMediaStreamingSession *)session streamStatusDidUpdate:(PLStreamStatus *)status;
    

    默认情况下,该回调每隔 3s 调用一次,每次包含了这 3s 内音视频的 fps 和总共的码率(注意单位是 kbps)。你可以通过 PLMediaStreamingSession 的 statusUpdateInterval 属性来读取或更改这个回调的间隔。

    5.3.4 产品层面的反馈

    status 的状态回调可以很好的反应发送情况,及网络是否流畅,是否拥塞。所以此处可以作为产品层面对弱网情况决策的一个入口。

    一般的,当 status.videoFPS 比预设的 FPS 明显小时(小于等于 20%),并且维持几秒都是如此,那么就可以判定为当前主播所在的网络为弱网环境,可以给主播视觉上的提示,或者主动降低编码配置,甚至直接断掉主播的流,这些都由具体的产品需求而定,而此处只是给出一个入口的提示和建议。

    5.4 网络异常处理

    直播中,网络异常的情况比我们能意料到的可能会多不少,常见的情况一般有

    • 网络环境切换,比如 3G/4G 与 Wi-Fi 环境切换
    • 网络不可达,网络断开属于这一类
    • 带宽不足,可能触发发送失败
    • 上行链路不佳,直接影响流发送速度

    作为开发者我们不能乐观的认为只要是 Wi-Fi 网就是好的,因为即便是 Wi-Fi 也有可能因为运营商上行限制,共享网络带宽等因素导致以上网络异常情况的出现。

    为何在直播中要面对这么多的网络异常情况,而在其他上传/下载中很少遇到的,这是因为直播对实时性的要求使得它不得面对这一情况,即无论网络是否抖动,是否能一直良好,直播都要尽可能是可持续,可观看的状态。

    5.4.1 重连

    PLMediaStreamingSession 内置了自动重连功能,但默认处于关闭状态。之所以默认关闭,一方面是考虑到 App 的业务逻辑场景多样而负责,对于直播重连的次数、时机、间隔都会有不同的需求,此时让开发者自己来决定是否重连,以及尝试重连的次数会更加合理;另一方面是兼容旧版本业务层面可能已实现的自动重连逻辑。

    如果你想直接使用内置的自动重连功能,可通过将 PLMediaStreamingSessionautoReconnectEnable 属性设置为 YES 来开启,并需要注意如下几点:

    • 自动重连次数上限目前设定为 3 次,重连的等待时间会由首次的 0~2s 之间逐步递增到第三次的 4~6s 之间
    • 等待重连期间,streamState 处于 PLStreamStateAutoReconnecting 状态,业务层可根据该状态来更新用户界面
    • 网络异常的 error Delegate 回调只有在达到最大重连次数后还未连接成功时才会被触发

    若你想自己实现自动重连逻辑,可以利用以下网络异常所触发的 error Delegate 回调接口来添加相应的逻辑:

    - (void)mediaStreamingSession:(PLMediaStreamingSession *)session didDisconnectWithError:(NSError *)error;
    

    你可以在这个方法内通过重新调用 -startStreamingWithFeedback: 方法来尝试重连。此处建议不要立即重连,而是采用重连间隔加倍的方式,比如共尝试 3 次重连,第一次等待 0.5s, 第二次等待 1s, 第三次等待 2s,这样的方式主要考虑到弱网时网络带宽的缓解需要时间,而加倍重连可以更容易在网络恢复的时候连接,而非在网络已经拥塞时还不断做无用功的重连。

    PLMediaStreamingSession 内置了网络切换监测功能,但默认处于关闭状态。开启后,网络在 WWAN(3G/4G) 和 Wi-Fi 之间相互切换时,我们提供了一个回调 connectionChangeActionCallback 属性,它的函数签名如下

    typedef BOOL(^ConnectionChangeActionCallback)(PLNetworkStateTransition transition);
    

    该回调函数传入参数为当前网络的切换状态 PLNetworkStateTransition。 返回值为布尔值,YES表示在某种切换状态下允许推流自动重启,NO则代表该状态下不应自动重启。例如在 PLNetworkStateTransitionWWANToWiFi 状态,即网络从 3G/4G 切换到 Wi-Fi 后,基于节省流量等需求考虑,你可能需要进行一次快速的重连,使得数据可以通过 Wi-Fi 网络发送,此时返回 YES 即可。反之,如果推流过程中 Wi-Fi 断掉切换到 3G/4G,此时在未征得用户同意使用移动流量推流时,可返回 NO 不自动重启推流。以下为参考逻辑

    session.connectionChangeActionCallback = ^(PLNetworkStateTransition transition) {
            switch (transition) {
                case PLNetworkStateTransitionWWANToWiFi:
                    return YES;
    
                case PLNetworkStateTransitionWiFiToWWAN:
                    return NO;
    
                default:
                    break;
            }
    
            return NO;
        };
    

    如果该属性未被初始化赋值,则 SDK 内部出于节省用户移动网络流量的目的,会默认在 Wi-Fi 切换到 3G/4G 时断开推流。此时,你可以自行监听网络状态,调用 -restartStreamingWithFeedback: 方法来快速重连。

    5.4.2 弱网优化

    移动直播过程中存在着各种各样的网络挑战。由于无线网络相对于有线网络,可靠性较低,会经常遇到信号覆盖不佳导致的高丢包、高延时等问题,特别是在用网高峰期,由于带宽有限,网络拥塞的情况时有发生。自 v2.1.3 起,PLMediaStreamingKit 内置了一套弱网优化方案,可以满足以下两个诉求:

    • 能动态地适应网络质量,即在质量不佳的网络下,能够自动下调视频编码的输出码率和帧率,而当网络质量恢复稳定时,输出码率和帧率也应得到相应回升,并能在调节过程中使得码率与帧率变化相对平稳。
    • 在直播端网络质量稳定时,确保编码器输出的码率和帧率恒定在一个期望的最高值,以提供良好的清晰度和流畅度。

    这套弱网优化方案包含两个工作模块:

    • 自适应码率模块,能够在期望码率与设定的最低码率间做出调节,适应网络抖动引发的数据带宽变化。
    • 动态帧率模块,能够在期望帧率与一个最低帧率间做出调节,动态调整输出的视频数据量。

    这两个模块可并行工作,可以单独开启或关闭,开发者可根据自己的业务场景来决定该方案的应用形态。一般情况下,如果开发者想使用该解决方案,建议将两个调节模块都开启,可达到我们测试的最佳效果。利用码率与帧率调整相互配合作用,一方面有效控制网络波动情况下的音视频数据发送量,缓解网络拥塞,同时又能给播放端带来流畅的观看体验;另一方面在网络质量恢复时能够确保音视频的码率帧率是以设定的最优质量配置进行推流,并且能使不同码率帧率配置切换时以一种更为平滑的方式进行,不会给观看端带来画质波动的突兀感。

    自适应码率调节可以通过 PLMediaStreamingSession 的如下接口开启:

    - (void)enableAdaptiveBitrateControlWithMinVideoBitRate:(NSUInteger)minVideoBitRate;
    

    其关闭接口为:

    - (void)disableAdaptiveBitrateControl;
    

    开启该机制时,需设置允许向下调节的最低码率(注意其单位为 bps,如设置最低为 200 Kbps,应传入参数值为 200*1024),以便使自动调整后的码率不会低于该范围。该机制根据网络吞吐量及 TCP 发送时间来调节推流的码率,在网络带宽变小导致发送缓冲区数据持续增长时,SDK 内部将适当降低推流码率,若情况得不到改善,则会重复该过程直至平均码率降至用户设置的最低值;反之,当一段时间内网络带宽充裕,SDK 将适当增加推流码率,直至达到预设的推流码率。

    动态帧率的开关为 PLMediaStreamingSessiondynamicFrameEnable 属性,开启后,自动调整的最大帧率不会超过预设在 videoStreamingConfiguration 配置中的 expectedSourceVideoFrameRate,最低不会小于 10 FPS。

    默认情况下,这两个模块处于关闭状态,是为了兼容旧版本中开发者可能已自行实现的弱网调节机制。若开发者想使用我们的内置方案,请确保您自定义的机制已被关闭。

    5.5 水印和美颜

    5.5.1 水印

    PLMediaStreamingKit 支持内置水印功能,你可以根据自己的需要添加水印或移除水印,并且能够自由设置水印的大小和位置。需要注意的是水印功能对预览和直播流均生效。

    添加水印

    -(void)setWaterMarkWithImage:(UIImage *)wateMarkImage position:(CGPoint)position;
    

    该方法将为直播流添加一个水印,水印的大小由 wateMarkImage 的大小决定,位置由 position 决定,需要注意的是这些值都是以采集数据的像素点为单位的。例如我们使用 AVCaptureSessionPreset1280x720 进行采集,同时 wateMarkImage.size(100, 100) 对应的 origin(200, 300),那么水印的位置将在大小为 1280x720 的采集画幅中位于 (200, 300) 的位置,大小为 (100, 100)

    移除水印

    -(void)clearWaterMark;
    

    该方法用于移除已添加的水印

    5.5.2 美颜

    'PLMediaStreamingSession' 支持内置美颜功能,你可以根据自己的需要选择开关美颜功能,并且能够自由调节包括美颜,美白,红润等在内的参数。需要注意的是水印功能对预览和直播流均生效。

    按照默认参数开启或关闭美颜

    -(void)setBeautifyModeOn:(BOOL)beautifyModeOn;
    

    设置美颜程度,范围为 0 ~ 1

    -(void)setBeautify:(CGFloat)beautify;
    

    设置美白程度,范围为 0 ~ 1

    -(void)setWhiten:(CGFloat)whiten;
    

    设置红润程度,范围为 0 ~ 1

    -(void)setRedden:(CGFloat)redden;
    

    5.6 后台推图片

    App 一旦切到后台,摄像头的采集功能会被系统暂停掉,观众会看到主播的画面会卡住,此时如果能推送一张图片告诉观众主播进入后台了,将带来更好的观看体验。具体实现方法如下:开发者需要自行监听 App 进入后台/前台的通知,当App 进入后台时,使用 PLMediaStreamingSession 的如下接口

    - (void)setPushImage:(nullable UIImage *)image;
    

    设置一张推流图片,PLMediaStreamingSession 会持续为您推送该图片,当 App 返回前台不再需要推送图片时,重新调用以上接口并传入 nil 即可。

    6 知识补充与建议

    6.1 丢帧策略

    这一章节,我们谈谈丢帧策略,这关乎最终的直播观看体验,这里我们主要说明为何需要它,以及它带来的利弊。

    6.1.1 丢帧策略的必要性

    我想可能没有人会喜欢在直播中出现丢帧,但是为何我们一定要实现并提供它呢?这是我们在最初提供出丢帧策略时也在反复考虑和一再讨论过的一个问题。

    原因很简单,为了保证直播的实时性。

    直播作为有别于录播的富媒体传播手段,它的第一要素就是实时,没有了实时,直播的价值就会荡然无存。保证实时性就需要确保录制端的数据尽可能少的累积,尽可能快的发送,但如果没有丢帧策略,在弱网环境下,就会因为待发送数据的不断堆积而产生累计延时,最终带来延时越来越大的情况。作为推流的发起端和推送端,推流 SDK 要考虑的还不单单是实时性这一点,因为移动设备的内存有限,而视频数据对内存的占用较大,所以在推流时还要确保不会因为待发送数据堆积过多而带来内存吃紧,触发 crash 等严重问题。所以我们需要也一定要在推流端提供丢帧策略。

    丢帧的方式可以有很多种,其中有些较为粗暴,会触发各类问题,比如花屏,爆音,音画不同步等问题,在反复尝试和验证了各类的丢帧策略后,我们最终选定了优先保证音频传输且不触发花屏、爆音、音画不同步问题的技术方案。这一方案可以保证在带宽不足或上行速度不佳时,优先丢弃视频帧,保证音频的持续传输,在观看端至多出现画面跳帧的情况,但声音会是连续的片段,体验上不会认为是推流端断网,确保直播的继续进行。

    6.1.2 利弊

    丢帧策略固然保证了直播的实时性和推流端相对的稳定性,但是它的弊端也是显然的,就是会带来观看端体验的不佳。

    面对并接受这一弊端是必要,这样才可以做出更好的产品决策,我们建议从产品层面至少需要考虑两点

    • 在主播弱网情况下,观看端体验要保证流畅度优先还是清晰度优先
    • 在主播弱网情况下,尽可能让主播自己知晓自己网络不佳这一事实

    对于流畅度和清晰度的问题,可以参考码率、fps、分辨对清晰度及流畅度的影响这一小节。

    7 API参考

    8 历史记录

    • 2.2.4 (Release Notes && API Diffs)

      • 缺陷
        • 修复 iOS 11 设备上预览启动慢的问题
        • 修复 iPhone X 设备上出现的 crash 问题
    • 2.2.3 (Release Notes && API Diffs)

      • 缺陷
        • 修复频繁设置 pushImage 内存未释放的问题
        • 修复在 iOS 8.1 设备上预览画面卡住的问题
        • 修复 VideoToolbox 编码方式下特定分辨率裁剪未居中的问题
        • 修复推流超过 4.5 小时掉线的问题
        • 修复 Xcode 9 下编译报错的问题
    • 2.2.1 (Release Notes && API Diffs)

      • 功能
        • 支持后台推静态图的功能
      • 缺陷
        • 修复 iOS 8.1 使用 VideoToolbox 编码失败的问题
        • 修复 iOS 9 及以上系统当 App 进入 Inactive 状态时推流画面卡住的问题
    • 2.2.0 (Release Notes && API Diffs)

      • 功能
        • 音频采集支持回声消除功能
        • 支持 HE-AAC 音频编码
      • 缺陷
        • 修复推流可能出现的内存泄露问题
        • 修复横屏推流镜像功能失效的问题
        • 修复特殊场景下偶现的崩溃
    • 2.1.6 (Release Notes && API Diffs)

      • 功能
        • 支持苹果 ATS 安全标准
        • PLMediaStreamingSession 增加外部传入 QNDnsManager 的接口
      • 缺陷
        • 修复设置音效后内存泄漏的问题
        • 修复设置推流镜像时预览画面会闪一下的问题
      • 其它
        • 废弃 PLCameraStreamingSession,请使用 PLMediaStreamingSession
    • 2.1.5 (Release Notes && API Diffs)

      • 缺陷
        • 修复推流预览在 app 退至后台一段时间后再返回前台时,有概率会卡住问题
        • 修复开启 VideoToolbox 编码时,退至后台再返回前台时,编码数据无法输出问题
    • 2.1.4 (Release Notes && API Diffs)

      • 功能
        • 增加对 iOS 10 ReplayKit 录屏推流的支持
        • 增加 VideoToolbox 视频硬件编码功能
        • 增加人工报障和自动报障功能
      • 缺陷
        • 修复 iPhone 6s 及以上机型在 iOS 10 上的电流音问题
        • 修复 iPhone 6 及以上机型在 iOS 10 上同时开启自动对焦和手动对焦功能时,手动对焦失效问题
      • 优化
        • 优化 RGB 转 YUV 的效率,去除对 libyuv 库的依赖
    • 2.1.3 (Release Notes && API Diffs)
      • 缺陷
        • 解决 iPhone 4s 及以下会 crash 的问题
    • 2.1.2 (Release Notes && API Diffs)
      • 功能
        • 增加截屏功能
        • 增加自动网络检测功能
        • 增加自适应码率功能
        • 增加动态帧率功能
      • 缺陷
        • 修复音频未授权时 crash 的问题
        • 修复所有已知 crash
        • 修复前置摄像头无法缩放的问题
      • 优化
        • 优化不开美颜和水印时的性能
    • 2.1.1 (Release Notes && API Diffs)
      • 缺陷
        • 修复与 PLPlayerKit v2.2.3 符号冲突的问题
    • 2.1.0 (Release Notes && API Diffs)
      • 功能
        • 新增返听功能
        • 新增内置音效功能,支持十余种音效与数十个参数自由调节
        • 新增内置音频文件播放及混音推流功能
        • 新增外部视频图像处理本地预览功能
      • 缺陷
        • 修复分享到微博和 qq 空间时可能出现的卡 UI 的问题
        • 修复在流未连接的状态调用 restart 方法会出现只有视频没有声音的问题
        • 修复初始化时自动对焦不生效的问题
        • 修复一些偶发的 crash 问题
    • 2.0.0 (Release Notes && API Diffs)
      • 功能
        • 提供 PLCameraStreamingKit 和 PLStreamingKit 两个层次的 API
        • 支持直接传入 stream URL 进行推流
        • 提供推流节点调度功能
        • 支持音频数据回调及处理功能
      • 缺陷
        • 修复orientation 在切换摄像头之后不起作用的问题
        • 修复初始化之后 inputGain 获取到的值始终为 0 的问题
        • 修复多种原因导致的死锁问题
        • 修复弱网推流可能出现的内存泄露问题
        • 修复特殊机器状态可能出现的 crash 问题
      • 优化
        • 优化对设备采样率的适配,推流过程中设备采样率变更将不再重新开始推流
    • 1.8.1 (Release Notes && API Diffs)
      • 功能
        • 更新依赖的 PLStreamingKit 到 1.2.5
        • 新增自动重连功能,默认关闭
        • 新增模拟器编译支持
        • 水印和美颜功能调整为支持 iPhone 5、iPad 3、iPod touch 4 及以上设备
      • 缺陷
        • 修复已知场景可能存在的没有声音的问题
        • 修复填充模式改变可能导致 preview 的 frame 发生改变的问题
        • 修复触摸屏幕对焦无效的问题
        • 修复无法正确设置采集相机位置的问题
        • 修复 capture session 设置不正确可能导致 crash 的问题
        • 修复偶尔出现的画面卡住无法正常推流的问题
    • 1.8.0 (Release Notes && API Diffs)
    • 功能
      • 更新依赖的 PLStreamingKit 到 1.2.4
      • 新增内置美颜功能,美颜效果可调节
      • 新增单独调节前后置摄像头预览及推流是否镜像的接口
      • 新增动态帧率功能,通过降低采集帧率来适配弱网环境
    • 缺陷
      • 修复音视频时间戳偶尔出现的非单调递增的缺陷
      • 修复特殊机型可能出现的没有声音的问题
    • 优化
      • 优化水印性能,降低 CPU 和内存消耗
    • 1.7.2 (Release Notes && API Diffs)
      • 功能
        • 更新依赖的 PLStreamingKit 到 1.2.2
        • 新增回调队列配置功能
        • 新增默认摄像头位置配置项
        • 新增录制音量调节选项(由于系统原因,仅对除 iPhone 6s 系列以外的机型生效)
        • 支持初始化的时候传入 stream 为 nil
        • 支持快速重连操作,方便 4G 推流时切换 WIFI 场景快速切换网络
      • 缺陷
        • 修复特殊场景可能出现的电流音问题
        • 修复特殊场景可能出现的没有声音的问题
        • 修复后台推流时被音频打断结束之后无法正常恢复推流的问题
    • 1.7.1 (Release Notes && API Diffs)
      • 缺陷
        • 修复切换前置摄像头之后无法缩放的问题
        • 修复不添加水印无法正常推流的问题
    • 1.7.0 (Release Notes && API Diffs)
      • 功能
        • 新增后台推流功能(仅音频,因 iOS 隐私限制不允许后台访问摄像头)
        • 新增水印功能
        • 新增可选定制美颜功能(需联系工作人员)
      • 缺陷
        • 修复特定机型上的电流音等杂音问题
      • 版本
        • 更新依赖 PLStreamingKit 的版本到 v1.2.0
      • 其他
        • 部分接口重命名
    • 1.6.3 (Release Notes && API Diffs)
      • 更新依赖 PLStreamingKit 的版本到 v1.1.6
      • 更新 Demo 适应 PLStreamingKit v1.1.6 接口变更
    • 1.6.2 (Release Notes && API Diffs)
      • 更新依赖 PLStreamingKit 的版本到 v1.1.5
      • 支持 Zoom 操作
    • 1.6.1 (Release Notes && API Diffs)
      • 更新依赖 PLStreamingKit 的版本到 v1.1.3
      • 修复调用 - (void)reloadVideoConfiguraiton 方法,fps 变更失败的问题
    • 1.6.0 (Release Notes && API Diffs)
      • 更新依赖 PLStreamingKit 的版本到 v1.1.2
      • 添加 PLStreamStatus 回调,便于客户端监控推流状态
      • 修复采集源 fps 变更失败的问题
    • 1.5.2 (Release Notes && API Diffs)
      • 更新依赖 PLStreamingKit 的版本到 v1.0.3
    • 1.5.1 (Release Notes && API Diffs)
      • 更新依赖 PLStreamingKit 的版本到 v1.0.2
      • 更改音频数据源采集部分,转换为单声道
    • 1.5.0 (Release Notes && API Diffs)
      • 编码推流改为依赖 PLStreamingKit
      • 去除 PLAudioStreamingSession 类, 建议单纯推音频的 App 直接接入 PLStreamingKit
      • 摄像头及音频采集部分开源
      • 底层添加了 HappyDNS, 解决部分地区 DNS 感染严重导致推流失败问题
      • 优化 TCP 层发包,极大程度解决了网络正常但推流中经常断开的问题
    • 1.4.16 (Release Notes && API Diffs)
      • 解决 destroy 方法可能卡死线程的问题
    • 1.4.15 (Release Notes && API Diffs)
      • 修复类库 .a 未更新问题
    • 1.4.14 (Release Notes && API Diffs)
      • 解决视频质量切换时导致 crash 的问题
      • 解决推流时触发的只有音频无视频问题
      • 解决音频采样导致的电流声
      • 解决潜在内存问题,整体提升稳定性
      • 视频编码统一 profileLevel 为 baseline31
      • 限定最高支持分辨率到 720p
    • 1.4.13 (Release Notes && API Diffs)
      • 更新 mute 行为,mute 后不会中断发包
      • 更新音频设备采样率获取途径
      • 更新底层库,避免冲突
    • 1.4.12 (Release Notes && API Diffs)
      • 添加 smoothAutoFocusEnabled 参数,确保拍摄时对焦的平滑过渡
      • 修复无网络环境或其他情况触发断流时引起的 crash
      • 修复频繁切换摄像头时引起的 crash
      • 修复内存 leak
    • 1.4.11 (Release Notes && API Diffs)
      • 修复 iPhone 6s 系列机型直播无声音问题
    • 1.4.10 (Release Notes && API Diffs)
      • 修复错误重连或者主动重连时导致 UI 卡顿的问题
    • 1.4.9 (Release Notes && API Diffs)
      • 尝试修复 iPhone 6s 音频获取不到权限的问题
      • 优化丢包策略,兼顾高延时和低带宽的情况
      • 更新 demo 为全异步请求
    • 1.4.8 (Release Notes && API Diffs)
      • 尝试修复 iPhone 6s 音频获取不到权限的问题
      • 修复弱网环境触发的内存和 CPU 占用升高的问题
    • 1.4.7 (Release Notes && API Diffs)
      • 尝试修复音频获取不到权限的问题
      • 添加关闭 SDK 渲染 preview 的接口
    • 1.4.6 (Release Notes && API Diffs)
      • 修复弱网环境下切换 VideoQuality 可能触发的 crash 问题
      • 添加 PLAudioComponentFailedToCreateNotification 通知,在音频资源被占用时,创建音频结构失败会发送这个通知
    • 1.4.5 (Release Notes && API Diffs)
      • 添加自行绘制 CMSampleBufferRef 的支持
    • 1.4.4 (Release Notes && API Diffs)
      • 为 PLCameraStreamingSession 多个属性添加 kvo 支持
      • 由时间计数改为包数计数
      • 针对弱网坏境更改丢帧策略,确保不会出现花屏和声音抖动,取而代之会出现间断的无数据,但是可以保证画面和声音的流畅
      • 发送队列的默认上下阈值更改为 0.3 和 0.7
    • 1.4.3 (Release Notes && API Diffs)
      • 优化网络层调用,添加 Disconnecting 流状态
      • 抽离可导致推流中断的错误
      • 添加错误回调,同时将错误信息返回,便于 debug 及异常处理
      • 修复 destroy 调用导致的崩溃问题
      • 支持 iOS 9 的 bitcode
    • 1.4.2 (Release Notes && API Diffs)
      • 添加 SendingBuffer 支持
      • 修复 iPhone 6s 下崩溃的问题
    • 1.4.1 (Release Notes && API Diffs)
      • 添加可以获取视频源数据的回调方法,便于开发者做滤镜等处理
      • 对自定义分辨率做了内部修正,保证宽高均为 16 倍数
    • 1.4.0 (Release Notes && API Diffs)
      • 添加音频推流的 PLAudioStreamingSession, 纯音频推流合并到 PLCameraStreamingKit
      • 添加后台推流支持,暂且只在纯音频推流中有效
    • 1.3.2 (Release Notes && API Diffs)
      • 修复直播被电话 / 闹钟中断后后续直播无声音的问题
      • 更改音频采集类型: RecordAndPlay -> Record
      • 添加对蓝牙音频设备的支持
    • 1.3.1 (Release Notes && API Diffs)
      • 修复调用 destroy 方法后,重新创建 session 进入后台触发的 crash 问题
      • 去除无用依赖, SDK 大小由 17 MB 降低为 4.7 MB
    • 1.3.0 (Release Notes && API Diffs)
      • 添加带宽质量检测机制,推流过程中可无缝切换音视频 Quality,实现码率及帧率的动态调节
      • 添加发送队列的配置及状态回调
      • 更新 Example 来简单说明如何使用发送队列和 Quality 组合推流策略
    • 1.2.8 (Release Notes && API Diffs)
      • 更新编码配置,分离音视频编码配置,便于提供更灵活的配置方案
      • 去除 SIGPIPE 断点
      • 修复 URL 错误时导致的崩溃
      • 修复创建 Session 后设置 Stream 推流失败的问题
    • 1.2.7 (Release Notes && API Diffs)
      • 修复断网后停止流时导致的 UI 卡死
      • 修复停止推流时概率出现的 crash 问题
      • 添加 - (void)destroy 方法到 PLCameraStreamingSession
      • 暂且去除 iOS 8 编码,待进一步优化后再做开放
      • 修复反复进出持有 streamingSession 的 viewController 出现 IO 错误或者 crash 的问题
    • 1.2.6 (Release Notes && API Diffs)
      • 修复 iOS 8 以下推流时,编码导致的崩溃问题
    • 1.2.5 (Release Notes && API Diffs)
      • 更新了 Quality 配置
    • 1.2.4 (Release Notes && API Diffs)
      • 添加全新的 iOS 8 硬编码器,减少编码延时
    • 1.2.3 (Release Notes && API Diffs)
      • 更新了 PLStream 类结构
      • 添加新的 session 创建接口
      • 移除 publishHost,PLStream 对象支持自动生成推流地址,请搭配服务端 SDK 至少 1.2.0 或以上版本使用
    • 1.2.2 (Release Notes && API Diffs)
      • 更新麦克风资源调用方式,添加进入后台后自动停用麦克风功能
    • 1.2.1 (Release Notes && API Diffs)
      • 修复初次授权摄像头后预览界面为黑屏的问题
    • 1.2.0 (Release Notes && API Diffs)
      • 添加了 PLStream 类,支持 Coding 协议便于打包存储
      • 更新 StreamingSession 创建方法,借助传递 PLStream 对象再无需推流时等待服务端生成推流地址
      • 完善 HeaderDoc 文档
    • 1.1.8 (Release Notes && API Diffs)
      • 添加摄像头开启和关闭的操作,便于开发者控制 AVCaptureSession
    • 1.1.7 (Release Notes && API Diffs)
      • 添加推流质量字段,方便开发者指定推流质量
      • 移除原配置中的网络选项
      • 默认情况下关闭了 PLLog
      • 添加摄像头开始运行的通知
      • 添加麦克风开始运行的通知
    • 1.1.6 (Release Notes && API Diffs)
      • 尝试修复音频变声问题
    • 1.1.5 (Release Notes && API Diffs)
      • 修复了重连后无法播放的问题
    • 1.1.4 (Release Notes && API Diffs)
      • 更新了码率和采样率。现在统一使用 128Kbps 和 44100KHZ,用以解决噪音的问题
      • 更新了网络 socket。对 socket 在调试情况下出现的 SIGPIPE 进行了处理,不会再出现
      • 更新了网络状态的返回情况。当不是主动调用 close 接口导致的断开都将以 error 状态通知 delegate
    • 1.1.3 (Release Notes && API Diffs)
      • 更新了获取视频截图的方法
      • 添加 HeaderDoc 格式注释文档
    • 1.1.2 (Release Notes && API Diffs)
      • 添加自定视频大小的编码配置
      • 添加进入后台后自动停止推流的支持
      • 添加保持常亮的开关
      • 添加获取当前录制截屏的功能
      • 修复进入后台导致崩溃的问题
      • 修复切换前置摄像头失效的问题
      • 添加 Release Notes 说明每个版本变动
      • 添加 API Diffs 说明具体修改细节
    • 1.1.1
      • 修复 release 版本无法推流的 bug
      • 内存优化,比 1.1.0 减少 6% 左右内存消耗
    • 1.1.0
      • 重构接口
      • 优化编码参数
      • 提供不同网络和分辨率下的多种配置可选
      • 添加消息通知,便于监听
      • 兼顾 arc 及非 arc 的工程
    • 1.0.0
      • 发布 CocoaPods 版本
    以上内容是否对您有帮助?
  • 提交工单