查看: 5479|回复: 3

鸿蒙平台uni-app x视频播放video组件开发属性事件全屏适配避坑

[复制链接]
发表于 2026-9-18 12:00:00 | 显示全部楼层 |阅读模式
在鸿蒙平台做 uni-app x 视频播放,video 组件是标准方案,HarmonyOS 4.61 开始支持。它支持本地与网络视频,自带播放/暂停、进度条、全屏按钮,还能做全屏、弹幕、倍速、小窗播放和投屏。鸿蒙端底层使用 ArkUI 的 Video 组件原生实现,因此播放流畅、系统解码支持较好;代价是格式与能力受平台约束,支持 mp4、m4v、mov、3gp、flv、m3u8,本地 m3u8 文件不支持。

一、核心属性与事件

video 的属性很多,实际开发先掌握 src、controls、object-fit、poster、muted、autoplay、loop、show-controls、show-fullscreen-btn、show-center-play-btn、direction 等。object-fit 控制视频缩放方式,类似 image 的 mode。常用事件包括 play、pause、ended、timeupdate、progress、fullscreenchange、error,以及 list-view 下的 recycle、reuse。

基础写法:
  1. <template>
  2.   <video src='' style='width: 100%; height: 250px;'></video>
  3. </template>
复制代码

二、典型场景拆解

1. 基础播放与状态监听
  1. <template>
  2.   <view style='padding: 15px;'>
  3.     <video src='' style='width: 100%; height: 250px;' @play='onPlay' @pause='onPause' @ended='onEnded'></video>
  4.   </view>
  5. </template>
  6. <script setup lang='uts'>
  7. const onPlay = () => { console.log('开始播放') }
  8. const onPause = () => { console.log('暂停播放') }
  9. const onEnded = () => { console.log('播放结束') }
  10. </script>
复制代码

2. 封面和全屏标题
poster 设置封面图片,title 设置全屏时顶部显示的标题。注意 poster 只支持网络地址,不支持本地路径;如果 controls=false,poster 不会显示,需要自己用 image 组件覆盖实现封面。
  1. <video src='' poster='封面网络地址' title='视频标题' :show-fullscreen-btn='true' style='width: 100%; height: 250px;'></video>
复制代码

3. 自动播放与循环
短视频常用 autoplay + loop + muted。muted 必须为 true,否则很多浏览器和平台不允许自动播放。
  1. <video src='' :autoplay='true' :loop='true' :muted='true' :show-controls='false' object-fit='cover' style='width: 100%; height: 400px;'></video>
复制代码

4. 播放进度与缓冲进度
@timeupdate 每 250ms 触发一次,可取得当前播放进度;@progress 可取得缓冲进度。若在 timeupdate 里做复杂计算,可能影响性能。
  1. <template>
  2.   <view style='padding: 15px;'>
  3.     <video id='myVideo' src='' style='width: 100%; height: 250px;' @timeupdate='onTimeUpdate' @progress='onProgress'></video>
  4.     <text>播放进度:{{currentTime}}s / {{duration}}s</text>
  5.     <text>缓冲进度:{{buffered}}%</text>
  6.   </view>
  7. </template>
  8. <script setup lang='uts'>
  9. const currentTime = ref(0)
  10. const duration = ref(0)
  11. const buffered = ref(0)
  12. const onTimeUpdate = (event: UniVideoTimeUpdateEvent) => {
  13.   currentTime.value = Math.floor(event.detail.currentTime)
  14.   duration.value = Math.floor(event.detail.duration)
  15. }
  16. const onProgress = (event: UniVideoProgressEvent) => {
  17.   buffered.value = event.detail.buffered
  18. }
  19. </script>
复制代码

5. 全屏状态与方向
@fullscreenchange 可监听全屏状态,并从事件中读取 fullScreen 和 direction。direction 只在全屏时生效:0 是竖屏,90 是横屏(逆时针),-90 是反向横屏。
  1. <video src='' style='width: 100%; height: 250px;' @fullscreenchange='onFullscreenChange'></video>
  2. <script setup lang='uts'>
  3. const isFullscreen = ref(false)
  4. const onFullscreenChange = (event: UniVideoFullScreenChangeEvent) => {
  5.   isFullscreen.value = event.detail.fullScreen
  6.   console.log('全屏方向:', event.detail.direction)
  7. }
  8. </script>
复制代码

6. 错误处理
@error 可处理播放错误,事件中有 errMsg 和 errCode。错误码包括 100001 网络错误、200001 内部错误、300001 SDK 错误。播放成功后可清除错误提示。
  1. <video :src='videoUrl' style='width: 100%; height: 250px;' @error='onError' @play='onPlay'></video>
  2. <script setup lang='uts'>
  3. const videoUrl = ref('https://example.com/invalid-video.mp4')
  4. const errorMsg = ref('')
  5. const onError = (event: UniVideoErrorEvent) => {
  6.   errorMsg.value = '播放失败:' + event.detail.errMsg
  7.   console.log('错误码:', event.detail.errCode)
  8. }
  9. const onPlay = () => { errorMsg.value = '' }
  10. </script>
复制代码

三、鸿蒙平台专属特性

鸿蒙平台从 HarmonyOS 4.61 开始支持 video 组件,底层使用 ArkUI 的 Video 组件。对比鸿蒙原生开发,uni-app x 的 video 属性更丰富,弹幕、小窗、投屏等功能原生往往需要自行实现。

小窗播放(画中画)可通过 picture-in-picture-mode 设置:
  1. <video src='' :picture-in-picture-mode="['push', 'pop']" style='width: 100%; height: 250px;'></video>
复制代码

在 list-view 中使用 video 时,video 会被复用,可用 @recycle 和 @reuse 事件控制复用行为:
  1. <list-view @scrolltolower='onLoadMore'>
  2.   <list-item v-for='(item, index) in list' :key='index'>
  3.     <video :src='item.src' :controls='true' @recycle='onRecycle(index)' @reuse='onReuse(index)' style='width: 100%; height: 250px;'></video>
  4.   </list-item>
  5. </list-view>
复制代码

鸿蒙原生 Video 组件的写法可作对照:
  1. Video({ src: '', currentProgress: 0 })
  2.   .width('100%')
  3.   .height(250)
  4.   .autoPlay(false)
  5.   .controls(true)
  6.   .objectFit(ImageFit.Contain)
  7.   .onStart(() => {
  8.     console.log('开始播放')
  9.   })
复制代码

四、踩坑与修复清单

1. autoplay 需要 muted:带声音自动播放通常会被平台限制,必须同时设置 muted=true。
2. 本地视频只能访问 /static 目录:与 image 一样,本地视频要放在 /static 下。
3. poster 需要网络地址:不支持本地路径;如需本地封面,可先用 image 组件覆盖在 video 上。
4. controls=false 时 poster 无效:需要自己实现封面逻辑。
5. timeupdate 触发频率为 250ms:事件处理函数里不要做复杂操作。
6. direction 只控制全屏方向:0 竖屏,90 横屏(逆时针),-90 反向横屏。
7. HBuilderX 5.08 以后,Android 使用 ExoPlayer,iOS 使用 AVPlayer,不再支持 codec、play-strategy 属性,也不再支持 rtmp/rtsp 流媒体。

五、结论

video 组件是 uni-app x 在鸿蒙平台播放视频的标准方案。落地时先抓住几个关键点:autoplay 配合 muted;本地视频放 /static;poster 只支持网络地址;controls=false 时 poster 无效;object-fit 控制缩放;HarmonyOS 4.61 起支持;5.08 版本底层实现有变化。属性虽多,常用组合并不复杂,先把 src、controls、poster、muted 用好,再按业务加全屏、进度、小窗和错误处理。
回复

使用道具 举报

发表于 2026-9-18 19:00:00 | 显示全部楼层

Re: 鸿蒙平台uni-app x视频播放video组件开发属性事件全屏适配避坑

感谢分享,整理得很细。我一开始没注意到 poster 只支持网络地址,而且 controls 为 false 时封面不会显示,这个坑确实容易忽略;本地 m3u8 不支持也得提前跟产品说明。自动播放要 muted、timeupdate 里别做复杂计算、全屏方向用 0、90、-90 控制,这些点都很实用。错误码那组也先记下了。后面如果做小窗和投屏,应该也是围绕这些基础事件和状态来扩展吧,期待继续更新避坑经验。
回复 支持 反对

使用道具 举报

发表于 2026-9-18 19:10:00 | 显示全部楼层

Re: 鸿蒙平台uni-app x视频播放video组件开发属性事件全屏适配避坑

感谢楼主整理,这篇对鸿蒙平台 uni-app x 的 video 组件讲得很实用。尤其是 poster 只支持网络地址,而且 controls=false 时 poster 不显示、需要自己用 image 覆盖做封面这个坑,之前确实容易忽略;本地 m3u8 不支持、自动播放必须 muted 为 true、timeupdate 每 250ms 触发如果做复杂计算会影响性能,这些也都很有提醒价值。想请教一下,如果自己用 image 覆盖实现封面,全屏标题和全屏按钮是不是也得一并自己处理?另外 direction 只在全屏时生效,那非全屏下设置是不是没有意义?感谢分享,收藏了。
回复 支持 反对

使用道具 举报

发表于 2026-9-18 19:20:00 | 显示全部楼层

Re: 鸿蒙平台uni-app x视频播放video组件开发属性事件全屏适配避坑

感谢楼主整理,这个帖子挺实用的。我最近刚好在鸿蒙上做一个短视频模块,几个点确实踩过坑,补充一下自己的经验。 poster 只支持网络地址这一条太真实了,我们一开始想用本地资源做封面,结果死活不显示,后来发现只能走网络。还有 controls 设为 false 之后 poster 直接不渲染这个坑,很多人第一反应是组件坏了,其实得自己拿 image 叠一层,还要注意层级和点击穿透的问题,不然点不到播放按钮。 本地 m3u8 不支持也是硬伤,我们项目原本是本地缓存的切片,最后只能改成 mp4 或者把 m3u8 放到服务端再拉。顺便提一句,m3u8 在鸿蒙上的首帧出来会比 mp4 慢一点,如果对秒开有要求,建议还是优先 mp4。 timeupdate 那个 250ms 频率我深有体会,一开始我在回调里又算进度又更新好几个响应式变量,列表滚动明显掉帧,后来把复杂逻辑挪到 requestAnimationFrame 或者做节流才好起来。如果是做进度条拖动,建议直接监听拖动结束再 seek,不要边拖边 seek。 另外想请教楼主两个没展开的点:一是小窗播放,在页面切换或者回到桌面的时候,video 组件是怎么保持播放的,需要配合系统层的画中画能力吗?二是弹幕,是自己在 video 上层用 view 渲染飘过去的,还是有更好的方案?投屏那块也想知道实际落地难不难。 全屏 direction 那块
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-10-7 03:08 , Processed in 0.031447 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部