mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-12 23:33:43 +08:00
- 将 groupedSources 存储在 sessionStorage 中而非 URL 参数里,以防止因 URL 过长导致的 CDN 414 错误 (#112) - 自动将旧版 groupedSources URL 迁移至短 gs 键 - 从视频元素中检测并显示实际视频分辨率(例如 1920x1080),不再依赖来源提供的标签 - 修复 PlayerNavbar 设置链接在高级模式下总是跳转到 /settings 而非 /premium/settings 的问题 (#106) - 修复 WatchHistorySidebar 未向 HistoryList 传递 isPremium,导致历史记录项 URL 丢失 premium=1 参数的问题 (#106) - 为 HLS 播放添加多级浏览器回退机制 (HLS.js → 原生 → 代理 → 错误并提供浏览器建议) (#104) - 在 IPTV 播放器中添加 HEVC/H.265 级别过滤,防止 CCTV 等频道出现仅有音频播放的问题 (#81) - 更新依赖并升级版本至 4.5.0
67 lines
2.1 KiB
TypeScript
67 lines
2.1 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
|
|
/**
|
|
* Maps video resolution height to a human-readable quality label.
|
|
*/
|
|
function getResolutionLabel(width: number, height: number): { label: string; color: string } | null {
|
|
if (width === 0 || height === 0) return null;
|
|
|
|
// Use the larger dimension in case of portrait video
|
|
const h = Math.max(width, height) === width ? height : width;
|
|
|
|
if (h >= 2160) return { label: '4K', color: 'bg-amber-500' };
|
|
if (h >= 1440) return { label: '2K', color: 'bg-emerald-500' };
|
|
if (h >= 1080) return { label: '1080P', color: 'bg-green-500' };
|
|
if (h >= 720) return { label: '720P', color: 'bg-teal-500' };
|
|
if (h >= 480) return { label: '480P', color: 'bg-sky-500' };
|
|
if (h >= 360) return { label: '360P', color: 'bg-gray-500' };
|
|
return { label: `${h}P`, color: 'bg-gray-500' };
|
|
}
|
|
|
|
export interface VideoResolutionInfo {
|
|
width: number;
|
|
height: number;
|
|
label: string;
|
|
color: string;
|
|
}
|
|
|
|
/**
|
|
* Detects the actual video resolution from the <video> element
|
|
* after metadata is loaded.
|
|
*/
|
|
export function useVideoResolution(videoRef: React.RefObject<HTMLVideoElement | null>): VideoResolutionInfo | null {
|
|
const [resolution, setResolution] = useState<VideoResolutionInfo | null>(null);
|
|
|
|
useEffect(() => {
|
|
const video = videoRef.current;
|
|
if (!video) return;
|
|
|
|
const detectResolution = () => {
|
|
const w = video.videoWidth;
|
|
const h = video.videoHeight;
|
|
if (w > 0 && h > 0) {
|
|
const info = getResolutionLabel(w, h);
|
|
if (info) {
|
|
setResolution({ width: w, height: h, ...info });
|
|
}
|
|
}
|
|
};
|
|
|
|
// Detect on loadedmetadata and also on resize (quality change)
|
|
video.addEventListener('loadedmetadata', detectResolution);
|
|
video.addEventListener('resize', detectResolution);
|
|
|
|
// Check if already loaded
|
|
if (video.videoWidth > 0 && video.videoHeight > 0) {
|
|
detectResolution();
|
|
}
|
|
|
|
return () => {
|
|
video.removeEventListener('loadedmetadata', detectResolution);
|
|
video.removeEventListener('resize', detectResolution);
|
|
};
|
|
}, [videoRef]);
|
|
|
|
return resolution;
|
|
}
|