腾讯特效 SDK 使用美颜特效处理视频

ArRecorderSdk 是 SDK 2.0.3 起新增的离线美颜能力,用于对已有的 mp4 文件或在线视频 URL 二次处理,加美颜、特效、滤镜等效果,并导出一份新的 mp4 文件。与实时模式的 ArSdk 不同,ArRecorderSdk 特点如下。

相关产品
腾讯特效 SDK 产品页,含版本规格、价格与购买入口。

一、概述

·不依赖摄像头/直播流,处理本地或远端的录播 mp4。

·串行 await 每一帧,不丢帧,处理时长视设备性能,性能越好处理越快。

·音频原样透传,不解码不重编码。

·视频走 WebCodecs 硬解硬编(不做软解兜底)。

二、使用场景

·UGC 视频上传前的本地美颜。

·对已经录制好的 mp4 批量增加滤镜或贴纸特效。

·实现"先录制再美颜"的工作流。

三、浏览器要求

·必须支持 WebCodecs(VideoEncoder / VideoDecoder):

·Chrome 102+ 或 Edge 102+。

·Safari、移动端浏览器不满足要求。

·大文件输出(> 200 MB)建议浏览器支持 File System Access API(Chrome / Edge 桌面版),否则会回退到内存模式,超过 ~1.5 GB 可能 OOM。

四、使用注意

·不可与 ArSdk 共存:同页面同时实例化 ArSdk 和 ArRecorderSdk 会因共享 AROptionsManager 单例发生状态污染。如需在两者间切换,务必先 destroy() 已有实例。

·导出期间锁定参数:process() 进行中调用 setBeautify / setEffect / setFilter 会报错。如需在导出第一帧前完成参数设置,请监听 beforeRun 事件并在 handler 里 await 设置:

recorder.on('beforeRun', async ({ mode }) => { await recorder.setEffect({ id: 'xxx', intensity: 0.5 })})

·首次调用懒加载:构造时如果未传 beautify,运行期首次 setBeautify / setEffect 会触发管线懒加载(mediapipe + wasm,约 2-3 秒)。如希望第一帧立即带特效,请在构造时传 beautify,让 init() 阶段一并预热。

·WebCodecs 错误兜底:浏览器不支持 VideoEncoder / VideoDecoder 时,构造阶段会通过 error 事件抛出 ENVIRAONMENT_NOT_COMPATIBLE,请提前用环境检测屏蔽。

·音频不重编码:源视频音频会原样透传到输出 mp4,处理过程中不重新编码。

五、Demo 下载

完整 Demo 参考 recorder-demo.zip。

六、引入方式

ArRecorderSdk 与 ArSdk 同源同包,从同一个 npm 包按需引入即可:

import { ArRecorder } from 'tencentcloud-webar'const recorder = new ArRecorder.ArRecorderSdk({ auth: { licenseKey, appId, authFunc }, beautify: { whiten: 0.3, dermabrasion: 0.5 },})

注意:同一个页面不要同时实例化 ArSdk 和 ArRecorderSdk,否则会互相污染状态。可以先 destroy() 一个再实例化另一个。

七、完整示例

import { ArRecorder } from 'tencentcloud-webar'async function processVideo(file) { const recorder = new ArRecorder.ArRecorderSdk({ auth: { licenseKey: 'YOUR_LICENSE_KEY', appId: 'YOUR_APP_ID', authFunc: yourAuthFunc, // 与 ArSdk 同样的鉴权回调 }, beautify: { whiten: 0.3, dermabrasion: 0.5, }, }) // 1. 鉴权 + 预热处理管线 await recorder.init() // 2. 运行期可继续设置美颜/特效/滤镜 await recorder.setBeautify({ whiten: 0.5, lift: 0.2 }) await recorder.setEffect({ id: 'effectId', intensity: 0.7 }) await recorder.setFilter('filterId', 0.5) // 3. 处理 const result = await recorder.process(file, { onProgress: (current, total) => { console.log(`已处理 ${current}/${total} 帧`) }, }) // 4. 拿到结果 if (result.mode === 'in-memory') { const url = URL.createObjectURL(result.blob) document.querySelector('video').src = url } else { // file 模式:已直接写入用户选择的磁盘文件 const file = await result.fileHandle.getFile() } // 5. 清理资源 recorder.destroy()}

八、构造参数

new ArRecorder.ArRecorderSdk(options) 接受以下配置:

参数 说明 类型 是否必传
auth 鉴权参数,结构同 ArSdk。 {licenseKey: stringappId: stringsdkAppId?: stringauthFunc: () => Promise<{ signature, timestamp }>language?: string} 是
beautify 美颜参数,结构同 ArSdk 的 BeautifyOptions。不传时 init 阶段不会预热 detect+render 链路(节省加载时间),但运行期首次调用 setBeautify / setEffect 会触发懒加载(约 2-3 秒)。 BeautifyOptions 否
module 模块配置,结构同 ArSdk 的 ModuleConfig。Recorder 当前实际消费 faceDetectModel 字段;其余字段(segmentation / handLandmark 等)保留同样字段名以便迁移配置,但不会生效。 {faceDetectModel?: 'short' | 'full'// 其它 ArSdk 同名字段保留兼容,但不消费} 否
output 输出 mp4 编码配置。 {codec?: 'avc' // 当前仅支持 H.264bitrate?: number | 'auto' // bps,'auto' 跟随源视频fps?: number | 'auto' // 'auto' 跟随源视频} 否
initReport 是否初始化日志上报模块。 Boolean 否,默认 true

九、对象方法

接口 参数 返回 说明
async init() – Promise 鉴权 + 预热处理管线。构造时传了 beautify 时一并预热 detect+render 链路,第一帧不会再卡 2-3 秒。
async process(source, options?) source:Blob | File | string,本地文件或在线 URL(CORS 必须允许)。options:见"process 参数"。 Promise 对源视频做离线美颜处理,导出新的 mp4。处理过程中禁止再调 set* 接口。
async setBeautify(options) BeautifyOptions(同 ArSdk)。 Promise 热更新美颜参数,下一帧立即生效。导出期间(process 进行中)禁止调用。
async setEffect(input) input:特效 ID | Effect 对象 | (特效 ID | Effect 对象) 数组 | 空数组(清空)。参数风格同 ArSdk 的 setEffect。 Promise 设置/切换/清空特效(滤镜 / 贴纸 / 美妆 / 3D 试戴)。导出期间禁止调用。
async setFilter(id?, intensity?) id:滤镜 ID。缺省 / '' / 'none' 等于清除当前滤镜。intensity:滤镜强度 0-1,默认 1。 Promise 独立设置滤镜,与 setEffect 走不同通道(互斥滤镜)。导出期间禁止调用。
startPreview(source) source:HTMLVideoElement | MediaStream MediaStream 启动实时预览,返回处理后的 MediaStream,业务方设置到 `.srcObject` 即可。源视频 element 的播放/暂停/拖动会自动同步到预览。
stopPreview() – – 停止预览循环并释放资源。process() 执行前会自动调用。
destroy() – – 销毁实例,释放 detector / renderer / GPU 资源。同页面切换到 ArSdk 之前必须先 destroy。

十、process 参数

process(source, options) 的 options 字段:

参数 说明 类型
signal AbortSignal,用于业务方主动取消。 AbortSignal
onProgress 编码进度回调。current 为已编码完成的帧数,total 为总帧数。回调在编码完成时触发,避免出现"100% 后还要再等几分钟" 的卡死错觉。 (current: number, total: number) => void
onDownloadProgress URL 输入时的下载进度。total = -1 表示服务端未返回 Content-Length。 (loaded: number, total: number) => void
stallTimeoutMs URL 模式下,超过该毫秒数未收到新字节判定为网络卡死,主动 abort。默认 30000,设为 0 关闭检测。 Number
mode 输出模式:'in-memory':内存中累积整个 mp4,finalize 时返回 Blob。受 V8 单 buffer 上限(~1.5-2 GB)。'file':流式写入用户磁盘文件,需要 File System Access API(仅 Chrome / Edge 桌面)。'auto'(默认):按估算输出大小自动切换。 'in-memory' \\| 'file' \\| 'auto'
autoFileModeThreshold 'auto' 模式下切到 'file' 的字节数阈值,默认 200 MB。 Number
suggestedName 'file' 模式下浏览器保存对话框的默认文件名。 String
fileHandle 'file' / 'auto' 模式下推荐由业务方在 click handler 里同步调用 window.showSaveFilePicker() 拿到的 FileSystemFileHandle,避免 user activation 失效(详见下文)。 FileSystemFileHandle

process() 返回 ProcessResult:

{ blob: Blob | null, // in-memory 模式下为完整 mp4 Blob;file 模式下为 null fileHandle: FileSystemFileHandle | null, // file 模式下保存的文件句柄;in-memory 下为 null mode: 'in-memory' | 'file', // 实际使用的模式(auto 解析后的具体值) durationMs: number, // 处理耗时 frameCount: number, // 处理的视频帧数}

十一、in-memory 模式(默认小文件)

适合小于 200 MB 的视频。process() 返回的 Blob 可直接 URL.createObjectURL(blob) 用于预览或上传。

十二、file 模式(推荐大文件)

适合大于 200 MB 的视频,避免内存爆掉。必须在浏览器的 user gesture(如按钮点击)同步路径上调用 window.showSaveFilePicker() 拿到 fileHandle,再传给 process():

button.onclick = async () => { const fileHandle = await window.showSaveFilePicker({ suggestedName: 'output.mp4', types: [{ description: 'MP4 Video', accept: { 'video/mp4': ['.mp4'] } }], }) const result = await recorder.process(file, { mode: 'file', fileHandle, })}

注意:经过 await input.open() 等异步步骤后,user activation 已过期,SDK 内部弹出保存对话框会失败。请务必在 click 事件回调的同步开头先调用 showSaveFilePicker()。

十三、auto 模式(默认)

按 source.bitrate × duration / 8 估算输出大小,超过 autoFileModeThreshold(默认 200 MB)切换到 file 模式;浏览器不支持 File System Access API 时回退到 in-memory 并打印 warning。

赞 (0)
上一篇 4天前
下一篇 4天前