diff --git a/src/app/play/page.tsx b/src/app/play/page.tsx index a360ef3..639e8bc 100644 --- a/src/app/play/page.tsx +++ b/src/app/play/page.tsx @@ -570,6 +570,7 @@ function PlayPageClient() { const [videoLoadingStage, setVideoLoadingStage] = useState< 'initing' | 'sourceChanging' >('initing'); + const [videoError, setVideoError] = useState(null); // 播放器就绪状态(用于触发 usePlaySync 的事件监听器设置) const [playerReady, setPlayerReady] = useState(false); @@ -1939,6 +1940,7 @@ function PlayPageClient() { // 显示换源加载状态 setVideoLoadingStage('sourceChanging'); setIsVideoLoading(true); + setVideoError(null); // 记录当前播放进度(仅在同一集数切换时恢复) const currentPlayTime = artPlayerRef.current?.currentTime || 0; @@ -2958,6 +2960,32 @@ function PlayPageClient() { if (data.fatal) { switch (data.type) { case Hls.ErrorTypes.NETWORK_ERROR: + // 检查是否是 manifest 加载错误(通常是 403/404/CORS 错误) + if (data.details === 'manifestLoadError') { + console.log('Manifest 加载失败:可能是 403/404 或 CORS 错误'); + hls.destroy(); + // 检查是否有响应码 + const statusCode = data.response?.code || data.response?.status; + if (statusCode === 403) { + setVideoError('访问被拒绝 (403)'); + } else if (statusCode === 404) { + setVideoError('视频不存在 (404)'); + } else if (statusCode) { + setVideoError(`HTTP ${statusCode} 错误`); + } else { + // CORS 错误或其他网络错误 + setVideoError('无法访问视频源(可能是跨域限制或访问被拒绝)'); + } + return; + } + // 检查其他 HTTP 错误状态码 + const statusCode = data.response?.code || data.response?.status; + if (statusCode && statusCode >= 400) { + console.log(`HTTP ${statusCode} 错误`); + hls.destroy(); + setVideoError(`HTTP ${statusCode} 错误`); + return; + } console.log('网络错误,尝试恢复...'); hls.startLoad(); break; @@ -2968,6 +2996,7 @@ function PlayPageClient() { default: console.log('无法恢复的错误'); hls.destroy(); + setVideoError('视频加载错误'); break; } } @@ -3813,6 +3842,7 @@ function PlayPageClient() { // 隐藏换源加载状态 setIsVideoLoading(false); + setVideoError(null); }); // 监听视频时间更新事件,实现跳过片头片尾 @@ -4334,39 +4364,77 @@ function PlayPageClient() { > {/* 换源加载蒙层 */} - {isVideoLoading && ( + {(isVideoLoading || videoError) && (
- {/* 动画影院图标 */} -
-
-
🎬
- {/* 旋转光环 */} -
-
+ {videoError ? ( + // 错误显示 + <> + {/* 错误图标 */} +
+
+
⚠️
+
+
- {/* 浮动粒子效果 */} -
-
-
-
-
-
+ {/* 错误消息 */} +
+

+ 播放失败 +

+

+ {videoError} +

+ +
+ + ) : ( + // 加载显示 + <> + {/* 动画影院图标 */} +
+
+
🎬
+ {/* 旋转光环 */} +
+
- {/* 换源消息 */} -
-

- {videoLoadingStage === 'sourceChanging' - ? '🔄 切换播放源...' - : '🔄 视频加载中...'} -

-
+ {/* 浮动粒子效果 */} +
+
+
+
+
+
+ + {/* 换源消息 */} +
+

+ {videoLoadingStage === 'sourceChanging' + ? '🔄 切换播放源...' + : '🔄 视频加载中...'} +

+
+ + )}
)}