@vdegenne/subtitles 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +7 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +78 -0
- package/lib/index.js.map +1 -0
- package/package.json +36 -0
- package/types.d.ts +19 -0
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function numericTimeToTimecode(seconds: sub.NumericTime): sub.Timecode;
|
|
2
|
+
export declare function subtitlesToVTT(subtitles: sub.Subtitles): string;
|
|
3
|
+
export declare function numericTimeToSRTTimecode(seconds: sub.NumericTime): string;
|
|
4
|
+
export declare function subtitlesToSRT(subtitles: sub.Subtitles): string;
|
|
5
|
+
export declare function VTTtoSRT(vtt: string): string;
|
|
6
|
+
export declare function SRTtoVTT(srt: string): string;
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,GAAG,CAAC,WAAW,GAAG,GAAG,CAAC,QAAQ,CAQ5E;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,GAAG,CAAC,SAAS,GAAG,MAAM,CAU/D;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,GAAG,CAAC,WAAW,GAAG,MAAM,CAMzE;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,GAAG,CAAC,SAAS,GAAG,MAAM,CAS/D;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAyB5C;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAqB5C"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export function numericTimeToTimecode(seconds) {
|
|
2
|
+
return (String((seconds / 3600) | 0).padStart(2, '0') +
|
|
3
|
+
':' +
|
|
4
|
+
String(((seconds / 60) | 0) % 60).padStart(2, '0') +
|
|
5
|
+
':' +
|
|
6
|
+
String((seconds | 0) % 60).padStart(2, '0') +
|
|
7
|
+
'.' +
|
|
8
|
+
String(((seconds * 1000) | 0) % 1000).padStart(3, '0'));
|
|
9
|
+
}
|
|
10
|
+
export function subtitlesToVTT(subtitles) {
|
|
11
|
+
let vtt = 'WEBVTT\n\n';
|
|
12
|
+
for (const s of subtitles) {
|
|
13
|
+
if (s.id != null)
|
|
14
|
+
vtt += `${s.id}\n`;
|
|
15
|
+
vtt += `${numericTimeToTimecode(s.start)} --> ${numericTimeToTimecode(s.end)}\n`;
|
|
16
|
+
vtt += `${s.text}\n\n`;
|
|
17
|
+
}
|
|
18
|
+
return vtt;
|
|
19
|
+
}
|
|
20
|
+
export function numericTimeToSRTTimecode(seconds) {
|
|
21
|
+
const hours = String((seconds / 3600) | 0).padStart(2, '0');
|
|
22
|
+
const minutes = String(((seconds / 60) | 0) % 60).padStart(2, '0');
|
|
23
|
+
const secs = String((seconds | 0) % 60).padStart(2, '0');
|
|
24
|
+
const millis = String(((seconds * 1000) | 0) % 1000).padStart(3, '0');
|
|
25
|
+
return `${hours}:${minutes}:${secs},${millis}`;
|
|
26
|
+
}
|
|
27
|
+
export function subtitlesToSRT(subtitles) {
|
|
28
|
+
let srt = '';
|
|
29
|
+
for (let i = 0; i < subtitles.length; i++) {
|
|
30
|
+
const s = subtitles[i];
|
|
31
|
+
srt += `${i + 1}\n`;
|
|
32
|
+
srt += `${numericTimeToSRTTimecode(s.start)} --> ${numericTimeToSRTTimecode(s.end)}\n`;
|
|
33
|
+
srt += `${s.text}\n\n`;
|
|
34
|
+
}
|
|
35
|
+
return srt;
|
|
36
|
+
}
|
|
37
|
+
export function VTTtoSRT(vtt) {
|
|
38
|
+
const lines = vtt.split(/\r?\n/);
|
|
39
|
+
const srtLines = [];
|
|
40
|
+
let index = 1;
|
|
41
|
+
for (let i = 0; i < lines.length; i++) {
|
|
42
|
+
const line = lines[i].trim();
|
|
43
|
+
if (!line || line === 'WEBVTT')
|
|
44
|
+
continue;
|
|
45
|
+
// Timecode line
|
|
46
|
+
if (line.includes('-->')) {
|
|
47
|
+
srtLines.push(String(index++));
|
|
48
|
+
srtLines.push(line.replace('.', ',')); // convert milliseconds
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
// Subtitle text
|
|
52
|
+
srtLines.push(line);
|
|
53
|
+
// Add empty line after text if next line is empty or timecode
|
|
54
|
+
if (!lines[i + 1] || lines[i + 1].includes('-->')) {
|
|
55
|
+
srtLines.push('');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return srtLines.join('\n');
|
|
59
|
+
}
|
|
60
|
+
export function SRTtoVTT(srt) {
|
|
61
|
+
const lines = srt.split(/\r?\n/);
|
|
62
|
+
const vttLines = ['WEBVTT', '']; // header + empty line
|
|
63
|
+
for (let i = 0; i < lines.length; i++) {
|
|
64
|
+
const line = lines[i].trim();
|
|
65
|
+
// Skip numeric indices
|
|
66
|
+
if (/^\d+$/.test(line))
|
|
67
|
+
continue;
|
|
68
|
+
// Convert timecodes: comma → dot for milliseconds
|
|
69
|
+
if (line.includes('-->')) {
|
|
70
|
+
vttLines.push(line.replace(/,/g, '.'));
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
// Subtitle text or empty line
|
|
74
|
+
vttLines.push(line);
|
|
75
|
+
}
|
|
76
|
+
return vttLines.join('\n');
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vdegenne/subtitles",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Small npm utility to work with subtitles.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"import": "./lib/index.js",
|
|
9
|
+
"types": "./types.d.ts"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"./lib/",
|
|
14
|
+
"./types.d.ts"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "wireit"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"typescript": "^5.9.3",
|
|
21
|
+
"wireit": "^0.14.12"
|
|
22
|
+
},
|
|
23
|
+
"wireit": {
|
|
24
|
+
"build": {
|
|
25
|
+
"command": "tsc --pretty",
|
|
26
|
+
"clean": "if-file-deleted",
|
|
27
|
+
"files": [
|
|
28
|
+
"./tsconfig.json",
|
|
29
|
+
"./src"
|
|
30
|
+
],
|
|
31
|
+
"output": [
|
|
32
|
+
"./lib"
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
package/types.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
namespace sub {
|
|
3
|
+
type Timecode = `${number}:${number}:${number}.${number}`
|
|
4
|
+
/** in seconds */
|
|
5
|
+
type NumericTime = number
|
|
6
|
+
|
|
7
|
+
interface Subtitle {
|
|
8
|
+
id?: number
|
|
9
|
+
/** numeric time in seconds */
|
|
10
|
+
start: NumericTime
|
|
11
|
+
/** numeric time in seconds */
|
|
12
|
+
end: NumericTime
|
|
13
|
+
text: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type Subtitles = Subtitle[]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export {}
|