mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-08-18 12:18:29 -07:00
fix(overlay): prevent secondary subtitle duplication
- Reject decimal subtitle track IDs - Preserve repeated short dialogue lines
This commit is contained in:
@@ -181,6 +181,18 @@ test('dispatchMpvProtocolMessage emits subtitle track changes', async () => {
|
||||
]);
|
||||
});
|
||||
|
||||
test('dispatchMpvProtocolMessage rejects decimal subtitle track IDs', async () => {
|
||||
const { deps, state } = createDeps();
|
||||
|
||||
await dispatchMpvProtocolMessage({ event: 'property-change', name: 'sid', data: '4.5' }, deps);
|
||||
await dispatchMpvProtocolMessage(
|
||||
{ event: 'property-change', name: 'secondary-sid', data: '4.5' },
|
||||
deps,
|
||||
);
|
||||
|
||||
assert.deepEqual(state.events, [{ sid: null }, { sid: null }]);
|
||||
});
|
||||
|
||||
test('dispatchMpvProtocolMessage enforces sub-visibility hidden when overlay suppression is enabled', async () => {
|
||||
const { deps, state } = createDeps({
|
||||
isVisibleOverlayVisible: () => true,
|
||||
|
||||
@@ -283,7 +283,7 @@ export async function dispatchMpvProtocolMessage(
|
||||
: typeof msg.data === 'string'
|
||||
? Number(msg.data)
|
||||
: null;
|
||||
deps.emitSubtitleTrackChange({ sid: sid !== null && Number.isFinite(sid) ? sid : null });
|
||||
deps.emitSubtitleTrackChange({ sid: sid !== null && Number.isInteger(sid) ? sid : null });
|
||||
} else if (msg.name === 'secondary-sid') {
|
||||
const sid =
|
||||
typeof msg.data === 'number'
|
||||
@@ -292,7 +292,7 @@ export async function dispatchMpvProtocolMessage(
|
||||
? Number(msg.data)
|
||||
: null;
|
||||
deps.emitSecondarySubtitleTrackChange({
|
||||
sid: sid !== null && Number.isFinite(sid) ? sid : null,
|
||||
sid: sid !== null && Number.isInteger(sid) ? sid : null,
|
||||
});
|
||||
} else if (msg.name === 'secondary-sub-delay') {
|
||||
const delay =
|
||||
|
||||
@@ -1434,10 +1434,10 @@ test('prepareSecondarySubtitleLines collapses karaoke syllable spam into one ded
|
||||
assert.deepEqual(prepareSecondarySubtitleLines(karaoke), ['ya This no ma ups']);
|
||||
});
|
||||
|
||||
test('prepareSecondarySubtitleLines collapses a short stack of repeated ASS layers', () => {
|
||||
const layeredSign = ['Your', 'Your', 'Your', 'Your', 'mosaic'].join('\\N');
|
||||
test('prepareSecondarySubtitleLines preserves repeated short dialogue without layer metadata', () => {
|
||||
const dialogue = ['Wait', 'Wait', 'Wait'];
|
||||
|
||||
assert.deepEqual(prepareSecondarySubtitleLines(layeredSign), ['Your mosaic']);
|
||||
assert.deepEqual(prepareSecondarySubtitleLines(dialogue.join('\\N')), dialogue);
|
||||
});
|
||||
|
||||
test('prepareSecondarySubtitleLines preserves short simultaneous dialogue without repeats', () => {
|
||||
|
||||
@@ -657,24 +657,12 @@ function renderPlainTextPreserveLineBreaks(root: ParentNode, text: string): void
|
||||
// hover-pause band into a full-screen trap.
|
||||
const KARAOKE_MIN_LINE_COUNT = 8;
|
||||
const KARAOKE_MAX_MEDIAN_LINE_LENGTH = 4;
|
||||
const LAYERED_REPEAT_MIN_LINE_COUNT = 4;
|
||||
const LAYERED_REPEAT_MIN_COUNT = 3;
|
||||
|
||||
function isKaraokeLikeLineSet(lines: string[]): boolean {
|
||||
if (lines.length < KARAOKE_MIN_LINE_COUNT) return false;
|
||||
const lengths = lines.map((line) => line.length).sort((a, b) => a - b);
|
||||
const median = lengths[Math.floor(lengths.length / 2)] ?? 0;
|
||||
if (median > KARAOKE_MAX_MEDIAN_LINE_LENGTH) return false;
|
||||
|
||||
if (lines.length >= KARAOKE_MIN_LINE_COUNT) return true;
|
||||
if (lines.length < LAYERED_REPEAT_MIN_LINE_COUNT) return false;
|
||||
|
||||
const repeatCounts = new Map<string, number>();
|
||||
for (const line of lines) {
|
||||
const count = (repeatCounts.get(line) ?? 0) + 1;
|
||||
if (count >= LAYERED_REPEAT_MIN_COUNT) return true;
|
||||
repeatCounts.set(line, count);
|
||||
}
|
||||
return false;
|
||||
return median <= KARAOKE_MAX_MEDIAN_LINE_LENGTH;
|
||||
}
|
||||
|
||||
export function prepareSecondarySubtitleLines(text: string): string[] {
|
||||
|
||||
Reference in New Issue
Block a user