功能概述
摄像头推流,是指采集手机摄像头的画面以及麦克风的声音,进行编码之后再推送到直播云平台上。腾讯云 LiteAVSDK 通过
V2TXLivePusher 接口提供摄像头推流能力。特别说明
真机调试: 由于 SDK 大量使用鸿蒙系统的音视频接口,这些接口在仿真模拟器下往往不能工作,推荐您尽量使用真机调试。
功能对接
步骤1:下载 SDK 开发包
步骤2:给 SDK 配置 License 授权
1. 获取 License 授权:
若您已获得相关 License 授权,需在 云直播控制台 获取 License URL 和 License Key。

若您暂未获得 License 授权,需先参考 新增与续期 License 进行申请。
2. 在您的 App 调用全功能版 SDK 相关功能之前进行如下设置:
import { getV2TXLivePremierShareInstance } from 'liteavsdk';export default class EntryAbility extends UIAbility {onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {let licenseUrl: string = "<获取到的licenseUrl>";let licenseKey: string = "<获取到的key>";getV2TXLivePremierShareInstance(this.context).setLicence(licenseUrl, licenseKey);}}
注意:
License 中配置的 bundleName 必须和应用本身一致,否则会推流失败。
步骤3:创建 Pusher
视频云 SDK 中的
V2TXLivePusher 模块负责实现推流功能。import { createV2TXLivePusher, V2TXLivePusher, V2TXLiveMode } from 'liteavsdk';@Entry@Componentstruct ScreenPush {// 在 struct 成员变量区声明,指定推流协议// 指定对应的直播协议为 RTMP,该协议不支持连麦private pusher: V2TXLivePusher = createV2TXLivePusher(getContext(), V2TXLiveMode.V2TXLiveModeRTMP);// 指定对应的直播协议为 RTC,该协议支持连麦。如果在直播过程中有连麦需求,需要选择该协议// private pusher: V2TXLivePusher = createV2TXLivePusher(getContext(), V2TXLiveMode.V2TXLiveModeRTC);}
说明:
如果您有连麦需求,需要创建
V2TXLivePusher 对象时选择 RTC 协议。RTC 协议与 RTMP 协议在 API 使用上没有区别。步骤4:开启摄像头预览
想要开启摄像头的预览画面,您需要先给 SDK 提供一个用于显示视频画面的 XComponent 控件。您可以:
1. 在布局中声明 XComponent,需指定 libraryname 为 'liteavsdk',并为其设置一个唯一的 id:
// 在 build() 中添加视频渲染控件private viewId: string = 'camera_pusher_view';build() {Stack({ alignContent: Alignment.Bottom }) {XComponent({id: this.viewId,type: XComponentType.SURFACE,libraryname: 'liteavsdk'}).width('100%').height('100%').backgroundColor(Color.Black)}.width('100%').height('100%').backgroundColor(Color.Black)}
2. 在请求摄像头和麦克风权限通过后,再调用 startCamera 开启预览:
import { abilityAccessCtrl, Permissions, PermissionRequestResult } from '@kit.AbilityKit';import { BusinessError } from '@kit.BasicServicesKit';private requestPermissionsAndStartPreview(): void {const atManager = abilityAccessCtrl.createAtManager();const permissionList: Permissions[] = ['ohos.permission.CAMERA','ohos.permission.MICROPHONE'];atManager.requestPermissionsFromUser(getContext(), permissionList,(err: BusinessError, data: PermissionRequestResult) => {const allGranted = data.authResults.every(r => r === 0);if (allGranted) {// 权限授予后启动摄像头预览this.pusher.setRenderView(this.viewId);this.pusher.startCamera(true); // true 表示使用前置摄像头this.pusher.startMicrophone();}});}aboutToAppear(): void {this.requestPermissionsAndStartPreview();}
注意:
由于鸿蒙系统需要动态申请 ohos.permission.CAMERA 和 ohos.permission.MICROPHONE 权限,必须在权限授予后才能启动摄像头,否则会触发 V2TXLIVE_WARNING_CAMERA_NO_PERMISSION 警告。
步骤5:启动和结束推流
1. 如果已经通过
startCamera 接口启动了摄像头预览,就可以调用 V2TXLivePusher 中的 startPush 接口开始推流。startCameraPush(): void {// 根据推流协议传入对应的 URL 即可启动推流,RTMP 协议以 rtmp:// 开头,该协议不支持连麦let url: string = "rtmp://test.com/live/streamid?txSecret=xxxxx&txTime=xxxxxxxx";// 根据推流协议传入对应的 URL 即可启动推流,RTC 协议以 trtc:// 开头,该协议支持连麦// let url: string = "trtc://cloud.tencent.com/push/streamid?sdkappid=1400188888&userId=A&usersig=xxxxx";let ret: number = this.pusher.startPush(url);if (ret === V2TXLiveCode.V2TXLIVE_ERROR_INVALID_LICENSE) {console.error("startPush: license 校验失败");}}
注意:
返回 V2TXLIVE_ERROR_INVALID_LICENSE 的原因?
如果
startPush 接口返回 V2TXLIVE_ERROR_INVALID_LICENSE,则代表您的 License 校验失败了,请检查 步骤2:给 SDK 配置 License 授权 中设置的 url 和 key。2. 推流结束后,可以调用 V2TXLivePusher 中的 stopPush 接口结束推流。
aboutToDisappear(): void {if (this.isPushing) {this.pusher.stopPush();}}
步骤6:纯音频推流
this.pusher.startMicrophone();// 根据推流协议传入对应的 URL 即可启动推流,RTMP 协议以 rtmp:// 开头,该协议不支持连麦let url: string = "rtmp://test.com/live/streamid?txSecret=xxxxx&txTime=xxxxxxxx";// 根据推流协议传入对应的 URL 即可启动推流,RTC 协议以 trtc:// 开头,该协议支持连麦// let url: string = "trtc://cloud.tencent.com/push/streamid?sdkappid=1400188888&userId=A&usersig=xxxxx";let ret: number = this.pusher.startPush(url);
说明:
步骤7:设定画面清晰度
调用 V2TXLivePusher 中的 setVideoQuality 接口,可以设定观众端的画面清晰度。之所以说是观众端的画面清晰度,是因为主播看到的视频画面是未经编码压缩过的高清原画,不受设置的影响。而
setVideoQuality 设定的视频编码器的编码质量,观众端可以感受到画质的差异。详情请参见 设定画面质量。步骤8:美颜美白和红润特效

美颜风格
SDK 内置三种不同的磨皮算法,每种磨皮算法即对应一种美颜风格,您可以选择最适合您产品定位的方案。定义见 TXBeautyStyle 枚举:
美颜风格 | 效果说明 |
TXBeautyStyleSmooth | 光滑,适用于美女秀场,效果比较明显。 |
TXBeautyStyleNature | 自然,磨皮算法更多地保留了面部细节,主观感受上会更加自然。 |
TXBeautyStylePitu | 由上海优图实验室提供的美颜算法,磨皮效果介于光滑和自然之间,比光滑保留更多皮肤细节,比自然磨皮程度更高。 |
美颜风格可以通过 TXBeautyManager 的
setBeautyStyle 接口设置:美颜风格 | 设置方式 | 接口说明 |
美颜级别 | 通过 TXBeautyManager 的 setBeautyLevel 设置。 | 取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。 |
美白级别 | 通过 TXBeautyManager 的 setWhitenessLevel 设置。 | 取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。 |
红润级别 | 通过 TXBeautyManager 的 setRuddyLevel 设置。 | 取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。 |
步骤9:色彩滤镜效果

调用 V2TXLivePusher 中的 getBeautyManager 接口可以获取 TXBeautyManager 实例进一步设置色彩滤镜效果。
调用 TXBeautyManager 的
setFilter 接口可以设置色彩滤镜效果。所谓色彩滤镜,是指一种将整个画面色调进行区域性调整的技术,例如将画面中的淡黄色区域淡化实现肤色亮白的效果,或者将整个画面的色彩调暖让视频的效果更加清新和温和。我们的设计师团队提供了17种默认的 色彩滤镜 供您使用。调用 TXBeautyManager 的
setFilterStrength 接口可以设定滤镜的浓度,设置的浓度越高,滤镜效果也就越明显。// 选择期望的色彩滤镜文件,滤镜文件可以在小直播 App 的资源文件中获取(以 tuibeauty_filter_ 开头的 .png 文件)import image from '@ohos.multimedia.image';// 通过资源管理器加载滤镜图片let resourceMgr = getContext().resourceManager;let fileData = await resourceMgr.getMediaContent($r('app.media.tuibeauty_filter_biaozhun'));let imageSource = image.createImageSource(fileData.buffer);let pixelMap = await imageSource.createPixelMap();this.pusher.getBeautyManager().setFilter(pixelMap);this.pusher.getBeautyManager().setFilterStrength(0.5);
步骤10:设备管理
V2TXLivePusher 提供了一组 API 用于控制设备的行为。您通过
getDeviceManager 获取 TXDeviceManager 实例进一步进行设备管理,详细用法请参见 TXDeviceManager API。
步骤11:观众端的镜像效果
通过调用 V2TXLivePusher 的 setEncoderMirror 可以改变观众端观看到的镜像效果。之所以说是观众端的镜像效果,是因为当主播在使用前置摄像头直播时,默认情况下自己看到的画面会被 SDK 反转,这时主播就像照镜子一样,观众看到的效果和主播看到的是一致的。如下图所示:

步骤12:横屏推流
大多数情况下,主播习惯以“竖屏持握”手机进行直播拍摄,观众端看到的也是竖屏分辨率的画面(例如 540 × 960 这样的分辨率);有时主播也会“横屏持握”手机,这时观众端期望能看到是横屏分辨率的画面(例如 960 × 540 这样的分辨率),如下图所示:

V2TXLivePusher 默认推出的是竖屏分辨率的视频画面,如果希望推出横屏分辨率的画面,可以修改
setVideoQuality 接口的参数来设定观众端的画面横竖屏模式。import { V2TXLiveVideoEncoderParam, V2TXLiveVideoResolution, V2TXLiveVideoResolutionMode } from 'liteavsdk';let param: V2TXLiveVideoEncoderParam = new V2TXLiveVideoEncoderParam(V2TXLiveVideoResolution.V2TXLiveVideoResolution960x540);param.videoResolutionMode = this.isLandscape? V2TXLiveVideoResolutionMode.V2TXLiveVideoResolutionModeLandscape: V2TXLiveVideoResolutionMode.V2TXLiveVideoResolutionModePortrait;this.pusher.setVideoQuality(param);
步骤13:音效设置
调用 V2TXLivePusher 中的
getAudioEffectManager 获取 TXAudioEffectManager 实例可以实现背景混音、耳返、混响等音效功能。背景混音是指主播在直播时可以选取一首歌曲伴唱,歌曲会在主播的手机端播放出来,同时也会被混合到音视频流中被观众端听到,所以被称为“混音”。

调用 TXAudioEffectManager 中的
enableVoiceEarMonitor 选项可以开启耳返功能,“耳返”指的是当主播戴上耳机来唱歌时,耳机中要能实时反馈主播的声音。调用 TXAudioEffectManager 中的
setVoiceReverbType 接口可以设置混响效果,例如 KTV、会堂、磁性、金属等,这些效果也会作用到观众端。调用 TXAudioEffectManager 中的
setVoiceChangerType 接口可以设置变调效果,例如“萝莉音”,“大叔音”等,用来增加直播和观众互动的趣味性,这些效果也会作用到观众端。
说明:
步骤14:设置 Logo 水印
SDK 所要求的水印图片格式为 PNG 而不是 JPG,因为 PNG 图片格式有透明度信息,因而能够更好地处理锯齿等问题(将 JPG 图片修改后缀名是不起作用的)。
(x, y, scale)参数设置的是水印图片相对于推流分辨率的归一化坐标。假设推流分辨率为:540 × 960,该字段设置为:(0.1,0.1,0.1),则水印的实际像素坐标为:(540 × 0.1,960 × 0.1,水印宽度 × 0.1,水印高度会被自动计算)。import fs from '@ohos.file.fs';// 将水印图片从 rawfile 写入沙箱路径后,传入文件路径let content = getContext().resourceManager.getRawFileContentSync('watermark.png');let path = getContext().getApplicationContext().filesDir + '/image/watermark.png';let file = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);fs.writeSync(file.fd, content.buffer);fs.closeSync(file);// 设置视频水印this.pusher.setWatermark(path, 0.03, 0.015, 1);
步骤15:主播端弱网提醒
如果主播在推流时遇到网络很差的情况,需要有一个友好的提示,提示主播应当检查网络。

通过 V2TXLivePusherObserver 里的 onWarning 可以捕获 V2TXLIVE_WARNING_NETWORK_BUSY 事件,它代表当前主播的网络已经非常糟糕,出现此事件即代表观众端会出现卡顿。此时就可以像上图一样在 UI 上弹出一个“弱网提示”。
onWarning: (code: number, msg: string, extraInfo: object) => {if (code === V2TXLiveCode.V2TXLIVE_WARNING_NETWORK_BUSY) {this.showNetBusyTips(); // 显示网络繁忙的提示}}
步骤16:发送 SEI 消息
调用 V2TXLivePusher 中的 sendSeiMessage 接口可以发送 SEI 消息。所谓 SEI,是视频编码数据中规定的一种附加增强信息,平时一般不被使用,但我们可以在其中加入一些自定义消息,这些消息会被直播 CDN 转发到观众端。使用场景有:
答题直播:推流端将题目下发到观众端,可以做到“音-画-题”高度协调同步。
秀场直播:推流端将歌词下发到观众端,可以在播放端实时绘制出歌词特效,因而不受视频编码的降质影响。
在线教育:推流端将激光笔和涂鸦操作下发到观众端,可以在播放端实时地划圈划线。
由于自定义消息是直接被塞入视频数据中的,所以不能太大(几个字节比较合适),一般常用于塞入自定义的时间戳等信息。
let payloadType: number = 5;let msg: string = "test";let encoder = new util.TextEncoder();let data: Uint8Array = encoder.encodeInto(msg);this.pusher.sendSeiMessage(payloadType, data.buffer);
常规开源播放器或者网页播放器是不能解析 SEI 消息的,必须使用 LiteAVSDK 中自带的 V2TXLivePlayer 才能解析这些消息:
1. 设置:
let payloadType: number = 5;this.player.enableReceiveSeiMessage(true, payloadType);
2. 当 V2TXLivePlayer 所播放的视频流中有 SEI 消息时,会通过 V2TXLivePlayerObserver 中的 onReceiveSeiMessage 回调来接收该消息。
事件处理
事件监听
错误通知
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 | 录屏被系统中断。 |