更新记录
1.0.0(2026-06-21) 下载此版本
核心能力
- 屏幕采集:基于
getDisplayMediaAPI,支持屏幕 / 窗口 / 标签页采集 - 区域选择录制:交互式框选(
RegionPreviewSelector预览背景 + 坐标映射)与固定区域,通过 Canvas 裁剪输出 - 录制控制:开始 / 暂停 / 恢复 / 停止完整生命周期
- 截图功能:录制中随时截取当前帧,支持 jpeg / png / webp 格式与质量配置
- 视频导出:支持 Blob / BlobUrl / ArrayBuffer / Base64 / DataUrl 多种返回类型
- 视频下载:录制停止后一键下载,支持自定义文件名与格式
- 麦克风混音:录制时可混入麦克风音频,支持自定义麦克风约束与降噪回声消除
- 系统音频采集:支持采集系统音频(Chrome / Edge)
视频转换(WebM → MP4)
- 内置 ffmpeg.wasm(0.12.10)运行时,纯浏览器端转换,无需服务器
VideoConverter类封装转换逻辑,支持 high / medium / low 三档质量预设- 多线程加速:自动检测
crossOriginIsolated,环境支持时启用@ffmpeg/core-mt多线程(约 3~5 倍提速),不支持时自动降级单线程 - 转换进度预估:基于时间的指数衰减曲线 + ffmpeg progress 事件兜底,解决 WASM 环境下 progress 事件不可靠问题
- 加载进度通知:core / wasm / worker 分阶段加载进度
ScreenCaptureManager集成:setConverter()/stopAndConvert()/convert()/ 转换事件监听- 内置单线程 core(
@ffmpeg/core)与多线程 core-mt(@ffmpeg/core-mt)双核心,按环境自动切换
区域选择增强
RegionPreviewSelector:授权后从采集流抓取一帧画面作为选区背景,"所见即所框"- 视口坐标自动映射为采集流原始分辨率坐标,保证 Canvas 裁剪准确
- 选区约束在画面实际显示区域内,避免框到 letterbox 黑边
- 支持 frame(静态帧)与 live(实时流)两种预览模式
工具与检测
- 能力检测:
canCapture()/canCaptureAudio()/getPlatformInfo()自动检测平台能力 - 约束预设:默认 / 高质量 / 低延迟 / 演示 / 教程等场景预设,
getConstraintsByScenario一键配置 - 数据源转换:
createScreenCaptureDataSource提供 Blob / ArrayBuffer / Base64 / DataUrl / BlobUrl 互转 EventEmitter事件总线基类
演示页面
- 基础屏幕录制页:底部浮动胶囊菜单栏 + 全屏沉浸预览 + 多选项弹窗
- 首页:插件介绍、核心特性、平台兼容性、快速开始、注意事项
平台兼容性
uni-app(4.74)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| × | √ | √ | √ | × | × | × | × | × |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | × | × | × |
jz-screen-capture
jz-screen-capture 是一个面向 uni-app Vue3 H5 的 PC 端屏幕录制 插件。
基于 getDisplayMedia 采集屏幕,支持交互式区域选择录制、开始/暂停/停止录制、截图、视频导出,并内置 ffmpeg.wasm 实现 WebM 转 MP4(多线程加速)。
功能特性
- 屏幕采集:
getDisplayMedia采集屏幕 / 窗口 / 标签页,支持系统音频 - 区域选择录制:
RegionPreviewSelector预览背景 + 坐标映射,"所见即所框";也支持固定区域 - 录制控制:开始 / 暂停 / 恢复 / 停止完整生命周期
- 截图:录制中随时截取当前帧,支持 jpeg / png / webp
- 视频导出:Blob / BlobUrl / ArrayBuffer / Base64 / DataUrl 多种返回类型
- 视频下载:录制停止后一键下载
- 麦克风混音:录制时可混入麦克风音频
- WebM 转 MP4:内置 ffmpeg.wasm,纯浏览器端转换,支持多线程加速
- 能力检测:自动检测平台、浏览器、系统音频、区域选择支持情况
- 场景预设:默认 / 高质量 / 低延迟 / 演示 / 教程等约束预设
平台支持
| 端 | 能力 | 说明 |
|---|---|---|
| PC H5 Chrome / Edge | 完整支持 | getDisplayMedia + 系统音频 + 多线程转换 |
| PC H5 Safari | 部分支持 | 支持 getDisplayMedia,系统音频采集受限 |
| PC H5 Firefox | 支持 | 支持 getDisplayMedia,不支持系统音频 |
| 移动端 H5 | 不支持 | 移动端浏览器不支持 getDisplayMedia |
| App / 小程序 | 不支持 | 当前插件定位为 H5 Web API 能力 |
屏幕采集需要 HTTPS 环境,
localhost调试除外。
安装与引入
将插件放入项目 uni_modules/jz-screen-capture 后,在页面中按需引入:
import {
getScreenCaptureManager,
destroyScreenCaptureManager,
canCapture,
canCaptureAudio,
getPlatformInfo,
getConstraintsByScenario,
RegionSelector,
RegionPreviewSelector,
VideoConverter
} from '@/uni_modules/jz-screen-capture/js/index.js'
快速开始
基础录屏
import {
getScreenCaptureManager,
destroyScreenCaptureManager,
canCapture
} from '@/uni_modules/jz-screen-capture/js/index.js'
// 1. 检测平台能力
if (!canCapture()) {
console.error('当前环境不支持屏幕录制')
}
// 2. 获取管理器(单例)
const manager = getScreenCaptureManager()
// 3. 注册事件
manager.onStart(() => console.log('录制开始'))
manager.onStop((result) => {
console.log('录制结束', result)
// result.blobUrl 可直接用于 <video> 播放
})
manager.onError((err) => console.error(err))
// 4. 开始录制
await manager.start({
width: 1920,
height: 1080,
frameRate: 30,
audio: true,
returnType: ['blobUrl']
})
// 5. 暂停 / 恢复
manager.pause()
manager.resume()
// 6. 停止
manager.stop()
// 7. 下载
manager.download({ fileName: 'my-record' })
// 8. 释放资源
destroyScreenCaptureManager()
区域选择录制
// 方式一:交互式框选(推荐)
// 授权后弹出预览画面,用户在真实画面上框选区域
await manager.start({
region: 'interactive',
frameRate: 30,
audio: true
})
manager.onRegionSelected((region) => {
console.log('选区完成', region) // 已映射为采集流原始分辨率坐标
})
// 方式二:指定固定区域
await manager.start({
region: { x: 100, y: 100, width: 800, height: 600 },
frameRate: 30
})
截图功能
await manager.start({ frameRate: 30 })
// 录制中截图
const photo = manager.takePhoto({ format: 'png', quality: 1 })
console.log(photo.dataUrl)
限时录制
await manager.start({
duration: 10000, // 10 秒后自动停止
returnType: ['blobUrl', 'blob']
})
使用约束预设
import { getConstraintsByScenario } from '@/uni_modules/jz-screen-capture/js/index.js'
const constraints = getConstraintsByScenario('tutorial')
await manager.start(constraints)
视频转换(WebM → MP4)
使用内置 ffmpeg.wasm 将录制的 WebM 视频转换为 MP4 格式,纯浏览器端运行,无需服务器。
基础用法
import {
getScreenCaptureManager,
VideoConverter
} from '@/uni_modules/jz-screen-capture/js/index.js'
const manager = getScreenCaptureManager()
// 创建转换器(multiThread: 'auto' 自动检测跨源隔离)
const converter = new VideoConverter({
log: false,
multiThread: 'auto'
})
// 设置转换器到 manager
manager.setConverter(converter)
// 预加载转换器(推荐)
await converter.load()
// 录制
await manager.start({
returnType: ['blobUrl', 'blob'],
audio: true
})
// 停止录制并自动转换
const result = await manager.stopAndConvert({
quality: 'medium', // high | medium | low
outputFileName: 'output'
})
console.log(result.mp4.blobUrl) // MP4 Blob URL
console.log(result.mp4.size) // MP4 文件大小
手动转换
manager.stop()
manager.onStop(async (recordResult) => {
if (recordResult.blob) {
const mp4Result = await converter.convertWebmToMp4(recordResult.blob, {
quality: 'medium'
})
console.log(mp4Result)
}
})
多线程加速
ffmpeg.wasm 多线程需要服务器配置以下 CORS 响应头:
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
Vite 开发服务器配置示例:
// vite.config.js
export default defineConfig({
server: {
headers: {
'Cross-Origin-Embedder-Policy': 'require-corp',
'Cross-Origin-Opener-Policy': 'same-origin',
}
}
})
如果环境不支持跨源隔离,VideoConverter 会自动降级到单线程模式,功能不受影响,仅转换速度较慢。
API 参考
能力检测
canCapture() // 当前端是否可发起屏幕录制
canCaptureAudio() // 是否可采集系统音频
getPlatformInfo() // 获取平台信息
录制管理器
const manager = getScreenCaptureManager()
// 录制控制
manager.start(options)
manager.pause()
manager.resume()
manager.stop()
manager.takePhoto(options)
manager.download(options)
// 状态查询
manager.getState() // idle | recording | paused
manager.getDuration() // 录制时长(秒)
manager.getStream() // 输出 MediaStream
manager.getVideoTracks() // 视频轨道
manager.getAudioTracks() // 音频轨道
manager.hasVideoTrack()
manager.hasAudioTrack()
manager.getRecordingSize() // 录制大小(字节)
manager.getDisplaySurface() // 共享源类型
// 事件监听
manager.onStart(callback)
manager.onPause(callback)
manager.onResume(callback)
manager.onStop(callback)
manager.onError(callback)
manager.onRegionSelected(callback)
manager.onRegionChange(callback)
manager.onProgress(callback)
manager.onStreamChange(callback)
// 视频转换
manager.setConverter(converter)
manager.getConverter()
manager.getConvertState() // idle | loading | converting
manager.getConvertResult()
manager.stopAndConvert(options)
manager.convert(blob, options)
manager.onConvertProgress(callback)
manager.onConvertComplete(callback)
manager.onConvertError(callback)
start(options) 参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| width | number | 1920 | 期望宽度 |
| height | number | 1080 | 期望高度 |
| frameRate | number | 30 | 帧率 |
| cursor | string | 'always' | always | motion | never |
| displaySurface | string | null | monitor | window | browser | null |
| audio | boolean | true | 是否采集系统音频 |
| microphone | boolean | false | 是否采集麦克风 |
| microphoneConstraints | Object | null | 自定义麦克风约束 |
| mimeType | string | 'auto' | auto | video/webm;codecs=vp9 | ... |
| bitRate | number | 2500000 | 视频码率 |
| audioBitRate | number | 128000 | 音频码率 |
| region | null|Object|string | null | null=全屏 | {x,y,width,height} | 'interactive' |
| returnType | string[] | ['blobUrl'] | blob | arrayBuffer | base64 | dataUrl | blobUrl |
| fileName | string | 'screen-record' | 导出文件名 |
| duration | number | 0 | 0=不限时,>0=自动停止毫秒数 |
onStop 返回的 result
{
duration: 10.5, // 录制时长(秒)
size: 5242880, // 数据大小(字节)
mimeType: 'video/webm', // MIME 类型
blob: Blob, // returnType 包含 'blob'
blobUrl: 'blob:...', // returnType 包含 'blobUrl'
arrayBuffer: ArrayBuffer,// returnType 包含 'arrayBuffer'
base64: '...', // returnType 包含 'base64'
dataUrl: 'data:...' // returnType 包含 'dataUrl'
}
约束预设
getConstraintsByScenario('default') // 默认 1080p 30fps
getConstraintsByScenario('high-quality') // 4K 60fps
getConstraintsByScenario('low-latency') // 720p 15fps
getConstraintsByScenario('presentation') // 1080p 24fps
getConstraintsByScenario('tutorial') // 1280x720 15fps(含麦克风)
VideoConverter API
构造选项
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| log | boolean | false | 是否输出 ffmpeg 日志(调试用) |
| multiThread | boolean|string | 'auto' | true=强制多线程 | false=强制单线程 | 'auto'=自动检测 |
| corePath | string | null | ffmpeg-core.js 自定义路径 |
| wasmPath | string | null | ffmpeg-core.wasm 自定义路径 |
| workerPath | string | null | ffmpeg-core.worker.js 自定义路径 |
| basePath | string | '' | 基础路径(自定义资源加载) |
方法
// 加载 ffmpeg.wasm
await converter.load()
// 状态查询
converter.isLoaded() // 是否已加载
converter.isLoading() // 是否正在加载
converter.getLoadProgress() // 加载进度 0-100
converter.isMultiThread() // 当前是否启用多线程
VideoConverter.canMultiThread() // 静态方法,环境是否支持多线程
// WebM 转 MP4
const result = await converter.convertWebmToMp4(blob, {
quality: 'medium', // high(4M) | medium(2M) | low(1M)
outputFileName: 'output'
})
// 通用转换
const result = await converter.convert(inputBlob, 'webm', 'mp4', options)
// 转换状态
converter.isConverting() // 是否正在转换
converter.getConvertProgress() // 转换进度 0-100
// 资源释放
converter.terminate()
converter.revokeBlobUrl(blobUrl)
事件
converter.onLoadProgress((data) => {
console.log('加载进度:', data.progress, data.stage)
})
converter.onLoaded(() => {
console.log('加载完成')
})
converter.onLoadError((err) => {
console.error('加载失败:', err)
})
converter.onConvertStart((data) => {
console.log('开始转换:', data.inputSize)
})
converter.onConvertProgress((data) => {
console.log('转换进度:', data.progress, data.detail)
})
converter.onConvertComplete((result) => {
console.log('转换完成:', result.size, result.blobUrl)
})
converter.onConvertError((err) => {
console.error('转换失败:', err)
})
转换结果
{
blob: Blob, // MP4 Blob 对象
blobUrl: string, // blob: URL,可用于 <video> 播放
size: number, // 文件大小(字节)
mimeType: 'video/mp4', // MIME 类型
format: 'mp4', // 格式
inputSize: number, // 原始文件大小
compressionRatio: number // 压缩比率(百分比)
}
转换质量预设
| 预设 | 视频码率 | 音频码率 | CRF | 编码预设 |
|---|---|---|---|---|
| high | 4M | 192k | 18 | veryfast |
| medium | 2M | 128k | 23 | veryfast |
| low | 1M | 96k | 28 | ultrafast |
RegionSelector(独立使用)
import { RegionSelector } from '@/uni_modules/jz-screen-capture/js/index.js'
const selector = new RegionSelector({
mode: 'free', // free | fixed
aspectRatio: null, // fixed 模式下的固定比例
minWidth: 100,
minHeight: 100,
borderColor: '#1890ff',
backgroundColor: 'rgba(0,0,0,0.5)',
showSize: true,
allowMove: true,
allowResize: true
})
selector.on('selected', (region) => {
console.log('选中区域', region)
selector.hide()
})
selector.on('cancel', () => {
console.log('取消选择')
})
selector.show()
RegionPreviewSelector(独立使用)
import { RegionPreviewSelector } from '@/uni_modules/jz-screen-capture/js/index.js'
const selector = new RegionPreviewSelector({
stream: mediaStream, // 采集流
mode: 'frame' // frame | live
})
selector.on('selected', ({ viewport, stream }) => {
console.log('视口坐标', viewport)
console.log('原始坐标', stream) // 用于 Canvas 裁剪
selector.hide()
})
selector.show()
内置文件结构
js/
├── core/
│ ├── ScreenCaptureManagerBase.js # 管理器基类(状态、事件、转换集成)
│ ├── ScreenCaptureManager.js # 管理器实现(getDisplayMedia + MediaRecorder)
│ ├── ScreenCaptureManagerFacade.js# 外观类(单例 + 平台检测)
│ ├── RegionSelector.js # 交互式区域选择器
│ ├── RegionPreviewSelector.js # 预览背景区域选择器(坐标映射)
│ └── VideoConverter.js # 视频转换器(ffmpeg.wasm)
├── common/
│ ├── EventEmitter.js # 事件总线基类
│ ├── ScreenCaptureDetector.js # 平台/能力检测
│ ├── ScreenCaptureConstraints.js # 约束预设
│ └── ScreenCaptureDataSource.js # 数据源转换工具
└── libs/ffmpeg/
├── ffmpeg/ # @ffmpeg/ffmpeg ESM 运行时
├── util/ # @ffmpeg/util ESM 运行时
├── core/ # 单线程 ffmpeg-core(@ffmpeg/core)
│ ├── ffmpeg-core.js
│ └── ffmpeg-core.wasm
└── core-mt/ # 多线程 ffmpeg-core(@ffmpeg/core-mt)
├── ffmpeg-core.js
├── ffmpeg-core.wasm
└── ffmpeg-core.worker.js
ffmpeg.wasm 版本: 0.12.10(单线程 + 多线程双核心)
注意事项
- 屏幕录制需要浏览器支持
navigator.mediaDevices.getDisplayMedia和MediaRecorder。 - 屏幕采集必须运行在 HTTPS 或
localhost。 - 移动端不支持屏幕录制,请使用 PC 浏览器。
- 是否能采集系统音频由浏览器和用户选择的共享源决定(Chrome/Edge 支持)。
- 区域选择录制通过 Canvas 裁剪实现,需要浏览器支持
canvas.captureStream()。 - ffmpeg.wasm 核心文件体积较大(约 32MB),首次加载需要时间,建议预加载。
- 多线程模式可显著提升转换速度(约 3~5 倍),但需要服务器配置 COOP/COEP 响应头。
- 转换完成后记得调用
converter.terminate()释放资源。 - 使用完 Blob URL 后可调用
URL.revokeObjectURL()或converter.revokeBlobUrl()释放内存。 - 停止页面或组件卸载时,请调用
stop()或destroyScreenCaptureManager()释放资源。

收藏人数:
下载插件并导入HBuilderX
下载插件ZIP
赞赏(0)
下载 2408
赞赏 0
下载 12290912
赞赏 1922
赞赏
京公网安备:11010802035340号