更新记录
1.0.0(2026-08-21)
首个正式版本。
核心能力
- 统一 Android(ffmpeg-kit)、iOS(ffmpeg_kit)、Harmony(@sj/ffmpeg)的 FFmpeg / FFprobe 调用入口。
- 提供 17 个高层语义封装(recipes),支持视频 / 音频裁剪、合并、格式转换、获取媒体信息与图片处理等常见场景。
- 结构化媒体信息解析:
readMediaProfile自动解析info.videoStreams/info.audioStreams/info.allProperties。 - 任务管理能力:支持
queryTaskList/isRunning/abortTask/dispose,并内置进度回调。 - 路径与同步工具:
resolveLocalPath/getCachePath/getWorkDir/executeCommandSync/getMediaFileInfoSync/setLogEnabled。 - Demo 组件(
<lime-ffmpeg />)覆盖全部 17 个高层封装 + 核心 API,按功能分卡片组织,通用回调ok/ng统一收敛日志样板。
平台兼容性
uni-app(5.12)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | - | - | √ | √ | 5.0 | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
uni-app x(5.12)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| - | - | 5.0 | √ | √ | - |
lime-ffmpeg 多媒体处理
- 跨平台 FFmpeg / FFprobe 插件,统一 Android、iOS、Harmony 的调用入口。
- 支持视频转码、裁剪、合并、提取音频、截图等 FFmpeg 全部能力,以及 ffprobe 媒体信息探测。
安装
插件市场导入,在页面引入,自定义基座。
自定义基座说明:
- 本插件使用 UTS 原生能力(Android / iOS / Harmony),必须在自定义基座中运行,标准基座无法使用。
- CLI 项目特别注意:请检查根目录
package.json,确保所有@dcloudio/*相关包的版本号一致,且与当前 HBuilderX 版本对齐。版本不一致会导致自定义基座编译失败或运行异常。
代码演示
关于 TypeScript 类型:下方示例中的
as RunFFmpegOptions断言与type RunFFmpegOptions类型导入仅用于 TypeScript 环境的编译期类型检查,运行时完全不存在(不影响执行)。
- TS 项目(uni-app 默认模板):照示例原样使用即可,带
as/type能获得类型提示与校验。- 纯 JS 项目(非 TS):整段省略——不写
type ...导入、也不写as ...,直接传普通对象调用函数,行为完全一致。
视频转码(runFFmpeg)
command:完整 ffmpeg 命令(不含 ffmpeg 前缀)。
回调:start(任务创建)、progress(进度/统计)、log(日志)、success(仅成功)、complete(成功或失败都触发)、fail(仅失败)。
输出文件覆盖:底层已自动添加
-y参数强制覆盖已存在的输出文件。若需保留原文件,可在命令中添加-n参数(不覆盖)。
import { runFFmpeg, resolveLocalPath, getCachePath, type RunFFmpegOptions } from '@/uni_modules/lime-ffmpeg'
// 输入用 resolveLocalPath 转成平台绝对路径(绝对路径原样透传,file:// 去前缀)
const input = resolveLocalPath('/static/input.mp4') // 或文件选择返回的绝对路径
// 输出用 getCachePath 拼到缓存目录:getWorkDir() + 文件名
const output = getCachePath('output.mp4')
runFFmpeg({
command: `-i ${input} -vf scale=720:-2 ${output}`,
start(res) {
console.log('任务创建', res.sessionId)
},
progress(res) {
console.log('进度', res)
},
log(res) {
console.log('日志', res.message)
},
success(res) {
console.log('转码成功', res)
},
fail(err) {
console.log('失败', err)
},
complete(res) {
console.log('结束', res.stateLabel)
}
} as RunFFmpegOptions)
媒体探测(runFFprobe)
command:完整 ffprobe 命令(不含 ffprobe 前缀)。
import { runFFprobe, resolveLocalPath, type RunFFprobeOptions } from '@/uni_modules/lime-ffmpeg'
const input = resolveLocalPath('/static/input.mp4') // 待探测的真实媒体文件(绝对路径),转成平台路径
runFFprobe({
command: `-v quiet -print_format json -show_format -show_streams ${input}`,
success(res) {
console.log('探测成功', res)
},
fail(err) {
console.log('失败', err)
}
} as RunFFprobeOptions)
读取媒体信息(readMediaProfile)
path:媒体文件路径,内部自动调用 ffprobe,结果以 JSON 结构挂在 info.allProperties。
import { readMediaProfile, type ReadMediaProfileOptions } from '@/uni_modules/lime-ffmpeg'
readMediaProfile({
path: '/static/input.mp4',
success(res) {
// res.info.allProperties 为 ffprobe 返回的完整 JSON 对象
console.log('媒体信息', res.info?.allProperties)
},
fail(err) {
console.log('失败', err)
}
} as ReadMediaProfileOptions)
任务管理
import {
runFFmpeg,
abortTask,
abortAllTasks,
queryTaskList,
resolveLocalPath,
getCachePath,
type RunFFmpegOptions
} from '@/uni_modules/lime-ffmpeg'
// 启动并拿到 sessionId
let currentId = 0
// 输入用 resolveLocalPath 转成平台路径;输出用 getCachePath 拼到缓存目录
const input = resolveLocalPath('/static/input.mp4')
const output = getCachePath('output.mp4')
runFFmpeg({
command: `-i ${input} ${output}`,
start(res) { currentId = res.sessionId ?? 0 },
success() {},
fail() {}
} as RunFFmpegOptions)
// 取消单个任务(taskKey 可为 sessionId 或 command 字符串)
abortTask(currentId)
// 取消全部进行中的任务
abortAllTasks()
// 查询任务快照列表(每项含 taskKey,可直接用于 abortTask)
const list = queryTaskList()
console.log(list)
// 1) resolveLocalPath:把用户路径转成平台绝对路径(绝对路径原样透传,file:// 去前缀)
const inPath = resolveLocalPath('/static/input.mp4')
console.log(inPath)
// 2) getCachePath:把文件名拼到缓存目录,得到输出文件绝对路径(getWorkDir() + 文件名)
const outPath = getCachePath('output.mp4')
console.log(outPath)
结构化媒体信息(videoStreams / audioStreams)
readMediaProfile 的 success 回调中,res.info 除 allProperties(ffprobe 原始 JSON)外,还会自动解析出结构化的视频流 / 音频流数组,业务侧无需自行遍历 streams:
import { readMediaProfile, type ReadMediaProfileOptions } from '@/uni_modules/lime-ffmpeg'
readMediaProfile({
path: '/static/input.mp4',
success(res) {
const v = res.info?.videoStreams?.[0]
const a = res.info?.audioStreams?.[0]
if (v) console.log('视频', v.codec, v.width + 'x' + v.height, v.fps + 'fps', v.bitrate + 'bps')
if (a) console.log('音频', a.codec, a.sampleRate + 'Hz', a.channels + 'ch', a.channelLayout)
},
fail(err) { console.log('失败', err) }
} as ReadMediaProfileOptions)
高层语义封装(recipes)
除原始 runFFmpeg 外,插件内置一组「语义化封装」。业务侧无需手写 ffmpeg 命令,传入路径与选项即可。每个封装有自己专门的 XxxOptions(仅含该函数用到的字段 + 公共回调字段),FFmpegOptions 为内部合并类型、不对外暴露,内部统一委托 runFFmpeg。
路径自动解析(不用正则):每个封装在拼命令前,会按字段把 inputPath / outputPath / videoPath / audioPath / imagePath / overlayPath / inputPath1 / inputPath2 通过 resolveLocalPath 转成平台绝对路径(file:// 去前缀、相对路径落沙盒;绝对路径原样透传)——输入文件、用户指定的输出文件都走它。若想让输出落到缓存目录,把 getCachePath('文件名') 传给 outputPath 即可(getCachePath = getWorkDir() + 文件名)。file:// Uri 无需手动处理。Android / iOS 还会顺带创建输出父目录。仅原始 runFFmpeg(command)(路径嵌在自由字符串里)需你自己 resolveLocalPath / getCachePath 后再拼接。
import {
compressVideo, extractAudio, generateThumbnail, trimMedia, mergeAV,
mixAudio, convertFormat, replaceAudio, audioClip, videoSpeed,
videoCrop, durationClip, videoFilter, imageRemoveWatermark,
videoEffect, videoOpacity, videoPictureInPicture,
getCachePath,
type CompressVideoOptions, type ExtractAudioOptions, type GenerateThumbnailOptions,
type TrimMediaOptions, type MergeAVOptions, type MixAudioOptions, type ConvertFormatOptions,
type ReplaceAudioOptions, type AudioClipOptions, type VideoSpeedOptions, type VideoCropOptions,
type DurationClipOptions, type VideoFilterOptions, type ImageRemoveWatermarkOptions,
type VideoEffectOptions, type VideoOpacityOptions, type VideoPictureInPictureOptions
} from '@/uni_modules/lime-ffmpeg'
// 视频压缩 / 转码
// 注意:并非所有 ffmpeg 构建都含 libx264。
// 不显式指定 videoCodec 时,插件会让 ffmpeg 使用平台默认编码器;preset / crf 仅 libx264 / libx265 生效,
// 传给其它编码器会被自动忽略,不会报错。输出统一用 getCachePath 落到可写缓存目录。
// 下方每个调用都带 `as XxxOptions`(TS 类型断言);纯 JS 项目去掉 `as` 与 import 里的 `type` 导入即可,例如:
// compressVideo({ inputPath: '/static/input.mp4', outputPath: getCachePath('output.mp4'), resolution: '720p' })
compressVideo({
inputPath: '/static/input.mp4', outputPath: getCachePath('output.mp4'),
resolution: '720p', videoBitrate: '1000k', audioBitrate: '128k', fps: 30,
success(res) { console.log('压缩完成', res) }, fail(err) { console.log('失败', err) }
} as CompressVideoOptions)
// 提取音频(audioCodec:'copy' 无损提取;或 'aac' / 'mp3')
extractAudio({
inputPath: '/static/input.mp4', outputPath: getCachePath('out.aac'), audioCodec: 'copy',
success() {}, fail() {}
} as ExtractAudioOptions)
// 截图 / 缩略图
generateThumbnail({
inputPath: '/static/input.mp4', outputPath: getCachePath('thumb.jpg'),
time: '00:00:03', width: 320,
success() {}, fail() {}
} as GenerateThumbnailOptions)
// 按时间裁剪(copyCodec=true 流复制)
trimMedia({
inputPath: '/static/input.mp4', outputPath: getCachePath('clip.mp4'),
startTime: '00:00:05', duration: '00:00:10', copyCodec: true,
success() {}, fail() {}
} as TrimMediaOptions)
// 合并音视频
mergeAV({
videoPath: '/static/v.mp4', audioPath: '/static/a.aac', outputPath: getCachePath('merged.mp4'),
success() {}, fail() {}
} as MergeAVOptions)
// 双路音频混音
mixAudio({
inputPath1: '/static/a1.mp3', inputPath2: '/static/a2.mp3', outputPath: getCachePath('mix.mp3'),
volume1: 1.0, volume2: 0.6,
success() {}, fail() {}
} as MixAudioOptions)
// 格式转换(未指定编解码器时按纯转封装处理)
convertFormat({
inputPath: '/static/input.mp4', outputPath: getCachePath('output.mov'),
success() {}, fail() {}
} as ConvertFormatOptions)
// 替换音频轨(copyVideo=true 视频流复制)
replaceAudio({
videoPath: '/static/v.mp4', audioPath: '/static/a.aac', outputPath: getCachePath('out.mp4'),
copyVideo: true,
success() {}, fail() {}
} as ReplaceAudioOptions)
// 音频裁剪
audioClip({
audioPath: '/static/a.mp3', outputPath: getCachePath('clip.mp3'),
startTime: '00:00:10', duration: '00:00:30',
success() {}, fail() {}
} as AudioClipOptions)
// 视频倍速(>1 加速,<1 减速)
videoSpeed({
videoPath: '/static/v.mp4', outputPath: getCachePath('fast.mp4'), speed: 2.0,
success() {}, fail() {}
} as VideoSpeedOptions)
// 画面区域裁剪
videoCrop({
videoPath: '/static/v.mp4', outputPath: getCachePath('crop.mp4'),
x: 0, y: 0, width: 640, height: 360,
success() {}, fail() {}
} as VideoCropOptions)
// 按时间裁剪(inputPath 版)
durationClip({
inputPath: '/static/input.mp4', outputPath: getCachePath('clip.mp4'),
startTime: '00:00:05', duration: '00:00:10',
success() {}, fail() {}
} as DurationClipOptions)
// 视频滤镜(灰度 / 模糊 等)
videoFilter({
videoPath: '/static/v.mp4', outputPath: getCachePath('gray.mp4'),
filter: 'hue=s=0',
success() {}, fail() {}
} as VideoFilterOptions)
// 图片去水印
imageRemoveWatermark({
imagePath: '/static/img.png', outputPath: getCachePath('delogo.png'),
x: 10, y: 10, width: 80, height: 40,
success() {}, fail() {}
} as ImageRemoveWatermarkOptions)
// 视频特效
videoEffect({
videoPath: '/static/v.mp4', outputPath: getCachePath('fx.mp4'),
effect: 'grayscale',
success() {}, fail() {}
} as VideoEffectOptions)
// 视频透明度
videoOpacity({
videoPath: '/static/v.mp4', outputPath: getCachePath('alpha.mp4'),
opacity: 0.5,
success() {}, fail() {}
} as VideoOpacityOptions)
// 画中画
videoPictureInPicture({
videoPath: '/static/main.mp4', overlayPath: '/static/overlay.mp4', outputPath: getCachePath('pip.mp4'),
x: 10, y: 10, width: 200, height: 120,
success() {}, fail() {}
} as VideoPictureInPictureOptions)
API
runFFmpeg(options: RunFFmpegOptions)
执行 FFmpeg 转码命令。
runFFprobe(options: RunFFprobeOptions)
执行 ffprobe 探测命令。
readMediaProfile(options: ReadMediaProfileOptions)
读取媒体信息(内部调用 ffprobe,结果在 info.allProperties)。
abortTask(taskKey: number | string)
取消指定任务。taskKey 为 sessionId(number)或 command(string)。
abortAllTasks()
取消全部进行中的任务。
queryTaskList(): FFmpegTask[]
返回当前任务快照列表,每项含 taskKey、stateLabel、returnCode 等,可直接用于 abortTask。
resolveLocalPath(inputPath?: string): string
把用户路径转成平台绝对路径(file:// 去前缀、相对路径落沙盒;绝对路径原样透传)。输入文件、用户指定的输出文件都走它。
getCachePath(fileName: string): string
把文件名拼到平台缓存目录(getWorkDir())下,返回输出文件绝对路径。想让输出落在缓存时,把 getCachePath('文件名') 传给 outputPath 即可。
高层语义封装(recipes)
以下 17 个函数各自接收专门的 XxxOptions(对外强类型,字段按函数精确约束),FFmpegOptions 为内部合并类型、不对外暴露,内部统一委托 runFFmpeg:
compressVideo(options: CompressVideoOptions)— 视频压缩 / 转码extractAudio(options: ExtractAudioOptions)— 提取音频generateThumbnail(options: GenerateThumbnailOptions)— 截图 / 缩略图trimMedia(options: TrimMediaOptions)— 按时间裁剪(流复制优先)mergeAV(options: MergeAVOptions)— 合并音视频mixAudio(options: MixAudioOptions)— 双路音频混音convertFormat(options: ConvertFormatOptions)— 格式转换(未指定编解码器则纯转封装)replaceAudio(options: ReplaceAudioOptions)— 替换音频轨audioClip(options: AudioClipOptions)— 音频裁剪videoSpeed(options: VideoSpeedOptions)— 视频倍速videoCrop(options: VideoCropOptions)— 画面区域裁剪durationClip(options: DurationClipOptions)— 按时间裁剪(inputPath 版)videoFilter(options: VideoFilterOptions)— 视频滤镜imageRemoveWatermark(options: ImageRemoveWatermarkOptions)— 图片去水印videoEffect(options: VideoEffectOptions)— 视频特效videoOpacity(options: VideoOpacityOptions)— 视频透明度videoPictureInPicture(options: VideoPictureInPictureOptions)— 画中画
运维 / 调试
getVersion(): FFmpegKitVersion— 返回{ kit, ffmpeg, ffprobe }版本信息getWorkDir(): string— 返回引擎默认工作目录(缓存目录)setLogEnabled(options: SetLogEnabledOptions)— 开启 / 关闭日志回调({ enabled, success?, fail?, complete? })isRunning(sessionId: number): boolean— 判断某任务是否进行中dispose(sessionId: number): boolean— 取消并释放指定任务
同步执行
executeCommandSync(command: string): FFmpegPayload— 阻塞式执行 ffmpeg 命令(Android / iOS 真同步;Harmony 复用异步链路返回启动快照,建议优先用异步接口)getMediaFileInfoSync(path: string): FFmpegPayload— 阻塞式读取媒体信息
Options 字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| command | string | 必填,完整 ffmpeg / ffprobe 命令(不含 ffmpeg / ffprobe 前缀) |
| path | string | 必填(readMediaProfile),媒体文件路径 |
| timeout | number | 可选,超时毫秒数(readMediaProfile 生效,默认 5000) |
| start | (res: FFmpegPayload) => void | 任务创建时触发(runFFmpeg) |
| progress | (res: FFmpegPayload) => void | 进度 / 统计回调(runFFmpeg) |
| log | (res: FFmpegPayload) => void | 日志回调 |
| success | (res: FFmpegPayload) => void | 仅成功(COMPLETED 且 returnCode = 0)触发 |
| complete | (res: FFmpegPayload) => void | 成功或失败都触发 |
| fail | (res: FFmpegFail) => void | 仅失败(参数 / 环境 / 原生执行失败 / 不支持)触发 |
Payload(FFmpegPayload)字段说明
所有回调中的 res 均为 FFmpegPayload:
| 字段 | 类型 | 说明 |
|---|---|---|
| sessionId | number | 任务会话 ID |
| command | string | 执行的命令 |
| returnCode | number | 退出码,0 为成功 |
| state / stateCode | number | 状态码(1 = RUNNING 等) |
| stateLabel | FFmpegState | 状态标签:CREATED / RUNNING / FAILED / COMPLETED / CANCELLED / UNSUPPORTED |
| output | string | 命令标准输出 |
| allLogsAsString | string | 全部日志 |
| failStackTrace | string | 失败堆栈 |
| duration | number | 耗时(ms) |
| createTime / endTime | number | 创建 / 结束时间戳(ms) |
| platform | FFmpegPlatform | 运行平台 |
| isMediaInformation | boolean | 是否为媒体信息任务 |
| info | FFmpegMediaInfo | readMediaProfile 返回的媒体信息:info.allProperties 为 ffprobe 原始 JSON;info.videoStreams / info.audioStreams 为自动解析的结构化视频流 / 音频流数组(VideoStreamInfo / AudioStreamInfo) |
| unsupported | boolean | 是否为不支持平台占位 |
| parseError | string | 媒体信息 JSON 解析失败原因 |
| stage | string | 当前阶段(session-created / ffmpeg-log / ffmpeg-statistics / …) |
| level / speed / videoFps / bitrate / size / time | number | 日志级别 / 速度 / 帧率 / 码率 / 大小 / 耗时等进度统计字段 |
| tempFilePath | string | 高层封装(recipes)成功时回写的产物绝对路径。由 resolveLocalPath(outputPath) 解析得到,可直接用于读取/分享产物文件。success 回调里返回;runFFmpeg 原始命令与 unsupported 平台不回填此字段 |
错误码
fail 回调的 err 为 FFmpegFail 对象(errSubject / errCode / errMsg):
| errCode | 常量 | 说明 |
|---|---|---|
| 9010001 | PARAM_INVALID | 参数校验失败 |
| 9010002 | PATH_INVALID | 路径格式无效 |
| 9010003 | COMMAND_EMPTY | 命令为空 |
| 9010010 | UNSUPPORTED | 当前平台不支持(Web / 微信小程序) |
| 9010020 | NATIVE_FAILED | 原生执行失败 |
平台降级说明
Web 与微信小程序无 FFmpeg 引擎,调用任意函数会:
- 依次触发
start/log/progress(占位 payload,unsupported: true); - 触发
fail(errCode = UNSUPPORTED)与complete,不会触发success。
业务层建议:在 fail 中判断 err.errCode === 9010010 走降级提示,例如「当前环境不支持视频处理」。
文档
(如有线上文档可在此补充链接)
平台支持
| 平台 | 支持情况 |
|---|---|
| Android | ✅ 原生实现 |
| iOS | ✅ 原生实现 |
| Harmony(鸿蒙) | ✅ 原生实现 |
| Web | ⚠️ 占位 |
| 微信小程序 | ⚠️ 占位 |
Web 与微信小程序无 FFmpeg 引擎,所有函数仍可被编译调用,但会立即触发
fail回调,业务层据此判断降级(详见「平台降级说明」)。

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 73792
赞赏 596
下载 12522205
赞赏 1943
赞赏
京公网安备:11010802035340号