更新记录
1.0.0(2026-11-13) 下载此版本
视频压缩(yy-videocompress)
纯 Android 系统 API 实现的视频压缩原生插件,不携带任何第三方 so,aar 仅 18KB。
功能
对已有视频文件做一次转码压缩,输出体积更小的 mp4。适用于作业类、巡检类 App 上传现场录像前把 40~80MB 的原片压到 3~6MB。
- 硬解硬编直连:
MediaExtractor解封装 →MediaCodec解码 → 编码器输入 Surface 直连 →MediaMuxer重封装,全程不经过 CPU 内存拷贝,不产生 YUV 中间数据 - 分辨率降级链:按源尺寸、1280、960、640 逐档尝试,某档编码器不认才降下一档,四档全失败才报错
- 旋转信息保留:读取源
rotation并写入setOrientationHint,竖屏录像压完不会变横屏 - 音频直通:采样率与声道不变时不重编码,速度快且无二次损伤
- 单线程串行队列:内部排队,不并发抢
MediaCodec实例(低端手持机通常只有 2~4 个编码器实例,并发即失败) - 输出落应用私有目录:不需要任何存储权限,Android 10 / 11 / 12+ 行为一致
- 源文件未写完保护:进转码前轮询等文件大小稳定,避免录制刚结束时读到不完整的 moov
兼容性
| 项 | 支持范围 |
|---|---|
| 平台 | Android |
| 最低版本 | Android 5.0(API 21) |
| CPU 架构 | 不限(纯 Java,无 so) |
| 权限 | 不需要申请任何权限 |
| 需用 | 云打包、离线打包均可(云打包需上架市场) |
前置条件
插件不申请存储权限,因此只能读取宿主 App 自己有权限访问的路径。录制产生的文件位于应用私有目录(getExternalFilesDir 下)时可直接使用;若要处理相册或外置卡的任意视频,需宿主 App 自行申请 READ_MEDIA_VIDEO(Android 13+)或 READ_EXTERNAL_STORAGE 后再传路径进来。
使用方法
const vc = uni.requireNativePlugin('yy-videocompress-YYVideoCompressModule');
vc.compress({
inPath: '/storage/emulated/0/Android/data/<包名>/files/xxx.mp4',
bitrate: 1800000,
frameRate: 24
}, (res) => {
if (res.done) {
console.log('压缩完成', res.outPath, res.outBytes);
}
}, (err) => {
console.log('压缩失败', err.code, err.message);
});
参数
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
| inPath | String | 必填 | 源文件绝对路径,带不带 file:// 均可 |
| outPath | String | 空 | 不传则输出到源文件同目录,命名 原名_c.mp4,重名自动加序号 |
| bitrate | Number | 1800000 | 目标码率,会按缩放比例折算并夹到编码器支持区间 |
| frameRate | Number | 24 | 目标帧率,上限 60 |
| maxWidth | Number | 0 | 0 表示跟随源尺寸;指定后以此宽度为第一档再逐档降 |
| timeoutMs | Number | 120000 | 单档超时,超时后自动换下一档继续,不整体失败 |
回调
进度回调走第二个参数,字段 done: false、progress: 0~100,可多次触发:
{ done: false, progress: 45 }
终态只回调一次。
成功:
{ done: true, outPath: '/xxx/xxx_c.mp4', outBytes: 4123456, srcBytes: 41234567 }
失败:
{ done: false, code: 1002, message: '四档降级均失败: 1280px: ...' }
其他方法
// 读取视频信息,用于判断是否值得压缩
vc.info({ inPath: '...' }, (res) => {
// { done: true, width, height, rotation, durationMs, bitrate, bytes }
});
// 查询队列积压数
vc.pending((res) => { console.log(res.pending); });
// 取消当前任务及队列中后续任务
vc.cancel();
错误码
| code | 含义 | 建议处理 |
|---|---|---|
| 1001 | 源文件不存在、不可读或无视频轨 | 不要重试,直接用原文件 |
| 1002 | 四档降级全部失败 | 可重试一次,仍失败则用原文件 |
| 1003 | 解码异常,源文件多半被截断 | 不要重试 |
| 1004 | 编码异常,codec 被回收 | 可重试一次 |
| 1005 | 输出文件创建失败 | 检查剩余存储空间 |
| 1006 | 单档超时 | 内部已自动降档,一般不会外抛 |
注意事项
- 压缩耗时与视频时长、分辨率正相关,1080p、30 秒的视频在低端手持机上约需 20~40 秒,建议在界面上给出进度提示
- 插件内部串行处理,同时提交多条任务时会依次排队,可用
pending()取积压数 - 压缩失败时务必保留原文件,不要直接删除,避免数据丢失
- 不支持 Kotlin,插件本身为 Java 实现
更新记录
1.0.0
- 首个版本,支持分辨率降级、旋转保留、音频直通、队列串行与取消
平台兼容性
uni-app(5.04)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | 5.0 | - | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
视频压缩(yy-videocompress)
纯 Android 系统 API 实现的视频压缩原生插件,不携带任何第三方 so,aar 仅 18KB。
功能
对已有视频文件做一次转码压缩,输出体积更小的 mp4。适用于作业类、巡检类 App 上传现场录像前把 40~80MB 的原片压到 3~6MB。
- 硬解硬编直连:
MediaExtractor解封装 →MediaCodec解码 → 编码器输入 Surface 直连 →MediaMuxer重封装,全程不经过 CPU 内存拷贝,不产生 YUV 中间数据 - 分辨率降级链:按源尺寸、1280、960、640 逐档尝试,某档编码器不认才降下一档,四档全失败才报错
- 旋转信息保留:读取源
rotation并写入setOrientationHint,竖屏录像压完不会变横屏 - 音频直通:采样率与声道不变时不重编码,速度快且无二次损伤
- 单线程串行队列:内部排队,不并发抢
MediaCodec实例(低端手持机通常只有 2~4 个编码器实例,并发即失败) - 输出落应用私有目录:不需要任何存储权限,Android 10 / 11 / 12+ 行为一致
- 源文件未写完保护:进转码前轮询等文件大小稳定,避免录制刚结束时读到不完整的 moov
兼容性
| 项 | 支持范围 |
|---|---|
| 平台 | Android |
| 最低版本 | Android 5.0(API 21) |
| CPU 架构 | 不限(纯 Java,无 so) |
| 权限 | 不需要申请任何权限 |
| 需用 | 云打包、离线打包均可(云打包需上架市场) |
前置条件
插件不申请存储权限,因此只能读取宿主 App 自己有权限访问的路径。录制产生的文件位于应用私有目录(getExternalFilesDir 下)时可直接使用;若要处理相册或外置卡的任意视频,需宿主 App 自行申请 READ_MEDIA_VIDEO(Android 13+)或 READ_EXTERNAL_STORAGE 后再传路径进来。
使用方法
const vc = uni.requireNativePlugin('yy-videocompress-YYVideoCompressModule');
vc.compress({
inPath: '/storage/emulated/0/Android/data/<包名>/files/xxx.mp4',
bitrate: 1800000,
frameRate: 24
}, (res) => {
if (res.done) {
console.log('压缩完成', res.outPath, res.outBytes);
}
}, (err) => {
console.log('压缩失败', err.code, err.message);
});
参数
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
| inPath | String | 必填 | 源文件绝对路径,带不带 file:// 均可 |
| outPath | String | 空 | 不传则输出到源文件同目录,命名 原名_c.mp4,重名自动加序号 |
| bitrate | Number | 1800000 | 目标码率,会按缩放比例折算并夹到编码器支持区间 |
| frameRate | Number | 24 | 目标帧率,上限 60 |
| maxWidth | Number | 0 | 0 表示跟随源尺寸;指定后以此宽度为第一档再逐档降 |
| timeoutMs | Number | 120000 | 单档超时,超时后自动换下一档继续,不整体失败 |
回调
进度回调走第二个参数,字段 done: false、progress: 0~100,可多次触发:
{ done: false, progress: 45 }
终态只回调一次。
成功:
{ done: true, outPath: '/xxx/xxx_c.mp4', outBytes: 4123456, srcBytes: 41234567 }
失败:
{ done: false, code: 1002, message: '四档降级均失败: 1280px: ...' }
其他方法
// 读取视频信息,用于判断是否值得压缩
vc.info({ inPath: '...' }, (res) => {
// { done: true, width, height, rotation, durationMs, bitrate, bytes }
});
// 查询队列积压数
vc.pending((res) => { console.log(res.pending); });
// 取消当前任务及队列中后续任务
vc.cancel();
错误码
| code | 含义 | 建议处理 |
|---|---|---|
| 1001 | 源文件不存在、不可读或无视频轨 | 不要重试,直接用原文件 |
| 1002 | 四档降级全部失败 | 可重试一次,仍失败则用原文件 |
| 1003 | 解码异常,源文件多半被截断 | 不要重试 |
| 1004 | 编码异常,codec 被回收 | 可重试一次 |
| 1005 | 输出文件创建失败 | 检查剩余存储空间 |
| 1006 | 单档超时 | 内部已自动降档,一般不会外抛 |
注意事项
- 压缩耗时与视频时长、分辨率正相关,1080p、30 秒的视频在低端手持机上约需 20~40 秒,建议在界面上给出进度提示
- 插件内部串行处理,同时提交多条任务时会依次排队,可用
pending()取积压数 - 压缩失败时务必保留原文件,不要直接删除,避免数据丢失
- 不支持 Kotlin,插件本身为 Java 实现
更新记录
1.0.0
- 首个版本,支持分辨率降级、旋转保留、音频直通、队列串行与取消

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