最可靠方式是将视频加载进video元素后监听@canplay事件获取时长和宽高,而非依赖uni.chooseVideo返回的duration;需注意H5用URL.createObjectURL、小程序需临时路径转objectUrl、App端统一走video加载流程。

能直接拿到,但方式因平台和时机不同,不能只靠 uni.chooseVideo 返回值。
video 标签绑定 @canplay 读取 duration 和 videoWidth/videoHeight
这是最可靠、跨平台(H5/小程序/App)获取视频时长与宽高的方式,前提是已将视频加载进 <video> 元素(比如用 src 或 objectUrl)。
-
@canplay触发时,duration才真正可用;@loadedmetadata有时也行,但真机上不如@canplay稳定 - 直接访问
videoEl.duration得到秒级浮点数(如123.45),videoEl.videoWidth和videoEl.videoHeight是像素整数 - 注意:iOS 小程序中若用
src指向本地临时路径(tempFile.path),需先转成objectUrl(H5 必须,App 端部分版本也要求) - 示例片段:
<video ref="videoRef" @canplay="onCanPlay" :src="videoSrc" /> // ... onCanPlay() { const el = this.$refs.videoRef; console.log('时长:', el.duration, '宽高:', el.videoWidth, el.videoHeight); }
uni.chooseVideo 返回的 tempFiles[0] 里只有基础信息,没有时长
它只提供 size(字节数)、name、type、duration(⚠️注意:这个 duration 是 iOS/Android 原生层“估算值”,在 H5 不返回,且微信小程序里经常为 0 或不准)。
- 安卓 App 端可能返回近似值,但不可信;H5 完全不返回该字段
-
size是准确的,可用于上传前校验(如限制 ≤100MB) - 别依赖
tempFiles[0].duration做逻辑判断,尤其不能用于进度条或裁剪起点
需要精确时长?必须走 video 元素加载 + canplay 流程
哪怕只是上传前校验,也要把文件转成 URL 并挂到 <video> 上——这是目前 uni-app 全平台唯一稳定方案。
- H5:用
URL.createObjectURL(file),加载完记得URL.revokeObjectURL() - 小程序:
uni.createVideoContext不支持读取元数据,仍需 DOM 方式(video标签 +src设为临时路径) - App 端(nvue):若用原生
<video>,同样适用;若用 webview 内嵌,同 H5 - 坑点:iOS 真机对
tempFilePath直接赋给src可能失败,建议统一走createObjectURL或服务端代理 URL
文件大小始终可用,但要注意单位和压缩干扰
tempFiles[0].size 是原始字节数,但 uni.chooseVideo 默认开启压缩(iOS/Android 均如此),实际上传的是压缩后体积。
- 关掉自动压缩:
compressed: false,否则你看到的size和最终上传的文件大小不一致 - 示例:
uni.chooseVideo({ compressed: false, success: res => { console.log('原始大小:', res.tempFiles[0].size); // 字节 } }); - 如果用户选了 400MB 视频却只传了 28MB,大概率是没关
compressed
真正麻烦的不是“怎么读”,而是“什么时候读才准”——duration 必须等 canplay,size 虽然立刻有,但得确认是否被压缩过。这两个值从来就不是一回事,别混着用。


















