更新记录

1.0.0(2025-11-10) 下载此版本

多格式支持:自动识别并播放 M3U8、FLV、MP4、WEBM、OGG 等多种视频格式 ✅ 直播/点播:支持直播流和点播视频,通过 isLive 参数区分 ✅ 跨平台兼容:H5、APP、微信小程序全平台支持 ✅ 智能降级:根据浏览器能力自动选择播放方案 ✅ iOS 优化:针对 iOS 环境特殊处理,避免不兼容问题 ✅ 错误提示:友好的错误提示界面,提升用户体验 ✅ 画中画支持:小程序直播场景支持画中画功能


平台兼容性

uni-app(4.21)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
× - 5.0 12 -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 快应用-华为 快应用-联盟
- - - - - - - - - -

VideoPlayer 视频播放器组件使用文档

📋 目录


组件概述

video-player.vue 是一个跨平台的视频播放器组件,支持 H5APP小程序端,能够智能识别视频格式并选择最优播放方式。

能干什么?

多格式支持:自动识别并播放 M3U8、FLV、MP4、WEBM、OGG 等多种视频格式 ✅ 直播/点播:支持直播流和点播视频,通过 isLive 参数区分 ✅ 跨平台兼容:H5、APP、微信小程序全平台支持 ✅ 智能降级:根据浏览器能力自动选择播放方案 ✅ iOS 优化:针对 iOS 环境特殊处理,避免不兼容问题 ✅ 错误提示:友好的错误提示界面,提升用户体验 ✅ 画中画支持:小程序直播场景支持画中画功能

⚠️ 重要提示:使用组件时必须正确设置 isLive 参数!

  • 直播场景isLive=true(小程序使用 live-player)
  • 点播场景isLive=false(小程序使用 video)

错误的 isLive 设置会导致小程序端播放失败或功能异常!


核心功能

1. 智能格式识别

组件会根据视频 URL 自动识别格式:

格式 识别规则 播放方式
M3U8/HLS URL 包含 .m3u8m3u8 hls.js (H5/APP) / 原生支持 (iOS)
FLV URL 包含 .flvflv flv.js (非 iOS) / 不支持 (iOS)
RTMP URL 以 rtmp:// 开头 不支持 (提示错误)
MP4 URL 包含 .mp4 原生 video 标签
WEBM URL 包含 .webm 原生 video 标签
OGG URL 包含 .ogg 原生 video 标签

2. 平台适配

H5 端

  • 使用 DOM 创建 <video> 元素
  • 动态加载 hls.js 和 flv.js 库
  • 支持所有现代浏览器

APP 端

  • 使用 renderjs 在渲染层操作 DOM
  • 性能更优,避免逻辑层与渲染层通信开销
  • 支持 iOS 和 Android

小程序端

  • 使用微信原生 <live-player> 组件
  • 仅支持直播流播放

3. iOS 特殊处理

为什么 iOS 不支持 FLV?

FLV (Flash Video) 格式依赖 Adobe Flash 技术,而:

  • iOS 从未支持 Flash:苹果设备从未内置 Flash Player
  • flv.js 依赖 MSE:虽然 flv.js 可以通过 Media Source Extensions (MSE) 播放 FLV,但 iOS Safari 对 MSE 的支持有限且不稳定
  • 安全性考虑:iOS 严格限制底层媒体解码能力

为什么 iOS 推荐使用 HLS?

HLS (HTTP Live Streaming) 是苹果公司开发的流媒体协议:

  • 原生支持:iOS Safari 原生支持 HLS,无需任何插件
  • 性能最优:硬件加速解码,功耗低、流畅度高
  • 自适应码率:根据网络状况自动调整清晰度
  • 行业标准:被广泛应用于直播和点播场景

建议:如果需要兼容 iOS,请使用 M3U8/HLS 格式的视频源。


Props 参数

参数名 类型 默认值 必填 说明
url String '' 视频播放地址,支持 http/https 协议
isLive Boolean false 是否为直播源(影响 FLV 播放器配置)
muted Boolean false 是否静音
autoplay Boolean true 是否自动播放
loop Boolean false 是否循环播放(仅点播有效)
controls Boolean false 是否显示控制条
poster String '' 视频封面图 URL

参数详解

url - 视频地址

// M3U8 直播流
url: 'https://example.com/live/stream.m3u8'

// FLV 直播流(注意:iOS 不支持)
url: 'https://example.com/live/stream.flv'

// MP4 点播视频
url: 'https://example.com/video/demo.mp4'

isLive - 直播标识

// 直播场景
:isLive="true"  // 优化 FLV 播放器配置,禁用 seek 等点播功能

// 点播场景
:isLive="false" // 启用完整的播放控制功能

autoplay - 自动播放

:autoplay="true"  // 页面加载后自动播放(可能受浏览器策略限制)
:autoplay="false" // 需要用户手动点击播放

⚠️ 注意:大部分浏览器要求用户交互后才能自动播放有声视频,建议配合 muted 使用。


Events 事件

组件会向父组件抛出以下事件:

事件名 参数 说明 触发时机
error { message, code?, format? } 播放错误 加载失败、格式不支持、播放异常
play Event 开始播放 视频开始播放
pause Event 暂停播放 视频暂停
ended Event 播放结束 视频播放完毕(仅点播)
timeupdate Event 时间更新 播放进度变化
loadedmetadata Event 元数据加载完成 视频时长、尺寸等信息加载完成
waiting Event 等待数据 缓冲中
canplay Event 可以播放 数据加载足够,可以开始播放
statechange Event 状态变化 小程序端专用 (live-player)
netstatus Event 网络状态 小程序端专用 (live-player)
fullscreenchange Event 全屏变化 进入/退出全屏
pictureinpicturechange { type, isEnter, detail } 画中画变化 小程序端进入/退出画中画

错误事件详解

iOS 不支持 FLV 错误

{
  message: 'iOS系统不支持FLV格式播放',
  code: 'FLV_NOT_SUPPORTED_ON_IOS',
  format: 'flv'
}

RTMP 不支持错误

{
  message: 'RTMP协议不支持',
  code: 'RTMP_NOT_SUPPORTED',
  format: 'rtmp'
}

FLV 播放错误

{
  message: 'FLV播放错误',
  errorType: 'NetworkError',
  errorDetail: 'HttpStatusCodeInvalid',
  errorInfo: { ... }
}

画中画事件详解

进入画中画

{
  type: 'enterpictureinpicture',
  isEnter: true,
  detail: { ... }
}

退出画中画

{
  type: 'leavepictureinpicture',
  isEnter: false,
  detail: { ... }
}

使用示例

<video-player
  :url="videoUrl"
  :isLive="false"
  @pictureinpicturechange="handlePipChange"
/>

<script setup>
const handlePipChange = (e) => {
  if (e.isEnter) {
    console.log('进入画中画模式')
  } else {
    console.log('退出画中画模式')
  }
}
</script>

Methods 方法

通过 ref 可以调用组件的控制方法:

方法名 参数 返回值 说明
play() - - 播放视频
pause() - - 暂停视频
stop() - - 停止视频(暂停并回到起点)
setVolume(volume) volume: Number (0-1) - 设置音量
setMuted(muted) muted: Boolean - 设置静音状态

方法调用示例

<template>
  <view>
    <video-player ref="playerRef" :url="videoUrl" />
    <button @click="handlePlay">播放</button>
    <button @click="handlePause">暂停</button>
  </view>
</template>

<script setup>
import { ref } from 'vue'

const playerRef = ref(null)

const handlePlay = () => {
  playerRef.value?.play()
}

const handlePause = () => {
  playerRef.value?.pause()
}
</script>

使用示例

示例 1:基础直播播放(M3U8)

<template>
  <video-player
    :url="liveUrl"
    :isLive="true"
    :autoplay="true"
    :muted="false"
    @error="handleError"
    @play="handlePlay"
  />
</template>

<script setup>
import { ref } from 'vue'
import VideoPlayer from './components/video-player.vue'

const liveUrl = ref('https://example.com/live/stream.m3u8')

const handleError = (error) => {
  console.error('播放错误:', error)
  uni.showToast({
    title: error.message,
    icon: 'none'
  })
}

const handlePlay = () => {
  console.log('开始播放')
  // 小程序端会使用 <live-player> 组件
  // H5/APP端会使用 hls.js 播放
}
</script>

示例 2:FLV 直播流(带 iOS 检测)

<template>
  <view>
    <!-- iOS 环境下会自动显示不支持提示 -->
    <video-player
      :url="flvUrl"
      :isLive="true"
      :autoplay="true"
      @error="handleError"
    />
  </view>
</template>

<script setup>
import { ref } from 'vue'

const flvUrl = ref('https://example.com/live/stream.flv')

const handleError = (error) => {
  if (error.code === 'FLV_NOT_SUPPORTED_ON_IOS') {
    // iOS 环境,建议切换到 M3U8
    console.log('检测到 iOS 环境,建议使用 M3U8 格式')
    // 可以在这里切换到备用的 M3U8 地址
    // flvUrl.value = 'https://example.com/live/stream.m3u8'
  }
}
</script>

示例 3:点播视频(带控制条)

<template>
  <video-player
    ref="playerRef"
    :url="videoUrl"
    :isLive="false"
    :autoplay="false"
    :controls="true"
    :loop="false"
    :poster="posterUrl"
    @ended="handleEnded"
    @timeupdate="handleTimeUpdate"
  />
</template>

<script setup>
import { ref } from 'vue'

const playerRef = ref(null)
const videoUrl = ref('https://example.com/video/demo.mp4')
const posterUrl = ref('https://example.com/poster.jpg')

const handleEnded = () => {
  console.log('视频播放完毕')
}

const handleTimeUpdate = (e) => {
  // 获取播放进度
  const currentTime = e.target?.currentTime
  const duration = e.target?.duration
  console.log(`播放进度: ${currentTime}/${duration}`)
}
</script>

示例 4:多清晰度切换

<template>
  <view>
    <video-player :url="currentUrl" :isLive="true" />
    <view class="quality-selector">
      <button @click="switchQuality('hd')">高清</button>
      <button @click="switchQuality('sd')">标清</button>
    </view>
  </view>
</template>

<script setup>
import { ref } from 'vue'

const currentUrl = ref('')

const urlMap = {
  hd: 'https://example.com/live/hd.m3u8',
  sd: 'https://example.com/live/sd.m3u8'
}

const switchQuality = (quality) => {
  currentUrl.value = urlMap[quality]
}

// 默认高清
switchQuality('hd')
</script>

示例 5:小程序画中画功能

<template>
  <view>
    <video-player
      ref="playerRef"
      :url="videoUrl"
      :isLive="false"
      :controls="true"
      @pictureinpicturechange="handlePipChange"
    />
    <view class="pip-status">
      画中画状态: {{ pipStatus }}
    </view>
  </view>
</template>

<script setup>
import { ref } from 'vue'

const playerRef = ref(null)
const videoUrl = ref('https://example.com/video/demo.mp4')
const pipStatus = ref('未激活')

const handlePipChange = (e) => {
  if (e.isEnter) {
    pipStatus.value = '已进入画中画'
    console.log('进入画中画模式,事件类型:', e.type)
  } else {
    pipStatus.value = '已退出画中画'
    console.log('退出画中画模式,事件类型:', e.type)
  }
}
</script>

📱 注意:画中画功能仅在小程序端的 <video> 组件中可用(isLive=false


注意事项

1. iOS 兼容性

不支持的格式

  • FLV 格式(会显示错误提示)
  • RTMP 协议

推荐格式

  • M3U8/HLS(最佳选择)
  • MP4(点播视频)

iOS FLV 格式自动处理: 组件会自动检测 iOS 环境下的 FLV 格式播放请求:

  • H5 端:显示警告覆盖层,阻止播放,触发 error 事件
  • APP 端:显示警告覆盖层,阻止播放,触发 error 事件
  • 小程序端:不受影响(使用原生组件)

错误事件参数:

{
  message: 'iOS系统不支持FLV格式播放',
  code: 'FLV_NOT_SUPPORTED_ON_IOS',
  format: 'flv'
}

2. 自动播放限制

大部分浏览器(尤其是移动端)限制自动播放有声视频:

<!-- 方案 1:静音自动播放 -->
<video-player :url="url" :autoplay="true" :muted="true" />

<!-- 方案 2:用户交互后播放 -->
<video-player ref="player" :url="url" :autoplay="false" />
<button @click="$refs.player.play()">点击播放</button>

3. 跨域问题

视频资源需要配置 CORS 响应头:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, HEAD

4. 直播延迟优化

对于直播场景,建议配置:

<video-player
  :url="liveUrl"
  :isLive="true"
  :autoplay="true"
  :muted="false"
/>

组件内部已针对直播优化:

  • HLS:lowLatencyMode: true,减少缓冲
  • FLV:isLive: true,禁用 seek 功能

5. 资源释放

组件会在卸载时自动释放资源,无需手动清理。


常见问题

Q1: isLive 参数有什么作用?为什么很重要?

A: isLive 是组件最重要的参数之一,它决定了:

  1. 小程序端组件选择

    • isLive=true → 使用 <live-player> 组件(直播专用)
    • isLive=false → 使用 <video> 组件(点播专用)
  2. H5/APP 端播放优化

    • isLive=true → FLV 播放器配置为直播模式,禁用 seek、优化缓冲
    • isLive=false → 启用完整的播放控制功能
  3. 功能可用性

    • 直播模式:不支持进度条拖拽、循环播放等点播功能
    • 点播模式:支持完整的播放控制、画中画等功能

错误示例

<!-- ❌ 错误:直播流使用 isLive=false -->
<video-player :url="live.m3u8" :isLive="false" />
<!-- 小程序端会使用 video 组件,可能无法正常播放直播流 -->

<!-- ✅ 正确:直播流使用 isLive=true -->
<video-player :url="live.m3u8" :isLive="true" />

Q2: 为什么 iOS 上 FLV 不能播放?

A: iOS 不支持 Flash 技术,且对 MSE 支持有限。建议使用 M3U8 格式,这是 iOS 原生支持的流媒体格式。

Q3: 如何判断当前是否为 iOS 环境?

A: 组件内部已自动检测,当 iOS 环境遇到 FLV 格式时会自动显示错误提示。你也可以监听 error 事件:

const handleError = (error) => {
  if (error.code === 'FLV_NOT_SUPPORTED_ON_IOS') {
    // 切换到 M3U8 或提示用户
  }
}

Q4: 如何实现多清晰度切换?

A: 直接修改 url 属性即可,组件会自动重新加载:

const switchQuality = (newUrl) => {
  videoUrl.value = newUrl // 组件会自动销毁旧播放器并加载新地址
}

Q5: 小程序端支持哪些格式?

A: 小程序端根据 isLive 参数使用不同组件:

直播场景 (isLive=true),使用 <live-player> 组件,支持:

  • RTMP
  • FLV
  • M3U8

点播场景 (isLive=false),使用 <video> 组件,支持:

  • MP4
  • M3U8
  • 其他微信支持的视频格式

具体支持情况以微信官方文档为准。

Q6: 如何监听播放进度?

A: 监听 timeupdate 事件(仅点播场景有效):

<video-player :isLive="false" @timeupdate="handleTimeUpdate" />

<script setup>
const handleTimeUpdate = (e) => {
  const video = e.target
  console.log('当前时间:', video.currentTime)
  console.log('总时长:', video.duration)
  console.log('进度百分比:', (video.currentTime / video.duration * 100).toFixed(2) + '%')
}
</script>

⚠️ 注意:直播场景 (isLive=true) 不支持进度监听。

Q7: 如何使用画中画功能?

A: 画中画功能仅在小程序端的直播场景可用:

<video-player
  :url="videoUrl"
  :isLive="true"
  :controls="false"
  @pictureinpicturechange="handlePipChange"
/>

<script setup>
const handlePipChange = (e) => {
  if (e.isEnter) {
    console.log('进入画中画')
    // 可以在这里更新UI状态
  } else {
    console.log('退出画中画')
  }
}
</script>

📱 限制

  • 仅小程序端支持
  • 必须设置 isLive=true(直播模式)
  • 需要用户手动触发(微信限制)

Q8: 如何处理网络错误?

A: 监听 error 事件并根据错误类型处理:

const handleError = (error) => {
  if (error.errorType === 'NetworkError') {
    // 网络错误,可以重试
    setTimeout(() => {
      playerRef.value?.play()
    }, 3000)
  } else {
    // 其他错误
    uni.showToast({ title: error.message, icon: 'none' })
  }
}

技术支持

如有问题,请联系开发团队或查阅相关文档:

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议