bricks/docs/cn.old/videoplayer.md
2025-11-19 12:30:39 +08:00

12 KiB
Raw Permalink Blame History

bricks.VideoPlayerbricks.Iptv 技术文档


概述

本文档介绍基于 bricks 框架实现的两个核心类:

  • bricks.VideoPlayer一个功能完整的自定义视频播放器组件支持多种视频格式MP4、HLS .m3u8、DASH .mpd),并提供播放控制、音量调节、倍速播放、音轨切换和全屏等功能。
  • bricks.Iptv:一个用于 IPTV 频道播放的高级组件,集成 VideoPlayer,可动态加载频道数据,并上报播放状态。

该组件依赖外部库:

  • hls.js 用于播放 HLS 流(.m3u8
  • dash.js 用于播放 DASH 流(.mpd

外部依赖引入建议

<!-- 在页面中引入 -->
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script src="https://cdn.dashjs.org/latest/dash.all.min.js"></script>

1. bricks.VideoPlayer

类定义

bricks.VideoPlayer = class extends bricks.VBox

继承自 bricks.VBox,表示这是一个容器型 UI 组件,内部包含视频元素及控制栏。


构造函数:constructor(opts)

参数

参数 类型 必填 说明
opts.url String 视频源地址,支持 .mp4, .m3u8, .mpd 或普通流媒体 URL
opts.autoplay Boolean 是否自动播放,默认为 false

示例

const player = new bricks.VideoPlayer({
  url: 'https://example.com/stream.m3u8',
  autoplay: true
});

DOM 结构

创建如下 HTML 结构:

<div class="video-container">
  <video class="video-element"></video>
  <div class="controls">
    <div class="progress-container">
      <input type="range" class="progress-bar" value="0" step="0.0001" />
    </div>
    <div class="controls-bottom">
      <button class="play-pause"></button>
      <div class="volume-container">
        <button class="mute">🔊</button>
        <input type="range" class="volume" min="0" max="1" step="0.01" value="1" />
      </div>
      <span class="time">00:00 / 00:00</span>
      <div class="speed-container">
        <select class="playback-speed">
          <option value="0.5">0.5x</option>
          <option value="0.75">0.75x</option>
          <option value="1" selected>1x</option>
          <option value="1.25">1.25x</option>
          <option value="1.5">1.5x</option>
          <option value="2">2x</option>
        </select>
      </div>
      <div class="audio-tracks">
        <select class="audio-track-select"></select>
      </div>
      <button class="fullscreen"></button>
    </div>
  </div>
</div>

属性

属性 类型 描述
this.video HTMLVideoElement 内部 <video> 元素引用
this.hls Hlsnull hls.js 实例,仅当播放 .m3u8 时创建
this.dashPlayer dashjs.MediaPlayernull dash.js 播放器实例,仅当播放 .mpd 时创建
this.controls Element 控制栏 DOM 引用
this.playPauseBtn Element 播放/暂停按钮
this.muteBtn Element 静音按钮
this.volumeInput Element 音量滑块
this.progressBar Element 进度条
this.timeDisplay Element 时间显示文本
this.speedSelect Element 倍速选择下拉框
this.audioTrackSelect Element 音轨选择下拉框
this.fullscreenBtn Element 全屏按钮

方法

init()

初始化播放器,在 DOM 加载完成后调用。负责加载视频、绑定事件、更新 UI 并根据 autoplay 设置开始播放。

destroy()

销毁当前播放器实例,释放资源:

  • 销毁 Hls 或 Dash 播放器
  • 清空 video 的 src
  • 防止内存泄漏

loadVideo(src)

动态加载指定视频源。

支持类型:
格式 判断方式 使用技术
.m3u8 或含 m3u8 字符串 `endsWith('.m3u8')
.mpd 或含 mpd 字符串 `endsWith('.mpd')
其他(如 .mp4 默认情况 原生 <video>

⚠️ 调用前会先执行 destroy(),确保旧播放器被清理。

onLoaded()

视频元信息加载完成后的回调,用于刷新 UI 和音轨列表。

bindEvents()

绑定所有用户交互事件和视频事件,包括:

事件目标 事件类型 功能
.play-pause click 切换播放/暂停
.mute click 切换静音
.volume input 调节音量
.progress-bar input 拖动进度条跳转时间
.playback-speed change 更改播放速度
.audio-track-select change 切换音轨
.fullscreen click 进入/退出全屏
video play/pause 更新播放按钮图标
video timeupdate 更新进度条和时间显示
video durationchange 更新总时长
video volumechange 同步静音按钮状态
video loadedmetadata 加载音轨信息
video seeking 更新进度条位置

updateUI()

统一刷新所有控件状态。

updatePlayPauseUI()

根据播放状态更新播放按钮图标:

  • 暂停 →
  • 播放中 → ❚❚

updateMuteUI()

根据是否静音或音量为 0 来更新静音按钮图标:

  • 静音 → 🔇
  • 非静音 → 🔊

updateProgress()

更新进度条和时间显示:

  • 显示当前时间和总时间(格式化为 mm:sshh:mm:ss
  • 进度条值为 (currentTime / duration)

updateAudioTracks()

video.audioTracks 中读取可用音轨,并填充到下拉菜单中。默认选中已启用的轨道。

若无音轨,则显示“无音轨”选项且禁用。

formatTime(seconds)String

将秒数转换为可读时间字符串。

示例输出:
  • 65"1:05"
  • 3665"1:01:05"

控制行为特性

  • 自动隐藏控制栏点击任意位置显示控制栏4 秒后自动隐藏。
    • show_controls():显示控制栏
    • hide_controls():隐藏控制栏
  • 全屏切换:兼容 Chrome/Firefox/Safari/Edge 的全屏 API。
    • 图标在全屏状态下变为返回窗口图标SVG 箭头)
  • 响应式设计建议CSS 类名可用于样式定制(见下文)

2. bricks.Iptv

类定义

bricks.Iptv = class extends bricks.VBox

专用于播放 IPTV 频道的组件,自动获取频道信息并使用 VideoPlayer 播放。


构造函数:constructor(opts)

参数

参数 类型 必填 说明
iptv_data_url String 获取频道信息的接口地址
playok_url String 上报“播放成功”的接口
playfailed_url String 上报“播放失败”的接口

接口应返回 JSON 数据,至少包含字段:url, tv_name, id

示例

const iptv = new bricks.Iptv({
  iptv_data_url: '/api/channel?id=123',
  playok_url: '/api/report/playok',
  playfailed_url: '/api/report/playfailed'
});

属性

属性 类型 描述
this.user_data Object 存储从服务器获取的频道数据
this.deviceid String 设备唯一标识(通过 bricks.deviceid('iptv') 生成)
this.video bricks.VideoPlayer 内嵌的视频播放器实例
this.title_w bricks.Text 显示频道名称的文本组件

方法

build_subwidgets()

异步方法,首次构建子组件:

  1. 若未加载 user_data,则通过 HTTP 请求获取
  2. 创建 VideoPlayer 播放器并传入 user_data.url
  3. 添加标题和播放器到界面
  4. 绑定播放成功/失败事件以进行状态上报

report_play_ok()Promise<void>

播放开始后触发,向 playok_url 发送设备 ID 和频道 ID。

report_play_failed()Promise<void>

播放出错时触发,上报失败记录。

注意:这两个方法仅在对应 URL 存在时才发送请求。

setValue(data)

外部更新频道的方法。可用于切换频道而不重新创建组件。

参数
  • data: 包含新频道信息的对象,结构同 user_data
示例
iptv.setValue({
  id: 'cctv5',
  tv_name: 'CCTV-5 体育频道',
  url: 'https://live.example.com/cctv5.m3u8'
});

事件系统Event Binding

bricks 框架支持事件绑定机制:

自定义事件 触发条件 用途
domon 组件挂载到 DOM 后 执行 init() 初始化
domoff 组件从 DOM 卸载前 执行 destroy() 回收资源
click 用户点击组件区域 显示控制栏
play_ok 视频开始播放(由 VideoPlayer 抛出) 上报播放成功
play_failed 播放出错(由 VideoPlayer 抛出) 上报播放失败

注:play_okplay_failed 需结合业务逻辑手动抛出(当前代码中暂未体现具体抛出点,可能需进一步扩展)


注册组件Factory Registration

以下语句将组件注册至 bricks.Factory,便于通过配置或模板动态创建:

bricks.Factory.register('Iptv', bricks.Iptv);
bricks.Factory.register('VideoPlayer', bricks.VideoPlayer);
bricks.Factory.register('Video', bricks.VideoPlayer); // 别名支持

这意味着你可以这样使用:

bricks.Factory.create('VideoPlayer', { url: '...' });
bricks.Factory.create('Iptv', { iptv_data_url: '...' });

CSS 类名参考(供样式开发)

类名 用途
.video-container 播放器最外层容器
.video-element <video> 元素
.controls 控制栏整体
.progress-container, .progress-bar 进度条容器与滑块
.controls-bottom 底部按钮行
.play-pause, .mute, .fullscreen 各功能按钮
.volume, .playback-speed, .audio-track-select 输入控件
.time 时间显示区域

建议添加 CSS 以美化外观例如半透明背景、hover 效果等。


使用示例

示例 1直接播放视频

const player = new bricks.VideoPlayer({
  url: 'https://example.com/video.mp4',
  autoplay: true
});
document.body.appendChild(player.dom_element);

示例 2播放 HLS 直播流

const player = new bricks.VideoPlayer({
  url: 'https://live.example.com/stream.m3u8',
  autoplay: true
});
container.add_widget(player);

示例 3使用 IPTV 组件

const iptv = new bricks.Iptv({
  iptv_data_url: '/api/get_channel?id=101',
  playok_url: '/log/play_start',
  playfailed_url: '/log/play_error'
});
document.getElementById('app').appendChild(iptv.dom_element);

已知限制与注意事项

  1. 浏览器兼容性

    • HLS 播放依赖 hls.js,不支持 iOS Safari 原生 HLS但通常仍可回退
    • DASH 需要 MSEMedia Source Extensions支持
  2. 跨域问题

    • 视频源必须允许 CORS否则无法加载元数据或音轨
  3. 移动端体验

    • 自动隐藏控制栏的时间40帧 ≈ 0.67秒)可能偏短,建议调整
    • 移动端建议禁用鼠标 hover 行为,改为点击切换显示
  4. 错误处理待完善

    • 当前未监听 error 事件来触发 play_failed,建议补充:
      this.video.addEventListener('error', () => {
        this.fire('play_failed'); // 触发事件
      });
      
    • 可增加重试机制或备用源切换逻辑
  5. 性能优化

    • 多次切换视频源时频繁重建播放器,可考虑缓存策略优化

总结

bricks.VideoPlayer 是一个轻量级、多功能、跨平台的视频播放组件,适用于点播与直播场景;
bricks.Iptv 在其基础上封装了频道管理和状态上报能力,适合构建智能电视或 Web 端 IPTV 应用。

两者结合可快速搭建现代化流媒体播放界面,具备良好的扩展性和维护性。


文档版本v1.0
📅 最后更新2025-04-05