12 KiB
bricks.VideoPlayer 与 bricks.Iptv 技术文档
概述
本文档介绍基于 bricks 框架实现的两个核心类:
bricks.VideoPlayer:一个功能完整的自定义视频播放器组件,支持多种视频格式(MP4、HLS.m3u8、DASH.mpd),并提供播放控制、音量调节、倍速播放、音轨切换和全屏等功能。bricks.Iptv:一个用于 IPTV 频道播放的高级组件,集成VideoPlayer,可动态加载频道数据,并上报播放状态。
该组件依赖外部库:
外部依赖引入建议
<!-- 在页面中引入 -->
<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 |
Hls 或 null |
hls.js 实例,仅当播放 .m3u8 时创建 |
this.dashPlayer |
dashjs.MediaPlayer 或 null |
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:ss或hh: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()
异步方法,首次构建子组件:
- 若未加载
user_data,则通过 HTTP 请求获取 - 创建
VideoPlayer播放器并传入user_data.url - 添加标题和播放器到界面
- 绑定播放成功/失败事件以进行状态上报
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_ok和play_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);
已知限制与注意事项
-
浏览器兼容性
- HLS 播放依赖
hls.js,不支持 iOS Safari 原生 HLS(但通常仍可回退) - DASH 需要 MSE(Media Source Extensions)支持
- HLS 播放依赖
-
跨域问题
- 视频源必须允许 CORS,否则无法加载元数据或音轨
-
移动端体验
- 自动隐藏控制栏的时间(40帧 ≈ 0.67秒)可能偏短,建议调整
- 移动端建议禁用鼠标 hover 行为,改为点击切换显示
-
错误处理待完善
- 当前未监听
error事件来触发play_failed,建议补充:this.video.addEventListener('error', () => { this.fire('play_failed'); // 触发事件 }); - 可增加重试机制或备用源切换逻辑
- 当前未监听
-
性能优化
- 多次切换视频源时频繁重建播放器,可考虑缓存策略优化
总结
bricks.VideoPlayer 是一个轻量级、多功能、跨平台的视频播放组件,适用于点播与直播场景;
bricks.Iptv 在其基础上封装了频道管理和状态上报能力,适合构建智能电视或 Web 端 IPTV 应用。
两者结合可快速搭建现代化流媒体播放界面,具备良好的扩展性和维护性。
✅ 文档版本:v1.0
📅 最后更新:2025-04-05