更新记录
1.2.1(2026-07-12)
更新文档
1.2.0(2026-07-12)
- 首次发布 Android/iOS 音视频裁剪、压缩与 FFmpeg/FFprobe 命令能力。
平台兼容性
uni-app(4.85)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | 5.0 | 1.2.1 | 12 | 1.2.1 | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
uni-app x(4.85)
| Chrome | Safari | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|---|---|
| - | - | 5.0 | 1.2.1 | 12 | 1.2.1 | - | - |
hl-ffmpeg-video
hl-ffmpeg-video 是一个运行在 Android 和 iOS 手机上的本地音视频处理插件。它可以裁剪、压缩、取帧、提取音频、拼接视频、生成 GIF,也可以直接执行 FFmpeg 和 FFprobe 命令。
所有处理都在设备本地完成。插件不会上传视频,也不会收集用户数据。
先了解这三件事
- 插件只处理本地视频文件,不能直接传网络 URL。
- 必须使用包含本插件的自定义基座或云端打包后的 App。标准基座不包含 FFmpeg 依赖。
- 所有处理结果都在回调里返回。成功时读取路径字段,例如
result.mp4、result.image或result.audio。
支持的平台
| 平台 | 最低版本 | 说明 |
|---|---|---|
| Android | Android 5.0(API 21) | 支持 armeabi-v7a、arm64-v8a、x86、x86_64 |
| iOS | iOS 12.0 | 支持 arm64 设备 |
| Web、小程序、HarmonyOS | 不支持 | 没有原生 FFmpeg 运行环境 |
第一次使用
1. 导入插件
插件放在项目的 uni_modules 目录时,不需要额外安装。
import { getVideoEditor } from '@/uni_modules/hl-ffmpeg-video'
const editor = getVideoEditor()
2. 选择视频并保存本地路径
uni.chooseVideo 返回的 tempFilePath 可以直接传给插件。
import { ref } from 'vue'
const videoPath = ref('')
function chooseVideo() {
uni.chooseVideo({
sourceType: ['album', 'camera'],
compressed: false,
success: (file) => {
videoPath.value = file.tempFilePath
}
})
}
如果你使用 _doc、_www 一类目录,请先转换为绝对路径:
const videoPath = plus.io.convertLocalFileSystemURL('_doc/source.mp4')
3. 用最小示例验证插件
先读取视频信息。看到 code: 0 即说明视频路径和原生依赖可用。
editor.getVideoInfo({ url: videoPath.value }, (result) => {
if (result.code === 0) {
console.log('视频尺寸:', result.width, result.height)
console.log('视频时长:', result.duration, '秒')
return
}
console.error('读取失败:', result.msg)
})
最常用:比例裁剪
下面的示例会打开原生裁剪页面。用户可以拖动裁剪框和时间滑块,点击“完成”后生成一条 9:16、720p 的视频。
editor.openCrop({
url: videoPath.value,
ratio: '9/16',
resolution: '720p',
mode: 'scale',
quality: 'hd',
mintime: 2000,
maxtime: 30,
codecs: 1,
fps: 30,
gop: 60
}, (result) => {
if (result.code === 1 && result.progress != null) {
console.log('处理进度:', result.progress)
return
}
if (result.code === 0) {
console.log('视频路径:', result.mp4)
console.log('封面路径:', result.image)
return
}
console.error(result.msg, result.detail || '')
})
mode 的含义:
| 值 | 适用场景 |
|---|---|
scale |
先按裁剪框裁剪,再输出指定比例。适合去掉画面边缘。 |
fill |
保留完整画面,等比缩放后用留边补满目标尺寸。适合不希望裁掉内容。 |
全部能力一览
| 方法 | 用途 | 成功结果的主要字段 |
|---|---|---|
openCrop |
打开固定比例裁剪页面 | mp4、image、duration、size |
openFreeCut |
打开自由裁剪页面 | mp4;或仅返回裁剪区域 |
videoToZip |
不打开页面,直接截取或压缩视频 | mp4、image、duration、size |
getVideoInfo |
读取时长、尺寸、帧率、码率等 | duration、width、height 等 |
getVideoFirstFrame |
提取第一帧图片 | image |
getVideoFrame |
提取指定时间点图片 | image |
generateThumbnails |
批量生成缩略图 | images、count |
extractAudio |
从视频提取 M4A 或 MP3 | audio、format |
removeAudio |
生成无声视频 | mp4 |
mergeAudioVideo |
用音频替换视频音轨 | mp4 |
concatVideos |
按顺序拼接多个视频 | mp4 |
videoToGif |
将视频片段转为 GIF | gif |
cancel |
取消当前媒体处理任务 | 无 |
deleteCache |
清理插件默认输出目录 | 无 |
FFmpeg |
执行 FFmpeg 命令并接收日志 | 回调 code、msg |
FFprobe |
执行 FFprobe 命令并接收日志 | 通过日志回调返回 |
ffmpegCancel |
取消 FFmpeg 启动的命令 |
无 |
常用调用示例
直接压缩到 720p
editor.videoToZip({
url: videoPath.value,
resolutionMax: '720p',
quality: 'hd',
codecs: 1,
startTime: 0,
endTime: 10_000
}, (result) => {
if (result.code === 0) console.log(result.mp4)
})
获取首帧和第 5 秒画面
editor.getVideoFirstFrame({ url: videoPath.value, width: 720 }, (result) => {
if (result.code === 0) console.log('首帧:', result.image)
})
editor.getVideoFrame({ url: videoPath.value, timeMs: 5000, width: 720 }, (result) => {
if (result.code === 0) console.log('第 5 秒画面:', result.image)
})
生成 6 张缩略图
editor.generateThumbnails({
url: videoPath.value,
startTime: 0,
intervalMs: 2000,
count: 6,
width: 320
}, (result) => {
if (result.code === 0) console.log(result.images)
})
提取音频、生成无声视频、替换音轨
editor.extractAudio({ url: videoPath.value, format: 'm4a', bitrate: '192k' }, (audioResult) => {
if (audioResult.code !== 0) return
editor.mergeAudioVideo({
url: videoPath.value,
audioUrl: audioResult.audio
}, (mergeResult) => {
if (mergeResult.code === 0) console.log('新视频:', mergeResult.mp4)
})
})
editor.removeAudio({ url: videoPath.value }, (result) => {
if (result.code === 0) console.log('无声视频:', result.mp4)
})
拼接视频和生成 GIF
editor.concatVideos({
urls: [firstVideoPath, secondVideoPath]
}, (result) => {
if (result.code === 0) console.log('拼接结果:', result.mp4)
})
editor.videoToGif({
url: videoPath.value,
startTime: 1000,
durationMs: 3000,
width: 480,
fps: 12
}, (result) => {
if (result.code === 0) console.log('GIF:', result.gif)
})
执行 FFmpeg 和 FFprobe
命令可以带 ffmpeg / ffprobe 前缀,也可以只传参数。路径中有空格时请用单引号包住。
const input = videoPath.value
const cover = plus.io.convertLocalFileSystemURL('_doc/cover.jpg')
editor.FFmpeg(
{ command: `ffmpeg -y -ss 1 -i '${input}' -frames:v 1 '${cover}'` },
(log) => console.log(log),
(result) => console.log(result)
)
editor.FFprobe(
{ command: `ffprobe -i '${input}' -show_streams -show_format` },
(log) => console.log(log)
)
参数说明
所有生成文件的方法
| 参数 | 类型 | 说明 |
|---|---|---|
url |
string |
本地视频绝对路径,必填。可以带 file://。 |
saveDirectory |
string |
输出目录绝对路径。省略时使用插件缓存目录。 |
裁剪、压缩和导出参数
| 参数 | 推荐值或范围 | 说明 |
|---|---|---|
resolution |
360p、480p、720p、1080p |
固定输出宽度。 |
resolutionMax |
同上 | 只在原视频超过该宽度时缩小。 |
ratio |
1/1、9/16、16/9 |
输出比例;不传则保持原比例。 |
mode |
scale、fill |
裁剪或留边策略。 |
quality |
ld、sd、hd、ssd |
预设码率等级。一般选择 hd。 |
bitrate |
例如 2500k |
明确指定视频码率,优先级高于 quality。 |
codecs |
0、1、2 |
0 为平台硬编码,1 为 H.264,2 为 H.265。iOS 会使用系统 VideoToolbox 编码器。 |
fps |
例如 30 |
输出帧率;0 保持原帧率。 |
gop |
例如 60 |
关键帧间隔;0 使用编码器默认值。 |
startTime、endTime |
毫秒 | 无界面截取的开始和结束时间;endTime: 0 表示到结尾。 |
saveToAlbum |
true、false |
成功后保存到系统相册。首次使用会请求系统权限。 |
crf 是软件编码质量参数。移动端首次接入建议先使用 quality,不必设置 crf。如同时设置 bitrate 和 crf,bitrate 优先。
裁剪界面额外参数
| 参数 | 说明 |
|---|---|
mintime |
最短可选时长,单位毫秒,默认 2000。 |
maxtime |
最长可选时长,单位秒,0 表示不限。 |
showModeButton |
是否显示“裁剪/填充”切换按钮。 |
backgroundColor |
裁剪页面背景色,例如 #141414。 |
setCropFrameColor |
裁剪框颜色。 |
isCrop |
仅 openFreeCut 使用。设为 false 时只返回选中的裁剪区域,不生成视频。 |
isHideCropFrame |
仅 openFreeCut 使用。是否隐藏裁剪框。 |
cropFrameParam |
网格配置,例如 { isShowGrid: true, gridNumber: 3, dragBlock4or8: true }。 |
回调结果和进度
每个回调至少包含 code 和 msg。
code |
含义 | 处理方式 |
|---|---|---|
0 |
成功 | 读取当前方法的结果字段。 |
1 且有 progress |
正在处理 | progress 范围为 0-99。成功时即为 100%。 |
1 且没有 progress |
已取消 | 可以恢复页面按钮状态。 |
| 负数 | 失败 | 查看 msg,高级方法还可查看 detail。 |
失败时建议同时输出 result.msg 和 result.detail:
if (result.code < 0) {
console.error(result.msg)
console.error(result.detail || '')
}
常见问题
提示找不到 FFmpeg 或原生类
当前运行的不是新制作的自定义基座。重新制作并安装基座后再运行项目;普通标准基座无法加载本插件的原生依赖。
提示文件不存在或无法读取视频
确认传入的是 App 可访问的本地绝对路径。不要直接传 _doc/a.mp4,应先通过 plus.io.convertLocalFileSystemURL() 转换。
处理完成后找不到输出文件
先使用回调中的 mp4、image、audio 或 gif 路径。未设置 saveDirectory 时,文件位于插件缓存目录;调用 deleteCache() 会清理这些默认输出。
处理失败如何定位
打印 result.detail。其中包含 FFmpeg 日志和失败时实际执行的命令。常见原因包括输入路径错误、输出目录不可写、视频编码不受支持或参数超出视频尺寸。
iOS 比例裁剪或压缩失败
iOS 使用 h264_videotoolbox 或 hevc_videotoolbox 进行编码。请使用本插件最新版本制作自定义基座,不要在 iOS 上手动指定 libx264 或 libx265。

收藏人数:
购买普通授权版(
试用
赞赏(0)
下载 276
赞赏 2
下载 12417505
赞赏 1933
赞赏
京公网安备:11010802035340号