mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-21 14:47:41 +01:00
subtitle tests
This commit is contained in:
parent
9c13be37e8
commit
42dee51570
2 changed files with 192 additions and 0 deletions
136
src/__tests__/subtitles/subtitles.test.ts
Normal file
136
src/__tests__/subtitles/subtitles.test.ts
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
import { describe, it } from "vitest";
|
||||||
|
import {
|
||||||
|
isSupportedSubtitle,
|
||||||
|
getMWCaptionTypeFromUrl,
|
||||||
|
parseSubtitles,
|
||||||
|
} from "@/backend/helpers/captions";
|
||||||
|
import { MWCaptionType } from "@/backend/helpers/streams";
|
||||||
|
import { ass, srt, visibleSubtitlesTestVtt, vtt } from "./testdata";
|
||||||
|
|
||||||
|
describe("subtitles", () => {
|
||||||
|
it("should return true if given url ends with a known subtitle type", ({
|
||||||
|
expect,
|
||||||
|
}) => {
|
||||||
|
expect(isSupportedSubtitle("https://example.com/test.srt")).toBe(true);
|
||||||
|
expect(isSupportedSubtitle("https://example.com/test.vtt")).toBe(true);
|
||||||
|
expect(isSupportedSubtitle("https://example.com/test.txt")).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return corresponding MWCaptionType", ({ expect }) => {
|
||||||
|
expect(getMWCaptionTypeFromUrl("https://example.com/test.srt")).toBe(
|
||||||
|
MWCaptionType.SRT
|
||||||
|
);
|
||||||
|
expect(getMWCaptionTypeFromUrl("https://example.com/test.vtt")).toBe(
|
||||||
|
MWCaptionType.VTT
|
||||||
|
);
|
||||||
|
expect(getMWCaptionTypeFromUrl("https://example.com/test.txt")).toBe(
|
||||||
|
MWCaptionType.UNKNOWN
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should throw when empty text is given", ({ expect }) => {
|
||||||
|
expect(() => parseSubtitles("")).toThrow("Given text is empty");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should parse srt", ({ expect }) => {
|
||||||
|
const parsed = parseSubtitles(srt);
|
||||||
|
const parsedSrt = [
|
||||||
|
{
|
||||||
|
type: "caption",
|
||||||
|
index: 1,
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
duration: 0,
|
||||||
|
content: "Test",
|
||||||
|
text: "Test",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "caption",
|
||||||
|
index: 2,
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
duration: 0,
|
||||||
|
content: "Test",
|
||||||
|
text: "Test",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
expect(parsed).toHaveLength(2);
|
||||||
|
expect(parsed).toEqual(parsedSrt);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should parse vtt", ({ expect }) => {
|
||||||
|
const parsed = parseSubtitles(vtt);
|
||||||
|
const parsedVtt = [
|
||||||
|
{
|
||||||
|
type: "caption",
|
||||||
|
index: 1,
|
||||||
|
start: 0,
|
||||||
|
end: 4000,
|
||||||
|
duration: 4000,
|
||||||
|
content: "Where did he go?",
|
||||||
|
text: "Where did he go?",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "caption",
|
||||||
|
index: 2,
|
||||||
|
start: 3000,
|
||||||
|
end: 6500,
|
||||||
|
duration: 3500,
|
||||||
|
content: "I think he went down this lane.",
|
||||||
|
text: "I think he went down this lane.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "caption",
|
||||||
|
index: 3,
|
||||||
|
start: 4000,
|
||||||
|
end: 6500,
|
||||||
|
duration: 2500,
|
||||||
|
content: "What are you waiting for?",
|
||||||
|
text: "What are you waiting for?",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
expect(parsed).toHaveLength(3);
|
||||||
|
expect(parsed).toEqual(parsedVtt);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should parse ass", ({ expect }) => {
|
||||||
|
const parsed = parseSubtitles(ass);
|
||||||
|
expect(parsed).toHaveLength(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should delay subtitles when given a delay", ({ expect }) => {
|
||||||
|
const videoTime = 11;
|
||||||
|
let delayedSeconds = 0;
|
||||||
|
const parsed = parseSubtitles(visibleSubtitlesTestVtt);
|
||||||
|
const isVisible = (start: number, end: number, delay: number): boolean => {
|
||||||
|
const delayedStart = start / 1000 + delay;
|
||||||
|
const delayedEnd = end / 1000 + delay;
|
||||||
|
return (
|
||||||
|
Math.max(0, delayedStart) <= videoTime &&
|
||||||
|
Math.max(0, delayedEnd) >= videoTime
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const visibleSubtitles = parsed.filter((c) =>
|
||||||
|
isVisible(c.start, c.end, delayedSeconds)
|
||||||
|
);
|
||||||
|
expect(visibleSubtitles).toHaveLength(1);
|
||||||
|
|
||||||
|
delayedSeconds = 10;
|
||||||
|
const delayedVisibleSubtitles = parsed.filter((c) =>
|
||||||
|
isVisible(c.start, c.end, delayedSeconds)
|
||||||
|
);
|
||||||
|
expect(delayedVisibleSubtitles).toHaveLength(1);
|
||||||
|
|
||||||
|
delayedSeconds = -10;
|
||||||
|
const delayedVisibleSubtitles2 = parsed.filter((c) =>
|
||||||
|
isVisible(c.start, c.end, delayedSeconds)
|
||||||
|
);
|
||||||
|
expect(delayedVisibleSubtitles2).toHaveLength(1);
|
||||||
|
|
||||||
|
delayedSeconds = -20;
|
||||||
|
const delayedVisibleSubtitles3 = parsed.filter((c) =>
|
||||||
|
isVisible(c.start, c.end, delayedSeconds)
|
||||||
|
);
|
||||||
|
expect(delayedVisibleSubtitles3).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
56
src/__tests__/subtitles/testdata.ts
Normal file
56
src/__tests__/subtitles/testdata.ts
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
const srt = `
|
||||||
|
1
|
||||||
|
00:00:00,000 --> 00:00:00,000
|
||||||
|
Test
|
||||||
|
|
||||||
|
2
|
||||||
|
00:00:00,000 --> 00:00:00,000
|
||||||
|
Test
|
||||||
|
`;
|
||||||
|
const vtt = `
|
||||||
|
WEBVTT
|
||||||
|
|
||||||
|
00:00:00.000 --> 00:00:04.000 position:10%,line-left align:left size:35%
|
||||||
|
Where did he go?
|
||||||
|
|
||||||
|
00:00:03.000 --> 00:00:06.500 position:90% align:right size:35%
|
||||||
|
I think he went down this lane.
|
||||||
|
|
||||||
|
00:00:04.000 --> 00:00:06.500 position:45%,line-right align:center size:35%
|
||||||
|
What are you waiting for?
|
||||||
|
`;
|
||||||
|
const ass = `[Script Info]
|
||||||
|
; Generated by Ebby.co
|
||||||
|
Title:
|
||||||
|
Original Script:
|
||||||
|
ScriptType: v4.00+
|
||||||
|
Collisions: Normal
|
||||||
|
PlayResX: 384
|
||||||
|
PlayResY: 288
|
||||||
|
PlayDepth: 0
|
||||||
|
Timer: 100.0
|
||||||
|
WrapStyle: 0
|
||||||
|
|
||||||
|
[v4+ Styles]
|
||||||
|
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
|
||||||
|
Style: Default, Arial, 16, &H00FFFFFF, &H00000000, &H00000000, &H00000000, 0, 0, 0, 0, 100, 100, 0, 0, 1, 1, 0, 2, 15, 15, 15, 0
|
||||||
|
|
||||||
|
[Events]
|
||||||
|
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
||||||
|
Dialogue: 0,0:00:10.00,0:00:20.00,Default,,0000,0000,0000,,This is the first subtitle.
|
||||||
|
Dialogue: 0,0:00:30.00,0:00:34.00,Default,,0000,0000,0000,,This is the second.
|
||||||
|
Dialogue: 0,0:00:34.00,0:00:35.00,Default,,0000,0000,0000,,Third`;
|
||||||
|
|
||||||
|
const visibleSubtitlesTestVtt = `WEBVTT
|
||||||
|
|
||||||
|
00:00:00.000 --> 00:00:10.000 position:10%,line-left align:left size:35%
|
||||||
|
Test 1
|
||||||
|
|
||||||
|
00:00:10.000 --> 00:00:20.000 position:90% align:right size:35%
|
||||||
|
Test 2
|
||||||
|
|
||||||
|
00:00:20.000 --> 00:00:31.000 position:45%,line-right align:center size:35%
|
||||||
|
Test 3
|
||||||
|
`;
|
||||||
|
|
||||||
|
export { vtt, srt, ass, visibleSubtitlesTestVtt };
|
Loading…
Reference in a new issue