自定义流方式适用于手动维护媒体流或者要求更高的灵活性与可控性的场景。
步骤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 对象用于初始化 sdkconfig)
注意:
由于美颜检测和人像分割均有一定的加载耗时和资源消耗,初始化配置中提供了模块配置以供选择需要的功能,关闭的模块将不会进行预加载和初始化,也无法设置相关的效果。
2. 输入除了媒体流外,也支持传
string|HTMLImageElement
来处理图片。const config = {auth: authData, // 鉴权参数input: 'https://xxx.png', // input传输入流}const sdk = new ArSdk(// 传入一个 config 对象用于初始化 sdkconfig)// 在 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 = outputdocument.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 = outputdocument.body.appendChild(video)video.play()})
步骤4:获取输出
拿到输出的
MediaStream
之后,可以结合第三方 SDK(如 TRTC Web SDK,快直播 Web SDK)进行推流等后续处理。const output = await sdk.getOutput()
注意:
如果传入的 input 是图片,则返回为 string 类型的 DataURL,其他场景均返回
MediaStream
类型。输出的媒体流中
video
轨道是 ArSdk 实时处理的,如有 audio
轨道则保持不变。getOutput 方法是异步方法,会等到 SDK 执行完一系列初始化工作并且可以生成流之后返回。
getOutput 方法支持传入一个 FPS 参数,表示设置输出的帧率为 FPS(例如15),不传则默认取输入流的帧率。
getOutput 可以执行多次,每次执行会产生一个新的媒体流,可用于输出不同帧率媒体流的场景(例如预览时使用高帧率流,推流时使用低帧率流)。
步骤5:设置美颜和特效
更新输入流(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()}