Skip to content
pengbin edited this page Jul 12, 2017 · 2 revisions

KSYAirStreamer SDK (基于Airplay Screen Mirroring的录屏SDK)

使用Airplay方案录屏, 其实就要求直播APP将自己伪装成一个Airplay的接收设备, 实现Airplay的协议,解密出Fairplay加密的数据, 再将数据转发出去. Airplay+live KSYAirStreamer_iOS 就提供了这样一个模拟接收设备的SDK, 开始录屏时iOS系统与SDK建立连接, SDK收到画面后, 编码发送到直播服务器. 其中编码和推流功能使用金山云直播SDK实现.

正常的Airplay镜像, 是当与手机在同一个局域网中有一台Apple TV时, 通过手机的控制中心(在屏幕下方边缘处上拨时出现), 可以看到候选的Airplay 设备, 选中对应的设备,即可开始镜像, 此时系统顶部的状态栏会变成蓝色, 并有AirPlay的logo.

使用KSYAirStreamer 进行录屏直播时, 则省去了用户手动选择设备的过程, 因为我们已经知道设备的名称, 可以直接主动的选择对应的设备. 这一步主要是通过调用私有API, 直接对控制中心进行操作实现的. 也是无法上AppStore的理由之一.

KSYAirStreamKit

KSYAirStreamKitKSYAirTunesServer和金山云直播SDK中的音频采集和推流等组件 组装在一起共同实现了iOS录屏直播的功能. 需要录屏时, 构造一个KSYAirStreamKit的实例, 并通过kit 设置关于录屏和推流的一些配置,最后调用startService / stopService 方法, 即可启 / 停录屏.

    _kit = [[KSYAirStreamKit alloc] init];
    _kit.airCfg = [[KSYAirTunesConfig alloc] init];
    _kit.videoBitrate = 800; //kbps
    _kit.streamUrl = @"rtmp://xxx.xxx/live/stream";
    [_kit startService];
    ....
    [_kit stopService];

Airplay镜像配置参数

启动镜像前, 需要根据实际情况, 设置airplay镜像的参数, 这一步和直播时设置摄像头采集的参数是类似的. 通过KSYAirTunesConfig类可以配置的参数内容如下:

参数名 类型 说明 默认值
airplayName NSString* Airplay接收设备的名称 ksyair
videoSize int 接收设备的尺寸, 指定的是MAX(宽,高) 960
framerate int 希望接收到iOS发送端的视频帧率 30
airTunesPort short 设置airtunes 服务的监听端口, 0 表示系统自动分配 0
airVideoPort short 设置视频数据的接收端口(带重试) 7100
macAddr NSData * 设备的mac地址, 默认随机生成,(长度为6字节) 随机

其中airplayName设定的字符串就是, 在控制中心中能够看到的设备的名称. 当同一个局域网需要有多个设备同时使用录屏SDK时, 建议这个名称加上设备相关的后缀, 避免冲突.

videoSize 和正常的分辨率设置不太一样, 只有一个数字. 竖屏时高度为videoSize, 宽度根据屏幕比例计算得到,横屏时则宽度为videoSize, 高度又系统自动计算. 实际测试发现, iOS 10以上的系统中,部分设备可能不支持低分辨率. 比如iPhone 6s等设备已经不支持720(416 * 720,或720 * 416)以下分辨率输出, 请按实际情况做分辨率调整. 设置这些分辨率容易导致系统异常, 可能需要重启手机才能恢复.

推流参数设置

KSYAirStreamKit 中通过streamerBase实例来实现推流, 对应参数的配置请参考wiki中的描述

声音采集

KSYAirStreamKit 中通过 KSYAUAudioCapture来实现的音频采集. 正常的Airplay镜像时, 其实是音频和画面同步被投影到AppleTV等设备上的. 但是当我们录屏时, 接收端也在同一个设备上, 这时候保持原有逻辑音频就会出现回环了. 因此实际上, 录屏时, 只有画面部分走Airplay协议发送, 而音频还是通过外放(Speaker)播放, 这样系统或者游戏等App的声音, 能和主播的声音一起, 通过 KSYAUAudioCapture一起采集进来, 观众听到的就是比较完整的场景声音了.

状态变化和消息通知

整个录屏推流过程中, 有两个状态变化需要关注. 一个是来自数据源的KSYAirTunesServer的状态变化, 另一个是推流状态的变化.

Airplay镜像的状态变化

Airplay镜像 其实也是iOS系统和我们SDK通过网络进行连接交互的一个过程, 在连接阶段可能出错, 在连接成功后也可能受到网络变化等因素的影响断开连接. KSYAirTunesServer 通过 KSYAirDelegate代理协议来提供状态变化的通知, KSYAirStreamKit也转发了此代理协议. didStartMirroring 和 didStopMirroring 方法负责通知Airplay镜像的启动和停止. mirroringErrorDidOcccur 负责通知当前遇到的错误.

错误类型 说明 错误码值
KSYAirErrorCodePortConflict 端口冲突, 请检查airTunesPort/airVideoPort的配置 0
KSYAirErrorCodeNetworkDisconnection 网络未连接 1
KSYAirErrorCodeAirPlaySelectTimeout 连接AirPlay超时 2
KSYAirErrorCodeConnectBreak 连接断开(网络切换) 3
KSYAirErrorCodeOther 其他未知错误 4

推流状态变化通知

推流的状态变化和直播SDK中的内容一致, 请参考wiki KSYAirStreamKit 中已经实现了基本的重连逻辑