更新记录

1.0.0(2026-06-21) 下载此版本

核心能力

  • 屏幕采集:基于 getDisplayMedia API,支持屏幕 / 窗口 / 标签页采集
  • 区域选择录制:交互式框选(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(单线程 + 多线程双核心)

注意事项

  1. 屏幕录制需要浏览器支持 navigator.mediaDevices.getDisplayMediaMediaRecorder
  2. 屏幕采集必须运行在 HTTPS 或 localhost
  3. 移动端不支持屏幕录制,请使用 PC 浏览器。
  4. 是否能采集系统音频由浏览器和用户选择的共享源决定(Chrome/Edge 支持)。
  5. 区域选择录制通过 Canvas 裁剪实现,需要浏览器支持 canvas.captureStream()
  6. ffmpeg.wasm 核心文件体积较大(约 32MB),首次加载需要时间,建议预加载。
  7. 多线程模式可显著提升转换速度(约 3~5 倍),但需要服务器配置 COOP/COEP 响应头。
  8. 转换完成后记得调用 converter.terminate() 释放资源。
  9. 使用完 Blob URL 后可调用 URL.revokeObjectURL()converter.revokeBlobUrl() 释放内存。
  10. 停止页面或组件卸载时,请调用 stop()destroyScreenCaptureManager() 释放资源。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

麦克风数据 屏幕数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。