uni-app的video组件在多数平台不支持真正边下边播:H5和小程序端受限于HTTP Range及流式解码,iOS App因WKWebView限制对非完整m3u8敏感,nvue下HLS可行但MP4流式仍受限。

video组件不支持边下边播?先确认平台限制
uni-app 的 组件在 H5 和小程序端默认不支持真正的“边下边播”(即 HTTP Range 请求 + 流式解码),尤其是微信小程序,它强制要求视频资源必须完整加载后才能播放。Android App 端通过 webview 加载原生 时行为接近浏览器,但 iOS App 因 WKWebView 限制,对非完整响应的 m3u8/hls 支持更敏感;nvue 下的 则依赖原生能力,HLS 可行,MP4 流式播放仍受限。
所以别一上来就写逻辑缓存——先看你的目标平台和视频格式:
- 直播/实时流:优先走
m3u8+ HLS,用src 直接设为 m3u8 地址,iOS/Android/H5 均可原生支持(需服务端正确配置 CORS 和 MIME) - 点播大文件(如 100MB+ MP4):H5 可尝试
MediaSource Extensions (MSE),但 uni-app 不暴露底层 API,需自己封装 webview 插件或改用 nvue + 原生模块 - 小程序端:放弃“边下边播”幻想,转为预加载关键帧、分段下载 + 自定义播放器(如用 canvas 渲染 + 解码库,成本极高,不推荐)
真要缓存视频文件,别用 setStorage 存二进制
很多人想把视频 tempFilePath 下载后用 uni.setStorageSync('video_123', data) 存起来,这会直接触发内存溢出或 iOS 崩溃——Base64 或 ArrayBuffer 写入本地存储,不仅超限(小程序单 key ≤1MB),还会让 JS 引擎频繁 GC。
正确做法是走文件系统路径缓存:
- 用
uni.downloadFile下载视频到uni.env.USER_DATA_PATH下的子目录,例如:uni.env.USER_DATA_PATH + '/videos/123.mp4' - 下载完成后,把该路径字符串(不是文件内容)存进
uni.setStorageSync('video_path_123', path) - 下次播放直接传这个本地路径给
的src,绕过网络请求,也规避了存储容量陷阱 - 注意清理:调用
uni.getFileSystemManager().unlink()删除过期视频,别依赖uni.clearStorageSync()
如何让“已缓存视频”真正被复用?校验文件有效性很关键
只存路径不校验,会导致用户看到黑屏或报错 VIDEO_ERROR_SRC_NOT_SUPPORTED——因为文件可能被系统清理、磁盘满、或下载中断残留了半截文件。
每次播放前必须做轻量校验:
- 用
uni.getFileSystemManager().getFileInfo检查文件是否存在且大小 > 0 - 对 MP4 文件,可额外读前 16 字节判断是否含
ftyp签名(避免误判为损坏文件) - 缓存键建议带哈希或时间戳,比如
video_${md5(url)}_${Date.now() / 3600000 | 0},避免 URL 参数变化后命中旧缓存 - H5 端若用 MSE 方案,还要检查
MediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E"'),不同设备支持的编码差异很大
小程序里“伪边播”能做什么?靠预加载 + 分片策略
微信/支付宝小程序无法真正流式播放,但可以模拟体验:
- 用
uni.downloadFile分块下载(如每 2MB 一个 chunk),下载完立刻通知播放器“第一段就绪”,从该 offset 开始播放(需服务端支持Range头) - 结合
uni.createInnerAudioContext或自定义 canvas 播放器,接管解码与渲染,但仅限极简需求(如语音片段) - 更实用的是“预加载下一集”:用户看第 1 集时,后台静默下载第 2 集到本地路径,切集时毫秒切换,感知上就是“不卡顿”
- 别在
onShow或onLoad里同步启动下载——会阻塞页面渲染,改用setTimeout(() => download(), 0)或nextTick
最常被忽略的一点:视频缓存不是存得越多越好。iOS 对 USER_DATA_PATH 下文件有后台清理机制,且无明确 API 查询剩余空间;Android 虽宽松,但用户手动清应用数据会一并清空。务必加兜底——播放失败时自动回退到在线 URL,并记录错误日志供后续分析。











