概述
摄像头推流,是指采集手机摄像头的画面以及麦克风的声音,进行编码之后再推送到直播云平台上。腾讯云 live_flutter_plugin 通过
V2TXLivePusher
接口提供摄像头推流能力。示例代码
针对开发者的接入反馈的高频问题,腾讯云提供有更加简洁的 API-Example 工程,方便开发者可以快速的了解相关 API 的使用,欢迎使用。
开发环境准备
Android
Android 5.0 系统以后开始支持录屏功能。
悬浮窗在部分手机和系统上需要通过手动设置打开。
iOS
录屏功能是 iOS 10 新推出的特性,苹果在 iOS 9 的 ReplayKit 保存录屏视频的基础上,增加了视频流实时直播功能,官方介绍见 Go Live with ReplayKit。iOS 11 增强为 ReplayKit2,进一步提升了 Replaykit 的易用性和通用性,并且可以对整个手机实现屏幕录制,并非只是支持 ReplayKit 功能,因此录屏推流建议直接使用 iOS 11 的 ReplayKit2 屏幕录制方式。系统录屏采用的是扩展方式,扩展程序有单独的进程,iOS 系统为了保证系统流畅,给扩展程序的资源相对较少,扩展程序内存占用过大也会被 Kill 掉。腾讯云 LiteAV SDK 在原有直播的高质量、低延迟的基础上,进一步降低系统消耗,保证了扩展程序稳定。
注意
本文主要介绍 iOS 11 的 ReplayKit2 录屏使用 SDK 推流的方法,涉及 SDK 的使用介绍同样适用于其它方式的自定义推流。更详细的使用说明可以参考 Demo 里 Live Demo Screen 文件夹示例代码。
1. 创建直播扩展
在现有工程选择 New > Target…,选择 Broadcast Upload Extension,如图所示。
配置好 Product Name。单击 Finish 后可以看到,工程多了所输 Product Name 的目录,目录下有个系统自动生成的 SampleHandler 类,这个类负责录屏的相关处理。注意
Xcode 9 及以上的版本,手机也必须升级至 iOS 11 以上,否则模拟器无法使用录屏特性。
2. 导入TXLiteAVSDK_ReplayKitExt.framework
直播扩展需要导入 TXLiteAVSDK_ReplayKitExt.framework。扩展导入 framework 的方式和主 App 导入方式相同,SDK 的系统依赖库也没有区别。具体请参见腾讯云官网 工程配置(iOS)。
快速开始
1. 设置依赖
dependencies:live_flutter_plugin: latest version number
2. 给 SDK 配置 License 授权
1. 获取 License 授权:
若您已获得相关 License 授权,需在 云直播控制台 获取 License URL 和 License Key。
若您暂未获得 License 授权,需先参考 新增与续期 License 进行申请。
2. 在您的 App 调用 live_flutter_plugin 的相关功能之前进行如下设置:
import 'package:live_flutter_plugin/v2_tx_live_premier.dart';/// 腾讯云License管理页面(https://console.cloud.tencent.com/live/license)setupLicense() {// 当前应用的License LicenseUrlvar LICENSEURL = "";// 当前应用的License Keyvar LICENSEURLKEY = "";V2TXLivePremier.setLicence(LICENSEURL, LICENSEURLKEY);}
注意
License 中配置的 packageName/BundleId 必须和应用本身一致,否则会推流失败。
3. 创建 Pusher 对象
创建一个 V2TXLivePusher 对象,我们后面主要用它来完成推流工作。
V2TXLivePusher livePusher = V2TXLivePusher(V2TXLiveMode.v2TXLiveModeRTMP);
4. 启动推流
String rtmpUrl = "rtmp://2157.livepush.myqcloud.com/live/xxxxxx";livePusher.startMicrophone();livePusher.startScreenCapture();livePusher.startPush(rtmpUrl);
返回 V2TXLIVE_ERROR_INVALID_LICENSE 的原因如果
startPush
接口返回V2TXLIVE_ERROR_INVALID_LICENSE
,则代表您的 License 校验失败了,请检查 第2步:给 SDK 配置 License 授权 中的工作是否有问题。5. 结束推流
因为用于推流的
V2TXLivePusher
对象同一时刻只能有一个在运行,所以结束推流时要做好清理工作。//结束录屏直播,注意做好清理工作void stopPush() {livePusher.stopMicrophone();livePusher.stopScreenCapture();livePusher.stopPush();}
事件处理
事件监听
错误通知
SDK 发现部分严重问题,推流无法继续。
事件 ID | 数值 | 含义说明 |
V2TXLIVE_ERROR_FAILED | -1 | 暂未归类的通用错误 |
V2TXLIVE_ERROR_INVALID_PARAMETER | -2 | 调用 API 时,传入的参数不合法 |
V2TXLIVE_ERROR_REFUSED | -3 | API 调用被拒绝 |
V2TXLIVE_ERROR_NOT_SUPPORTED | -4 | 当前 API 不支持调用 |
V2TXLIVE_ERROR_INVALID_LICENSE | -5 | license 不合法,调用失败 |
V2TXLIVE_ERROR_REQUEST_TIMEOUT | -6 | 请求服务器超时 |
V2TXLIVE_ERROR_SERVER_PROCESS_FAILED | -7 | 服务器无法处理您的请求 |
警告事件
SDK 发现部分警告问题,但 WARNING 级别的事件都会触发一些尝试性的保护逻辑或者恢复逻辑,而且有很大概率能够恢复。
事件 ID | 数值 | 含义说明 |
V2TXLIVE_WARNING_NETWORK_BUSY | 1101 | 网络状况不佳:上行带宽太小,上传数据受阻 |
V2TXLIVE_WARNING_VIDEO_BLOCK | 2105 | 当前视频播放出现卡顿 |
V2TXLIVE_WARNING_CAMERA_START_FAILED | -1301 | 摄像头打开失败 |
V2TXLIVE_WARNING_CAMERA_OCCUPIED | -1316 | 摄像头正在被占用中,可尝试打开其他摄像头 |
V2TXLIVE_WARNING_CAMERA_NO_PERMISSION | -1314 | 摄像头设备未授权,通常在移动设备出现,可能是权限被用户拒绝了 |
V2TXLIVE_WARNING_MICROPHONE_START_FAILED | -1302 | 麦克风打开失败 |
V2TXLIVE_WARNING_MICROPHONE_OCCUPIED | -1319 | 麦克风正在被占用中,例如移动设备正在通话时,打开麦克风会失败 |
V2TXLIVE_WARNING_MICROPHONE_NO_PERMISSION | -1317 | 麦克风设备未授权,通常在移动设备出现,可能是权限被用户拒绝了 |
V2TXLIVE_WARNING_SCREEN_CAPTURE_NOT_SUPPORTED | -1309 | 当前系统不支持屏幕分享 |
V2TXLIVE_WARNING_SCREEN_CAPTURE_START_FAILED | -1308 | 开始录屏失败,如果在移动设备出现,可能是权限被用户拒绝了 |
V2TXLIVE_WARNING_SCREEN_CAPTURE_INTERRUPTED | -7001 | 录屏被系统中断 |
常见问题
ReplayKit2 屏幕录制在 iOS 11 新推出功能,相关的官方文档比较少,且存在着一些问题,使得每个版本的系统都在不断修复完善中。以下是一些使用中的常见现象或问题:
1. 屏幕录制何时会自动停止?
系统在锁屏或有电话打入时,会自动停止屏幕录制,此时 SampleHandler 里的 broadcastFinished 函数会被调用,可在此函数发通知提示用户。
2. 采集推流过程中有时屏幕录制会自动停止问题?
通常是因为设置的推流分辨率过高时在做横竖屏切换过程中容易出现。ReplayKit2 的直播扩展目前是有50M的内存使用限制,超过此限制系统会直接杀死扩展进程,因此 ReplayKit2 上建议推流分辨率不高于720P。
3. iPhoneX 手机的兼容性与画面变形问题?
iPhoneX 手机因为有刘海,屏幕采集的画面分辨率不是 9:16。如果设了推流输出分辨率为 9:16 的比例,如高清里是为 960 × 540 的分辨率,这时因为源分辨率不是 9:16 的,推出去的画面就会稍有变形。建议设置分辨率时根据屏幕分辨率比例来设置,拉流端用 AspectFit 显示模式 iPhoneX 的屏幕采集推流会有黑边是正常现象,AspectFill 看画面会不全。