fix(parser): 原盘判定参考副标题线索与 PCM 音轨

标题写成 `Bluray H.264` 这类压制字样、但副标题写「自购自抓自扫」「BDMV」「原盘」「DIY」
「Blu-ray Disc」的,或带 LPCM / PCM 音轨又没有 x264 / x265 / BDRip / 压制说法的,判为原盘。
只在来源是 BluRay(或没写来源但有分辨率)时补判;「原盘压制」「自压」、WEB-DL、Remux、单个视频文件不受影响。
用「药屋少女的呢喃」真实搜索结果补正例与反例。

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-10-06 15:36:15 +08:00
1 parent 1845d47d3f
commit 18ee466664
2 files changed
+142 -1

No files matched your search

+35 -1
View File
@@ -45,6 +45,8 @@ type Draft = ParsedRelease & {
_fin?: boolean;
_disc?: boolean;
_remux?: boolean;
/** 标题里有 BDRip / BRRip(压制) */
_rip?: boolean;
/** `{[k=v;…]}` 显式身份块里的季/集/类型,finalize 时覆盖推断值 */
_explicit?: { season?: number; seasonEnd?: number; episodes?: EpisodeRange; tv?: boolean };
};
@@ -746,6 +748,7 @@ function walkTokens(tokens: string[], d: Draft): void {
const cnTitle = cn.join(" ").trim();
if (enTitle) d.titleEn = enTitle;
if (cnTitle) d.titleCn = cnTitle;
if (ripWord) d._rip = true;
if (d._remux) d.source = "REMUX";
else if (d._disc) d.source = "BluRay-Disc";
else if (blurayWord && discCodec && !encodeCodec && !ripWord && !d.encoder && sources.size === 1) {
@@ -1077,9 +1080,40 @@ export function parseRelease(input: string, opts: ParseOptions = {}): ParsedRele
}
}
// 14. 原盘线索:标题的编码字样不足以判定时,参考副标题 / 简介里的明确说法与无损 PCM 音轨
refineDisc(d, s, subtitle);
return finalize(d, opts);
}
/** 明确说是原盘:原盘(不含「原盘压制」)、BDMV、自购自抓 / 自抓自扫、Blu-ray Disc、DIY(原盘 DIY) */
const DISC_CUE =
/原[盘盤](?![\s::]*(?:压|壓|rip|转|轉))|BDMV|自[购購]自抓|自抓自[扫掃]|Blu-?ray[\s.]+Disc|(?<![A-Za-z])DIY(?![A-Za-z])/i;
/** 明确说是压制或其他来源 */
const ENCODE_CUE =
/自[压壓]|[压壓]制|重[编編]码|(?<![A-Za-z])(?:[xX]\.?26[45]|BDRip|BRRip|WEB-?DL|WEBRip|HDTV|Remux)(?![A-Za-z])/i;
/**
* 原盘补判(对照 MP 内置规则 BLU 之外的站点惯例):标题写成 `Bluray H.264` 这类压制字样、但副标题写「自购自抓自扫」,
* 或带 LPCM / PCM 音轨又没有 x264 / x265 / BDRip / 压制说法的,按原盘。只在来源是 BluRay(或标题没写来源但有分辨率)时补判,
* WEB / HDTV / Remux 不动。
*/
function refineDisc(d: Draft, title: string, subtitle: string | undefined): void {
// 单个视频文件(mkv / mp4 …)不会是原盘
if (d.isFile || d._rip || d.encoder || d._remux || d.source === "BluRay-Disc") return;
if (d.source !== "BluRay" && !(d.source === undefined && d.resolution)) return;
const text = subtitle ? `${title} | ${subtitle}` : title;
if (ENCODE_CUE.test(text)) return;
const pcm = d.source === "BluRay" && d.audio.some((a) => /^L?PCM\b/i.test(a));
if (DISC_CUE.test(text)) {
d.source = "BluRay-Disc";
d.evidence.push("source:disc_hint");
} else if (pcm) {
d.source = "BluRay-Disc";
d.evidence.push("source:disc_pcm");
}
}
function applyCnMarkers(d: Draft, cm: CnMarkers, prefix: string): void {
const ev = d.evidence;
const note = (k: string) => {
@@ -1171,7 +1205,7 @@ function finalize(d: Draft, opts: ParseOptions): ParsedRelease {
d.title = d.titleCn ?? d.titleEn;
d.confidence = confidenceOf(d);
const { _complete, _fin, _disc, _remux, _explicit, ...out } = d;
const { _complete, _fin, _disc, _remux, _rip, _explicit, ...out } = d;
return out;
}