6.5 KiB
6.5 KiB
BDCloudVideoView 视频播放器增强方案
问题描述
现有视频播放器已支持B站和本地视频,但缺少以下关键功能:
- 来源切换UI:用户无法在播放过程中切换B站/本地源
- 播放进度记忆:关闭页面后无法从断点继续播放
- 高级播放控制:缺少多清晰度、倍速播放、字幕等功能
- 学习时长统计:未与任务系统联动记录学习时长
用户选择
- ✅ 来源切换UI
- ✅ 播放进度记忆
- ✅ 高级播放控制(多清晰度、倍速播放、字幕)
- ✅ 学习时长统计(与任务系统联动)
当前状态分析
现有组件结构
src/components/BDCloudVideoView/
├── BDCloudVideoView.tsx # 播放器组件(175行)
├── BDCloudVideoView.css # 样式文件(107行)
└── BDCloudVideoView.md # 说明文档
现有功能
- B站视频:通过
<iframe>内嵌,自动解析 BV 号 - 本地视频:集成百度智能云 SDK,失败回退到 HTML5
<video> - 下载/跳转B站按钮
问题根源
videoSource是外部传入的 prop,组件内部无法切换- 没有使用
localStorage或后端存储播放进度 - 百度 SDK 初始化时未配置高级选项(清晰度、倍速)
- 没有与任务系统的
tasks.trackAPI 联动
实现方案
1. 来源切换UI
修改文件: BDCloudVideoView.tsx
interface BDCloudVideoViewProps {
videoSource: 'bilibili' | 'local';
bilibiliUrl?: string;
localUrl?: string;
posterUrl?: string;
title?: string;
onDownload?: () => void;
// 新增:支持双源配置
sources?: {
bilibili?: string;
local?: string;
};
// 新增:外部控制来源
activeSource?: 'bilibili' | 'local';
onSourceChange?: (source: 'bilibili' | 'local') => void;
}
新增来源切换器组件:
const SourceSwitcher: React.FC<{
activeSource: 'bilibili' | 'local';
hasBilibili: boolean;
hasLocal: boolean;
onSwitch: (source: 'bilibili' | 'local') => void;
}> = ({ activeSource, hasBilibili, hasLocal, onSwitch }) => {
if (!hasBilibili || !hasLocal) return null;
return (
<div className="bdcloud-source-switcher">
<button
className={`bdcloud-source-btn ${activeSource === 'bilibili' ? 'active' : ''}`}
onClick={() => onSwitch('bilibili')}
>
B站
</button>
<button
className={`bdcloud-source-btn ${activeSource === 'local' ? 'active' : ''}`}
onClick={() => onSwitch('local')}
>
本地
</button>
</div>
);
};
2. 播放进度记忆
存储策略:
- 使用
localStorage存储,key 格式:video_progress_{chapterId} - 存储内容:
{ currentTime: number, duration: number, timestamp: number } - 播放时每 5 秒自动保存
- 加载时自动恢复到上次位置
// 进度存储
const saveProgress = (chapterId: string, currentTime: number, duration: number) => {
try {
localStorage.setItem(`video_progress_${chapterId}`, JSON.stringify({
currentTime,
duration,
timestamp: Date.now(),
}));
} catch {}
};
// 读取进度
const loadProgress = (chapterId: string): number => {
try {
const data = localStorage.getItem(`video_progress_${chapterId}`);
if (data) {
const { currentTime, timestamp } = JSON.parse(data);
// 只恢复7天内的进度
if (Date.now() - timestamp < 7 * 24 * 60 * 60 * 1000) {
return currentTime;
}
}
} catch {}
return 0;
};
3. 高级播放控制
百度 SDK 增强配置:
const config = {
container: playerRef.current,
video: {
url: localUrl || '',
pic: posterUrl || '',
// 新增:多清晰度支持
qualityList: [
{ label: '1080P', url: localUrlHd || localUrl },
{ label: '720P', url: localUrlSd || localUrl },
{ label: '480P', url: localUrl },
],
},
autoplay: false,
controls: true,
// 新增:播放速度
playbackRate: {
defaultValue: 1,
options: [0.5, 0.75, 1, 1.25, 1.5, 2],
},
// 新增:字幕支持
subtitleList: subtitleUrl ? [
{ label: '中文字幕', url: subtitleUrl },
] : [],
};
新增控制面板:
- 清晰度切换按钮(播放时显示可选清晰度)
- 倍速选择器(0.5x - 2x)
- 字幕开关(如有字幕时显示)
4. 学习时长统计
新增 props:
interface BDCloudVideoViewProps {
// ... 现有 props
chapterId?: number; // 章节ID,用于学习统计
onStudyTime?: (seconds: number) => void; // 学习时长回调
}
统计逻辑:
// 累计有效观看时长(排除暂停、拖拽)
let studySeconds = 0;
let lastPlayTime = 0;
let isPlaying = false;
const handlePlay = () => {
isPlaying = true;
lastPlayTime = Date.now();
};
const handlePause = () => {
if (isPlaying && lastPlayTime > 0) {
const elapsed = Math.floor((Date.now() - lastPlayTime) / 1000);
studySeconds += elapsed;
// 每累计 60 秒上报一次
if (studySeconds >= 60) {
reportStudyTime(studySeconds);
studySeconds = 0;
}
}
isPlaying = false;
};
// 上报到任务系统
const reportStudyTime = async (seconds: number) => {
try {
await api_request.login.tasks.track({
action_type: 'learn',
count: Math.floor(seconds / 60), // 转换为分钟
});
} catch {}
};
涉及文件
| 文件 | 操作 | 说明 |
|---|---|---|
src/components/BDCloudVideoView/BDCloudVideoView.tsx |
修改 | 添加来源切换、进度记忆、高级控制、学习统计 |
src/components/BDCloudVideoView/BDCloudVideoView.css |
修改 | 添加来源切换器、高级控制面板样式 |
src/pages/CourseLearn/CourseLearn.tsx |
修改 | 传递 chapterId 和回调函数 |
验证步骤
- 打开课程学习页面,播放视频
- 验证来源切换:点击B站/本地按钮切换视频源
- 验证进度记忆:刷新页面后视频从断点继续
- 验证高级控制:清晰度切换、倍速播放、字幕开关
- 验证学习统计:播放后检查任务进度是否更新
- 验证暗色模式下样式正常
- 验证移动端响应式布局
假设与决策
- 假设:百度 SDK 支持 qualityList 和 subtitleList 配置(需查阅官方文档确认)
- 决策:播放进度存储在 localStorage 而非后端,减少 API 调用
- 决策:学习时长统计每 60 秒上报一次,避免频繁请求
- 决策:来源切换仅在同时配置了 bilibili 和 local 源时显示