Skip to content
maverick edited this page Aug 18, 2016 · 14 revisions

#5 功能使用

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

##5.1 音视频采集和编码配置

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

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

配置生效的时刻有两个:

  • PLCameraStreamingSession init 时传递对应的 configuration
  • 在推流前、推流中、推流结束后调用

- (void)reloadVideoStreamingConfiguration:(PLVideoStreamingConfiguration *)videoStreamingConfiguration videoCaptureConfiguration:(PLVideoCaptureConfiguration *)videoCaptureConfiguration;

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

###5.1.1 视频采集参数

1.自定义视频采集参数

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

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

**注意:**指定分辨率的 sessionPreset(如:AVCaptureSessionPreset1920x1080),并非所有机型的摄像头都支持,在设置相应采集分辨率之前,请务必保证做过充分的机型适配测试。另外,如果使用只指定采集质量的 sessionPreset(如:AVCaptureSessionPresetMedium)时,系统会根据当前摄像头的支持情况使用相应质量等级的分辨率进行采集。

###5.1.2 音频采集参数

1.自定义音频采集参数

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

  • channelsPerFrame
    • 采集时的声道数

###5.1.3 视频编码参数

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

1.Quality 的对比

Quality FPS ProfileLevel Video BitRate(Kbps)
kPLVideoStreamingQualityLow1 12 Baseline 31 150
kPLVideoStreamingQualityLow2 15 Baseline 31 264
kPLVideoStreamingQualityLow3 15 Baseline 31 350
kPLVideoStreamingQualityMedium1 30 Baseline 31 512
kPLVideoStreamingQualityMedium2 30 Baseline 31 800
kPLVideoStreamingQualityMedium3 30 Baseline 31 1000
kPLVideoStreamingQualityHigh1 30 Baseline 31 1200
kPLVideoStreamingQualityHigh2 30 Baseline 31 1500
kPLVideoStreamingQualityHigh3 30 Baseline 31 2000

2.自定义编码参数

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

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

PLCameraStreamingKit 为了防止编码参数设定失败而导致编码失败,出现推流无视频的情况,依据 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

3.码率、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。

Quality 的对比:

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

###5.1.5 切换音视频配置

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

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

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

###5.1.6 建议编码参数

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

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

  • WiFi: video Medium1 或者自定义编码参数时设定码率为 400~500Kbps
  • 3G/4G: video Low2 或者自定义编码参数时设定码率为 200~300Kbps

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

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

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

###5.1.7 如何只推音频

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

##5.2 DNS 优化

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

###5.2.1 HappyDNS

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

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

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

##5.3 流状态获取

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

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

###5.3.1 state 状态回调

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

- (void)cameraStreamingSession:(PLCameraStreamingSession *)session streamStateDidChange:(PLStreamState)state;

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

  • PLStreamStateConnecting
  • PLStreamStateConnected
  • PLStreamStateDisconnecting
  • PLStreamStateDisconnected

###5.3.2 error 状态回调

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

- (void)cameraStreamingSession:(PLCameraStreamingSession *)session didDisconnectWithError:(NSError *)error;

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

###5.3.3 status 状态回调

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

- (void)cameraStreamingSession:(PLCameraStreamingSession *)session streamStatusDidUpdate:(PLStreamStatus *)status;

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

###5.3.4 产品层面的反馈

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

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

##5.4 网络异常处理

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

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

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

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

对于网络环境的切换,通常需要 App 整体做出调整,不单单是针对直播,所以 PLCameraStreamingKit 并未对这一情况做额外的监听,而是需要开发者自己对这些状态做出处理。

###5.4.1 重连

PLCameraStreamingKit 内部不包含重连逻辑。之所以不包含,主要因素是考虑到 App 的业务逻辑场景多样而负责,对于直播重连的次数,时机,间隔都会有不同的需求,而此时应该让开发者自己来决定是否重连,以及尝试重连的次数。

当因为网络异常而触发了推流断开时,会通过 error Delegate 回调触发

- (void)cameraStreamingSession:(PLCameraStreamingSession *)session didDisconnectWithError:(NSError *)error;

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

当网络从 3G/4G 切换到 Wi-Fi 后,基于节省流量等需求考虑,你可能需要进行一次快速的重连,使得数据可以通过 Wi-Fi 网络发送,这时,可以调用 '-restartWithCompleted:' 方法来快速重连。

5.5 水印和美颜

5.5.1 水印

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

 -(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 美颜

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

-(void)setBeautifyModeOn:(BOOL)beautifyModeOn;

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

-(void)setBeautify:(CGFloat)beautify;

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

-(void)setWhiten:(CGFloat)whiten;

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

-(void)setRedden:(CGFloat)redden;