Make source badges numeric only

This commit is contained in:
kuekhaoyang
2026-04-16 16:41:37 +08:00
parent d7ba651950
commit eef52c751c
5 changed files with 60 additions and 50 deletions
+11 -11
View File
@@ -1,4 +1,4 @@
import { extractPlaybackQualityLabel } from '@/lib/utils/video';
import { extractNumericResolutionLabel } from '@/lib/utils/video';
export interface ResolutionProbeLabel {
label: string;
@@ -8,27 +8,22 @@ export interface ResolutionProbeLabel {
}
const QUALITY_RANK: Record<string, number> = {
'8K': 780,
'4K': 700,
'2K': 620,
'1080P': 540,
'蓝光': 520,
'HDR': 500,
'超清': 480,
'720P': 420,
'WEB-DL': 380,
'HDTV': 360,
'高清': 340,
'540P': 300,
'DVD': 280,
'480P': 260,
'360P': 220,
'TS': 120,
'SD': 100,
'240P': 180,
'144P': 160,
};
const DIMENSION_PATTERN = /(\d{3,4})\s*[xX]\s*(\d{3,4})/g;
const HLS_RESOLUTION_PATTERN = /RESOLUTION=(\d+)x(\d+)/gi;
const TEXT_QUALITY_PATTERNS: Array<{ pattern: RegExp; width?: number; height?: number; label: string; color: string }> = [
{ pattern: /(?:^|[^\d])(4320p?|8k)(?:[^\d]|$)/i, width: 7680, height: 4320, label: '8K', color: 'bg-rose-500' },
{ pattern: /(?:^|[^\d])(2160p?|4k|uhd)(?:[^\d]|$)/i, width: 3840, height: 2160, label: '4K', color: 'bg-amber-500' },
{ pattern: /(?:^|[^\d])(1440p?|2k|qhd)(?:[^\d]|$)/i, width: 2560, height: 1440, label: '2K', color: 'bg-emerald-500' },
{ pattern: /(?:^|[^\d])(1080p?|1080i|fhd|fullhd|full-hd)(?:[^\d]|$)/i, width: 1920, height: 1080, label: '1080P', color: 'bg-green-500' },
@@ -36,12 +31,15 @@ const TEXT_QUALITY_PATTERNS: Array<{ pattern: RegExp; width?: number; height?: n
{ pattern: /(?:^|[^\d])540p?(?:[^\d]|$)/i, width: 960, height: 540, label: '540P', color: 'bg-cyan-500' },
{ pattern: /(?:^|[^\d])480p?(?:[^\d]|$)/i, width: 854, height: 480, label: '480P', color: 'bg-sky-500' },
{ pattern: /(?:^|[^\d])360p?(?:[^\d]|$)/i, width: 640, height: 360, label: '360P', color: 'bg-gray-500' },
{ pattern: /(?:^|[^\d])240p?(?:[^\d]|$)/i, width: 426, height: 240, label: '240P', color: 'bg-gray-500' },
{ pattern: /(?:^|[^\d])144p?(?:[^\d]|$)/i, width: 256, height: 144, label: '144P', color: 'bg-gray-500' },
];
export function getResolutionLabel(width: number, height: number): ResolutionProbeLabel {
const normalizedWidth = Math.max(width, height);
const normalizedHeight = Math.min(width, height);
if (normalizedHeight >= 4320) return { width: normalizedWidth, height: normalizedHeight, label: '8K', color: 'bg-rose-500' };
if (normalizedHeight >= 2160) return { width: normalizedWidth, height: normalizedHeight, label: '4K', color: 'bg-amber-500' };
if (normalizedHeight >= 1440) return { width: normalizedWidth, height: normalizedHeight, label: '2K', color: 'bg-emerald-500' };
if (normalizedHeight >= 1080) return { width: normalizedWidth, height: normalizedHeight, label: '1080P', color: 'bg-green-500' };
@@ -49,6 +47,8 @@ export function getResolutionLabel(width: number, height: number): ResolutionPro
if (normalizedHeight >= 540) return { width: normalizedWidth, height: normalizedHeight, label: '540P', color: 'bg-cyan-500' };
if (normalizedHeight >= 480) return { width: normalizedWidth, height: normalizedHeight, label: '480P', color: 'bg-sky-500' };
if (normalizedHeight >= 360) return { width: normalizedWidth, height: normalizedHeight, label: '360P', color: 'bg-gray-500' };
if (normalizedHeight >= 240) return { width: normalizedWidth, height: normalizedHeight, label: '240P', color: 'bg-gray-500' };
if (normalizedHeight >= 144) return { width: normalizedWidth, height: normalizedHeight, label: '144P', color: 'bg-gray-500' };
return { width: normalizedWidth, height: normalizedHeight, label: `${normalizedHeight}P`, color: 'bg-gray-500' };
}
@@ -95,7 +95,7 @@ export function extractResolutionHint(...values: Array<string | undefined>): Res
});
}
best = chooseHigherQuality(best, extractPlaybackQualityLabel(value) || null);
best = chooseHigherQuality(best, extractNumericResolutionLabel(value) || null);
}
return best;
+2 -2
View File
@@ -1,4 +1,4 @@
import { extractPlaybackQualityLabel } from '@/lib/utils/video';
import { extractNumericResolutionLabel } from '@/lib/utils/video';
export interface ResolutionBadge {
label: string;
@@ -42,5 +42,5 @@ export function getSourceResolutionBadge(options: {
return { label: cachedResolution.label, color: cachedResolution.color };
}
return extractPlaybackQualityLabel(remarks) || null;
return extractNumericResolutionLabel(remarks) || null;
}
+26 -23
View File
@@ -27,39 +27,35 @@ export function parseVideoTitle(title: string): { cleanTitle: string, quality?:
}
/**
* Quality keywords and their display labels, ordered by priority (highest first).
* Numeric resolution keywords only.
* Qualitative labels such as "蓝光" or "高清" are intentionally excluded because
* they are not real numeric resolutions.
*/
const PLAYBACK_QUALITY_PATTERNS: { pattern: RegExp; label: string; color: string }[] = [
{ pattern: /4k|2160p|uhd/i, label: '4K', color: 'bg-amber-500' },
{ pattern: /2k|1440p|qhd/i, label: '2K', color: 'bg-emerald-500' },
{ pattern: /蓝光|藍光|bluray|blu-ray|remux/i, label: '蓝光', color: 'bg-blue-500' },
{ pattern: /\bhdr\b|hdr10\+?/i, label: 'HDR', color: 'bg-violet-500' },
{ pattern: /1080p|1080i|full\s*hd|fhd/i, label: '1080P', color: 'bg-green-500' },
{ pattern: /超清|超高清/i, label: '超清', color: 'bg-green-500' },
{ pattern: /540p/i, label: '540P', color: 'bg-cyan-500' },
{ pattern: /720p|hd720/i, label: '720P', color: 'bg-teal-500' },
{ pattern: /480p/i, label: '480P', color: 'bg-sky-500' },
{ pattern: /360p/i, label: '360P', color: 'bg-gray-500' },
{ pattern: /高清|流畅/i, label: '高清', color: 'bg-sky-500' },
{ pattern: /web-?dl|webrip/i, label: 'WEB-DL', color: 'bg-indigo-500' },
{ pattern: /hdtv/i, label: 'HDTV', color: 'bg-teal-500' },
{ pattern: /dvd|dvdrip/i, label: 'DVD', color: 'bg-purple-500' },
{ pattern: /抢先|枪版|ts版|(?:^|[\s([【_-])(ts|cam|hdts)(?:$|[\s)\]】_-])|预告/i, label: 'TS', color: 'bg-orange-500' },
{ pattern: /标清|(?:^|[\s([【_-])sd(?:$|[\s)\]】_-])/i, label: 'SD', color: 'bg-gray-500' },
const NUMERIC_RESOLUTION_PATTERNS: { pattern: RegExp; label: string; color: string }[] = [
{ pattern: /(?:^|[^\d])(4320p?|8k)(?:[^\d]|$)/i, label: '8K', color: 'bg-rose-500' },
{ pattern: /(?:^|[^\d])(2160p?|4k|uhd)(?:[^\d]|$)/i, label: '4K', color: 'bg-amber-500' },
{ pattern: /(?:^|[^\d])(1440p?|2k|qhd)(?:[^\d]|$)/i, label: '2K', color: 'bg-emerald-500' },
{ pattern: /(?:^|[^\d])(1080p?|1080i|full\s*hd|fhd)(?:[^\d]|$)/i, label: '1080P', color: 'bg-green-500' },
{ pattern: /(?:^|[^\d])720p?(?:[^\d]|$)|hd720/i, label: '720P', color: 'bg-teal-500' },
{ pattern: /(?:^|[^\d])540p?(?:[^\d]|$)/i, label: '540P', color: 'bg-cyan-500' },
{ pattern: /(?:^|[^\d])480p?(?:[^\d]|$)/i, label: '480P', color: 'bg-sky-500' },
{ pattern: /(?:^|[^\d])360p?(?:[^\d]|$)/i, label: '360P', color: 'bg-gray-500' },
{ pattern: /(?:^|[^\d])240p?(?:[^\d]|$)/i, label: '240P', color: 'bg-gray-500' },
{ pattern: /(?:^|[^\d])144p?(?:[^\d]|$)/i, label: '144P', color: 'bg-gray-500' },
];
/**
* Extracts a playback quality label from video remarks or title.
* This intentionally excludes language, subtitle, and audio labels.
* Extracts a numeric playback resolution from video remarks or title.
* Non-numeric labels are intentionally ignored.
*/
export function extractPlaybackQualityLabel(
export function extractNumericResolutionLabel(
remarks?: string,
quality?: string
): { label: string; color: string } | null {
const text = `${remarks || ''} ${quality || ''}`;
if (!text.trim()) return null;
for (const { pattern, label, color } of PLAYBACK_QUALITY_PATTERNS) {
for (const { pattern, label, color } of NUMERIC_RESOLUTION_PATTERNS) {
if (pattern.test(text)) {
return { label, color };
}
@@ -68,6 +64,13 @@ export function extractPlaybackQualityLabel(
return null;
}
export function extractPlaybackQualityLabel(
remarks?: string,
quality?: string
): { label: string; color: string } | null {
return extractNumericResolutionLabel(remarks, quality);
}
export function extractQualityLabel(remarks?: string, quality?: string): { label: string; color: string } | null {
return extractPlaybackQualityLabel(remarks, quality);
return extractNumericResolutionLabel(remarks, quality);
}