实现直播过程中共享屏幕分为两个步骤:屏幕数据采集和流媒体数据推送。前对于iOS来说,屏幕采集需要系统的权限,受制于iOS系统的限制,第三方app并没有直接录制屏幕的权限,必须通过系统的功能来实现。不同的版本之间有一些差异,下面做个简单的介绍。(注:由于iOS 10和之前的系统只支持App内录制屏幕,所以只做简单的介绍,不做详细说明)
古老的iOS8和以前,系统没有提供相应的功能,通过破解系统的功能调用私有的API来实现。由于iOS8太过古老而且运行iOS8系统的设备也基本上支撑不起来直播的功能,我们这里不做详细讨论,有兴趣的可以研究一下。
Apple在iOS 9 推出了ReplayKit框架,提供了录屏功能,但是限制是只能录制本App内的屏幕。录制完成后会生成一个视频文件,只能通过RPPreviewViewController来预览,编译生成的文件,录制过程中无法获取数据。
iOS 10 Apple 推出了Broadcast Upload Extention 和 Broadcast Setup UI Extention,来解决录屏的问题。
首先介绍一下App Extension,官方文档(Extension的官方文档)。Extension是对App的扩展,在一定程度上打破了沙盒的限制,提供了应用间通信的可能。Extension是一个独立运行的进程,有自己的生命周期。下图所示:
这里有两个概念:
Containing app:an app that contains one or more extensions is called acontaining app.
很好理解,包含Extension的app就是Containing app。Extension不能单独发布安装,需要伴随着Containing app的安装而安装。
一个Containing app可以包含多个Extension。Extension可以单独运行,在Containing app没有启动的时候依然可以启动运行。Extension可以单独被系统调用,也可以被其它App调用。
Host app:An app that a user employs to choose an app extension is called a host app. A host app defines the context provided to the extension and kicks off the extension life cycle when it sends a request in response to a user action. An extension typically terminates soon after it completes the request it received from the host app.
Host app也容易理解,Extension一般由用户在某个app内启动,这个启动Extension的app就是host app。Host app提供了Extension运行所需的环境,通过request/response方式启动或者结束Extension的运行。交互过程如下:
iOS 10 通过Extension提供了录屏的功能,我们可以通过添加Extension来实现屏幕录制分享,可以实时读取到录制的缓存数据从而进行实时直播。但是iOS 10仅提供了录制本app内的功能。对在线会议这样的场景来说还是不够。
iOS 10的主要限制:只能录制本app内的数据。
到了iOS 11 Apple终于良心发现了,提供了跨app录屏的功能,可以实现录取整个屏幕的功能,当然还是通过集成ReplayKit (iOS11升级为ReplayKit2)的Extension来实现(这也是为什么腾讯的TRTC iOS屏幕分享功能最低支持到iOS11的原因)。但是还是有很大的限制,无法直接在app内部启动录制屏幕,需要用户点击控制中心的屏幕录制功能(如果控制中心中没有录屏按钮,需要在设置-》控制中心中添加),然后在弹出的选框中选择我们的Extension进行录屏。
iOS 11限制:app内无法直接启动屏幕录制,需要用户手动在控制中心启动。
iOS 12
iOS 12 在iOS11的基础上提供了RPSystemBroadcastPickerView,在弹出的界面可以选择启动Broadcast Upload Extention
来录制屏幕,用户无需在控制中心手动启动。
实现代码:
let pickerView = RPSystemBroadcastPickerView(frame: CGRect(x: 100, y: 100, width: 200, height: 200))
pickerView.preferredExtension = "test.app.extension.screen"
pickerView.showsMicrophoneButton = true
self.view.addSubview(pickerView)
Broadcast Upload Extention通过Xcode-》File-》New-》Target,然后选择Broadcast Upload Extention即可。
项目配置方式参考:https://cloud.tencent.com/document/product/647/45750
创建完成后会生成SampleHandler的类
实现代码:
import ReplayKit
class SampleHandler: RPBroadcastSampleHandler {
override func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?) {
// User has requested to start the broadcast. Setup info from the UI extension can be supplied but optional.
}
override func broadcastPaused() {
// User has requested to pause the broadcast. Samples will stop being delivered.
}
override func broadcastResumed() {
// User has requested to resume the broadcast. Samples delivery will resume.
}
override func broadcastFinished() {
// User has requested to finish the broadcast.
}
override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
switch sampleBufferType {
case RPSampleBufferType.video:
// Handle video sample buffer
break
case RPSampleBufferType.audioApp:
// Handle audio sample buffer for app audio
break
case RPSampleBufferType.audioMic:
// Handle audio sample buffer for mic audio
break
@unknown default:
// Handle other sample buffer types
fatalError("Unknown type of sample buffer")
}
}
}
1、broadcastStarted(withSetupInfo setupInfo:[String : NSObject]?)
这是录制屏幕开始的回调,这里我们通常做一些初始化的工作,比如数据处理等的初始化。
2、broadcastPaused()、broadcastResumed()、broadcastFinished()这三个方法是录制状态的变化,通常我们会把状态通知到Host app处理。
3、processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType)
终于来到了最重要的方法了,前面介绍那么多内容就是为了拿到这个数据。其中sampleBuffer是返回的数据,sampleBufferType
是数据的类型,包括三种video:视频数据、audioApp:app音频数据、audioMic:麦克风的音频数据。拿到这些数据以后可以做进一步的处理,可以将数据写入文件,也可以直接推流,也可以通过一定的方式发送到host app做进一步的处理。但是要注意ReplayKit系统给了50M内存的限制,所以直接推流需要限制视频质量。一般我们会把数据通过进程间数据传输的方式推给host app在做后续处理。
Extension和Extension通信
1、通过配置app group的方式共享文件或者UserDefault。
2、进程间通知:CFNotificationCenter,一般开启关闭等可以通过通知实现。
3、通过Socket传输,像屏幕分享这样的场景比较适合这么做。
下一篇文章将介绍TRTC的实现方案。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。