mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-25 12:55:18 -07:00
127e1ea88e
- Add per-stream subtitle delay persistence and auto timeline-offset correction - Strip server-selected subtitle stream from mpv load URL; suppress plugin subtitle rearm and auto-start during app-managed preload - Fix resume position lost when mpv resets on stop; use last known position for final progress/stopped reports - Keep Play vs Resume distinct to avoid early seek race on normal play - Fix discovery resume when remote play sends StartPositionTicks=0 despite saved progress - Deduplicate show/hide overlay commands using recorded visibility state - Rewrite docs-site Jellyfin page around cast-to-device UX
74 lines
3.1 KiB
TypeScript
74 lines
3.1 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { estimateSubtitleTimingOffset } from './subtitle-timing-offset';
|
|
|
|
function cue(startTime: number) {
|
|
return { startTime, endTime: startTime + 1, text: `cue ${startTime}` };
|
|
}
|
|
|
|
test('estimate subtitle timing offset detects a late Jellyfin subtitle timeline', () => {
|
|
const primary = [
|
|
34.935, 36.937, 41.441, 45.279, 48.115, 52.286, 54.955, 59.793, 63.63, 67.634, 76.643, 80.814,
|
|
87.988, 90.991, 94.094, 97.097,
|
|
].map(cue);
|
|
const reference = [
|
|
3.46, 9.48, 13.61, 21.4, 28.16, 32.06, 35.93, 45.1, 56.57, 59.68, 62.44, 65.56,
|
|
].map(cue);
|
|
|
|
const result = estimateSubtitleTimingOffset(primary, reference);
|
|
|
|
assert.ok(result);
|
|
assert.ok(result.offsetSeconds > -32);
|
|
assert.ok(result.offsetSeconds < -31);
|
|
assert.ok(result.matchCount >= 8);
|
|
assert.ok(result.meanErrorSeconds <= 0.75);
|
|
});
|
|
|
|
test('estimate subtitle timing offset favors the early episode timeline', () => {
|
|
const primary = [
|
|
34.935, 36.937, 41.441, 45.279, 48.115, 52.286, 54.955, 59.793, 63.63, 67.634, 76.643, 80.814,
|
|
87.988, 90.991, 94.094, 97.097, 207.974, 212.579, 222.422, 228.095, 232.432, 238.271, 244.778,
|
|
246.78, 249.282, 251.284, 253.62, 256.289, 259.626, 262.129, 264.965, 267.634, 270.303, 274.407,
|
|
277.077, 280.08, 284.084, 288.421, 291.925, 295.262, 298.431, 301.101, 306.773, 308.942,
|
|
312.946, 316.283, 321.621, 326.626, 331.131, 336.069, 340.407, 343.41, 351.418, 355.422,
|
|
357.924, 362.429, 365.432, 370.604, 373.273, 377.944, 381.114, 384.618, 387.621, 390.957,
|
|
396.73, 399.232, 401.568, 403.57, 405.572, 407.574, 409.743, 412.746, 418.752, 425.258, 427.26,
|
|
435.602, 440.44, 442.942, 445.445, 449.783,
|
|
].map(cue);
|
|
const reference = [
|
|
3.46, 9.48, 13.61, 21.4, 28.16, 32.06, 35.93, 45.1, 56.57, 59.68, 62.44, 65.56, 165.77, 172.81,
|
|
176.1, 177.27, 186.33, 191.33, 195.78, 201.83, 212.9, 214.09, 216.73, 220.2, 222.91, 225.65,
|
|
232.8, 237.92, 242.23, 243.28, 247.53, 252.04, 255.9, 258.86, 262.09, 264.43, 276.07, 278.01,
|
|
280.98, 285.67, 289.89, 294.57, 300, 303.56, 308.58, 316.37, 318.38, 319.86, 325.38, 328.82,
|
|
333.68, 335.26, 336.82, 340.11, 342.11, 344.36, 346.39, 347.53, 350.92, 370.18, 372.88, 376.43,
|
|
388.2, 390.57, 403.96, 406.36, 409.72, 413.78, 425.55, 432.76, 435.03, 438.06, 443.73, 448.31,
|
|
450.57, 457.62, 463.41, 465.85, 473.79, 480.59,
|
|
].map(cue);
|
|
|
|
const result = estimateSubtitleTimingOffset(primary, reference);
|
|
|
|
assert.ok(result);
|
|
assert.ok(result.offsetSeconds > -32);
|
|
assert.ok(result.offsetSeconds < -31);
|
|
});
|
|
|
|
test('estimate subtitle timing offset ignores subtitle timelines that are already aligned', () => {
|
|
const starts = [1, 5, 9, 14, 20, 25, 31, 38];
|
|
|
|
const result = estimateSubtitleTimingOffset(
|
|
starts.map(cue),
|
|
starts.map((start) => cue(start + 0.04)),
|
|
);
|
|
|
|
assert.equal(result, null);
|
|
});
|
|
|
|
test('estimate subtitle timing offset rejects weak timeline matches', () => {
|
|
const primary = [10, 20, 30, 40, 50, 60, 70, 80].map(cue);
|
|
const reference = [1, 2, 3, 4, 5, 6, 7, 8].map(cue);
|
|
|
|
const result = estimateSubtitleTimingOffset(primary, reference);
|
|
|
|
assert.equal(result, null);
|
|
});
|