9.4 KiB
9.4 KiB
视频异常处理逻辑总结
📊 整体流程
视频加载 → URL测试 → 元数据加载 → 黑屏检测 → 播放 → 错误处理
1️⃣ 视频URL测试(testVideoUrl)
触发时机:
- 加载视频课件时(
loadCourseware)
处理逻辑:
async testVideoUrl(url) {
// 使用HEAD请求测试文件是否存在(不下载文件内容)
const res = await uni.request({
url: url,
method: 'HEAD',
timeout: 5000
})
if (res.statusCode === 200) {
✅ 视频文件可访问
- 记录Content-Type
- 记录Content-Length
} else if (res.statusCode === 404) {
❌ 视频文件不存在(404)
- 检查数据库filePath是否正确
} else if (res.statusCode === 403) {
❌ 没有权限访问(403)
} else {
⚠️ 其他响应码
}
}
作用:
- ✅ 提前检测视频是否可访问
- ✅ 输出详细日志,便于调试
- ⚠️ 只是日志输出,不会阻止播放
2️⃣ 黑屏检测与自动修复(onVideoLoadedMetadata)
触发时机:
- 视频元数据加载完成时
检测逻辑:
if (e.detail.width === 0 || e.detail.height === 0) {
⚠️ 检测到视频尺寸异常(黑屏)
if (videoRetryCount < 3) {
// 自动重试修复
videoRetryCount++
// 强制重新加载视频
this.videoId = 'course-video-' + Date.now() // 重新生成videoId
this.videoUrl = ''
await this.$nextTick()
this.videoUrl = currentUrl
this.initialTime = currentInitialTime
✅ 尝试修复黑屏(最多3次)
} else {
❌ 已达到最大重试次数,放弃修复
显示提示:'视频加载异常,请退出重试'
}
} else {
✅ 视频尺寸正常,重置重试计数器
videoRetryCount = 0
}
修复机制:
- 检测:宽度或高度为0 → 黑屏
- 重试:最多3次
- 方法:重新生成videoId,强制组件重建
- 失败:显示提示,要求用户退出重试
3️⃣ 播放错误处理(onVideoError)
触发时机:
- 视频播放过程中发生错误
错误分类与处理:
A. 根据错误码判断
if (e.detail?.errCode === -1) {
❌ 视频文件不存在或无法访问
} else if (e.detail?.errCode === -2) {
❌ 视频格式不支持
} else if (errMsg.includes('404')) {
❌ 视频文件未找到(404)
} else if (errMsg.includes('403')) {
❌ 没有权限访问视频文件(403)
} else if (errMsg.includes('timeout')) {
❌ 视频加载超时,请检查网络
}
B. 自动尝试URL编码切换
// 构建原始URL(未编码)
const originalUrl = config.FILE_BASE_URL + filePath
// 如果当前URL是编码的,尝试未编码版本
if (this.videoUrl !== originalUrl) {
console.log('尝试切换到未编码的URL')
this.videoUrl = originalUrl
// 等待500ms后重新尝试播放
setTimeout(() => {
const videoContext = uni.createVideoContext('course-video')
videoContext.play()
videoContext.pause()
}, 500)
} else {
// 已经尝试过未编码版本,显示错误提示
显示Modal:
- 标题:'视频播放失败'
- 内容:错误信息 + 服务器地址 + 文件路径
}
C. 显示详细错误信息
uni.showModal({
title: '视频播放失败',
content: `
${errorMsg}
请检查:
1. 服务器是否运行
2. 视频文件是否存在
3. 网络连接是否正常
服务器: ${config.FILE_BASE_URL}
路径: ${courseware.filePath}
`,
showCancel: false,
confirmText: '知道了'
})
4️⃣ 视频加载失败的完整处理流程
graph TD
A[开始加载视频] --> B{URL测试}
B -->|200 OK| C[加载视频]
B -->|404/403/其他| D[输出日志,继续尝试加载]
C --> E{元数据加载}
E -->|成功| F{尺寸检测}
F -->|正常| G[开始播放]
F -->|黑屏| H{重试次数<3?}
H -->|是| I[重新加载视频]
I --> C
H -->|否| J[提示用户:请退出重试]
E -->|失败| K[触发onVideoError]
G --> L{播放过程}
L -->|正常| M[播放完成]
L -->|错误| K
K --> N{URL编码尝试}
N -->|未尝试| O[切换到未编码URL]
O --> C
N -->|已尝试| P[显示错误提示Modal]
5️⃣ 不能播放的视频如何处理?
A. 自动处理(无需用户干预)
1. 黑屏问题
- ✅ 自动重试3次
- ✅ 每次间隔300ms
- ✅ 成功后重置计数器
- ❌ 3次失败后提示用户
2. URL编码问题
- ✅ 自动尝试未编码版本
- ✅ 间隔500ms后重试
- ❌ 失败后显示Modal
B. 需要用户干预
1. 文件不存在(404)
结果:显示Modal
提示:视频文件未找到(404)
服务器: http://xxx
路径: /profile/upload/xxx.mp4
建议:
- 检查服务器是否运行
- 检查视频文件是否存在
- 检查filePath是否正确
2. 权限问题(403)
结果:显示Modal
提示:没有权限访问视频文件(403)
建议:
- 检查服务器权限配置
- 检查防火墙设置
3. 网络超时
结果:显示Modal
提示:视频加载超时,请检查网络
建议:
- 检查网络连接
- 检查服务器响应速度
4. 格式不支持(-2)
结果:显示Modal
提示:视频格式不支持
建议:
- 转换视频格式为MP4
- 确保编码为H.264
C. 不影响学习进度
关键逻辑:
// 即使视频无法播放,图片/PDF仍然可以正常学习
// 进度计算:已完成课件数 / 总课件数
if ("video".equals(cw.getType())) {
if (detail != null && detail.getVideoPosition() != null) {
// 有观看记录才计入完成
if (videoPosition >= duration * 0.8) {
completedCount++
}
}
} else {
// 图片/PDF:查看过视为完成
if (detail != null) {
completedCount++ // ✅ 不影响
}
}
示例:
课程有:5个视频 + 3个图片
情况1:所有视频都能播放
- 看完3个视频 + 3个图片 → 进度 = 6/8 = 75%
情况2:有2个视频无法播放
- 看完3个视频 + 3个图片 → 进度 = 6/8 = 75%
- 无法播放的2个视频不计入(除非有观看记录)
情况3:所有视频都无法播放
- 看完3个图片 → 进度 = 3/8 = 37.5%
- 用户仍可学习图片课件
6️⃣ 日志输出(便于调试)
加载阶段:
[课程学习] 📦 加载课件数据: {...}
[课程学习] 课件ID: 893
[课程学习] 课件类型: video
[课程学习] 🔗 URL构建信息:
- FILE_BASE_URL: http://localhost:8080
- 原始filePath: /profile/upload/xxx.mp4
- 完整URL: http://localhost:8080/profile/upload/xxx.mp4
[课程学习] 🧪 测试视频URL可访问性: ...
[课程学习] ✅ 视频文件可访问
元数据加载:
[课程学习] ✅ 视频元数据加载完成
[课程学习] 视频时长: 300 秒
[课程学习] 视频宽度: 1920
[课程学习] 视频高度: 1080
[课程学习] ✅ 视频尺寸正常,重置重试计数器
错误阶段:
[课程学习] ❌❌❌ 视频播放错误 ❌❌❌
[课程学习] 错误码: -1
[课程学习] 错误信息: file not found
[课程学习] 视频URL: http://localhost:8080/profile/upload/xxx.mp4
[课程学习] 完整错误对象: {...}
7️⃣ 总结
自动处理机制:
- ✅ URL测试:提前检测可访问性
- ✅ 黑屏修复:最多3次自动重试
- ✅ 编码切换:自动尝试未编码URL
- ✅ 详细日志:便于定位问题
用户体验:
- ✅ 大部分问题自动修复,无需用户干预
- ✅ 修复失败时显示详细错误信息和建议
- ✅ 不影响其他课件的学习
- ✅ 进度计算正确,不会因个别视频问题阻塞
不影响进度:
- ✅ 无法播放的视频不计入完成
- ✅ 图片/PDF可正常学习并计入进度
- ✅ 用户可跳过问题视频,继续学习其他内容
🔧 管理员排查步骤
1. 检查后端日志
# 查看课件信息
[INFO] 视频课件 893 (测试视频): 时长=300秒
[WARN] 视频课件 894 时长信息缺失或无效: null
# 查看进度计算
[INFO] 课程 123 进度计算完成: 5个已完成课件 / 8个总课件 = 62.5%
2. 检查前端日志
# 查看URL构建
[课程学习] 🔗 URL构建信息:
- FILE_BASE_URL: http://localhost:8080
- 原始filePath: /profile/upload/2025/12/11/xxx.mp4
# 查看错误信息
[课程学习] ❌ 视频文件不存在(404)
[课程学习] 请检查数据库中的filePath是否正确
3. 验证文件
# 检查文件是否存在
ls -lh /path/to/upload/profile/upload/2025/12/11/xxx.mp4
# 检查文件权限
chmod 644 /path/to/upload/profile/upload/2025/12/11/xxx.mp4
4. 测试URL
# 使用curl测试
curl -I http://localhost:8080/profile/upload/2025/12/11/xxx.mp4
# 预期结果:HTTP/1.1 200 OK
最后更新: 2025-12-11 文档版本: v1.0