自定义流

最近更新时间:2024-08-20 14:07:41

我的收藏
自定义流方式适用于手动维护媒体流或者要求更高的灵活性与可控性的场景。

步骤1:引入 SDK

import { ArSdk } from 'tencentcloud-webar';// SDK 类
如果项目无需编译,则可以直接以如下方式引用:
<script charset="utf-8" src="https://webar-static.tencent-cloud.com/ar-sdk/resources/latest/webar-sdk.umd.js"></script>
<script>
// 从 window.AR 上获取 ArSdk 类
const { ArSdk } = window.AR;
......
</script>

步骤2:初始化实例

1. 初始化一个 SDK 实例。
// 获取鉴权参数
const authData = {
licenseKey: 'xxxxxxxxx',
appId: 'xxx',
authFunc: authFunc // 详见「License 配置与使用 - 签名方法」
};
// 输入SDK的流
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: { width: w, height: h }
})

const config = {
module: { // 0.2.0版本新增
beautify: true, // 是否启用美颜模块,启用后可以使用美颜、美妆、贴纸等功能
segmentation: true // 是否启用人像分割模块,启用后可以使用背景功能
},
auth: authData, // 鉴权参数
input: stream, // input传输入流
mirror: true, // 1.0.19 新增,输入流也可以设置镜像效果
beautify: { // 初始化美颜参数(可选)
whiten: 0.1,
dermabrasion: 0.3,
eye: 0.2,
chin: 0,
lift: 0.1,
shave: 0.2
}
}
const sdk = new ArSdk(
// 传入一个 config 对象用于初始化 sdk
config
)
注意:
由于美颜检测和人像分割均有一定的加载耗时和资源消耗,初始化配置中提供了模块配置以供选择需要的功能,关闭的模块将不会进行预加载和初始化,也无法设置相关的效果。
2. 输入除了媒体流外,也支持传 string|HTMLImageElement 来处理图片。
const config = {
auth: authData, // 鉴权参数
input: 'https://xxx.png', // input传输入流
}
const sdk = new ArSdk(
// 传入一个 config 对象用于初始化 sdk
config
)

// 在 created 回调中可拉取特效和滤镜列表供页面展示,详见「SDK接入 - 参数与方法」
sdk.on('created', () => {
// 获取内置美妆
sdk.getEffectList({
Type: 'Preset',
Label: '美妆',
}).then(res => {
effectList = res
});
// 获取内置滤镜
sdk.getCommonFilter().then(res => {
filterList = res
})
})

// 在 ready 回调中调用 setBeautify/setEffect/setFilter 等渲染方法
// 详情可参见「SDK接入 - 设置美颜和特效」
sdk.on('ready', () => {
// 设置美颜
sdk.setBeautify({
whiten: 0.2
});
// 设置特效
sdk.setEffect({
id: effectList[0].EffectId,
intensity: 0.7
});
// 设置滤镜
sdk.setFilter(filterList[0].EffectId, 0.5)
})

步骤3:播放流

可以使用 ArSdk.prototype.getOutput 方法获取输出的媒体流。 不同的回调事件中获取的输出流有些许差别,适用于不同的场景,根据自身业务需求选择一种处理方式即可。
如果对画面展示的时效性有需求,可以在 cameraReady 回调中获取并播放输出流,此时 SDK 尚未开始资源加载和检测的初始化,仅能展示原始画面。
sdk.on('cameraReady', async () => {
// 在 cameraReady 回调中可以更早地获取输出画面,此时初始化传入的美颜参数还未生效,同输入画面
// 适用于需要尽早地展示画面,但不要求画面一出现就有美颜的场景
// 后续美颜生效后无需更新stream,SDK内部已处理
const output = await ar.getOutput();
// 使用video播放输出的媒体流,预览效果
const video = document.createElement('video')
video.setAttribute('playsinline', '');
video.setAttribute('autoplay', '');
video.srcObject = output
document.body.appendChild(video)
video.play()
})
如果需要检测初始化完成,且美颜生效之后再播放,则可以在 ready 回调获取输出并播放。
sdk.on('ready', async () => {
// 在 ready 回调中获取输出画面,此时初始化传入的美颜参数已生效,获取的 output stream 已带美颜效果
// 区别上述 cameraReady 中获取 output,此回调执行时机稍晚一些,适用于画面一展示就要有美颜的场景,但不要求尽早地展示画面的场景
const output = await ar.getOutput();
// 使用video播放输出的媒体流,预览效果
const video = document.createElement('video')
video.setAttribute('playsinline', '');
video.setAttribute('autoplay', '');
video.srcObject = output
document.body.appendChild(video)
video.play()
})

步骤4:获取输出

拿到输出的 MediaStream 之后,可以结合第三方 SDK(如 TRTC Web SDK,快直播 Web SDK)进行推流等后续处理。
const output = await sdk.getOutput()
推流等操作参见 结合 TRTC 推流结合 WebRTC 推流
注意:
如果传入的 input 是图片,则返回为 string 类型的 DataURL,其他场景均返回 MediaStream 类型。
输出的媒体流中 video 轨道是 ArSdk 实时处理的,如有 audio 轨道则保持不变。
getOutput 方法是异步方法,会等到 SDK 执行完一系列初始化工作并且可以生成流之后返回。
getOutput 方法支持传入一个 FPS 参数,表示设置输出的帧率为 FPS(例如15),不传则默认取输入流的帧率。
getOutput 可以执行多次,每次执行会产生一个新的媒体流,可用于输出不同帧率媒体流的场景(例如预览时使用高帧率流,推流时使用低帧率流)。

步骤5:设置美颜和特效

SDK 的所有素材均兼容微信小程序端与 Web 端,调用方式一致,详情请参见 设置美颜和特效

更新输入流(0.1.19版本后开始支持)

如果您有切换设备、启停摄像头等需求,需要获取新的流输入sdk,请勿重复初始化多次sdk,可以直接调用sdk.updateInputStream切换输入流。 下述以切换电脑默认摄像头及外置摄像头为例,介绍 updateInputStream 的用法:

async function getVideoDeviceList(){
const devices = await navigator.mediaDevices.enumerateDevices()
const videoDevices = []
devices.forEach((device)=>{
if(device.kind === 'videoinput'){
videoDevices.push({
label: device.label,
id: device.deviceId
})
}
})
return videoDevices
}

async function initDom(){
const videoDeviceList = await getVideoDeviceList()
let dom = ''
videoDeviceList.forEach(device=>{
dom = `${dom}
<button id=${device.id} onclick='toggleVideo("${device.id}")'>${device.label}<nbutton>
`
})
const div = document.createElement('div');
div.id = 'container';
div.innerHTML = dom;
document.body.appendChild(div);
}

async function toggleVideo(deviceId){
const stream = await navigator.mediaDevices.getUserMedia({
video: {
deviceId,
width: 1280,
height: 720,
}
})
// 使用sdk提供的更新输入流接口,内部已处理旧轨道的 stop
// 输入流更新后无需再次调用 getOutput ,SDK内部已处理
sdk.updateInputStream(stream)
}

initDom()


暂停与恢复检测

暂停检测可以节省 CPU 占用,如果业务逻辑中有需要暂时停止检测可以调用 disable 和 enable 接口进行手动启停。
<button id="disable">停止检测</button>
<button id="enable">启动检测</button>
// 停止检测,输出原始画面
disableButton.onClick = () => {
sdk.disable()
}
// 启动检测,输出美颜等特效生效后的画面
enableButton.onClick = () => {
sdk.enable()
}