@byomakase/omakase-ttconv-ts 1.0.0-RC1
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/LICENSE.txt +21 -0
- package/README.md +281 -0
- package/dist/index.d.ts +639 -0
- package/dist/omakase-ttconv-ts.es.js +5537 -0
- package/dist/omakase-ttconv-ts.es.js.map +1 -0
- package/dist/omakase-ttconv-ts.umd.js +81 -0
- package/package.json +40 -0
package/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Copyright (c) 2020, Sandflow Consulting LLC
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
|
4
|
+
modification, are permitted provided that the following conditions are met:
|
|
5
|
+
|
|
6
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
7
|
+
list of conditions and the following disclaimer.
|
|
8
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
9
|
+
this list of conditions and the following disclaimer in the documentation
|
|
10
|
+
and/or other materials provided with the distribution.
|
|
11
|
+
|
|
12
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
13
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
14
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
15
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
16
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
17
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
18
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
19
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
20
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
21
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
# ttconv
|
|
2
|
+
|
|
3
|
+
TypeScript subtitle conversion library. Converts between SCC, STL, SRT, VTT, and TTML/IMSC formats.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install omakase-ttconv-ts
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
### Universal `convert` function
|
|
14
|
+
|
|
15
|
+
The simplest API — pass input content, input format, and output format:
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { convert } from 'omakase-ttconv-ts';
|
|
19
|
+
import type { ConvertConfig } from 'omakase-ttconv-ts';
|
|
20
|
+
import { readFileSync } from 'fs';
|
|
21
|
+
|
|
22
|
+
// SCC → VTT
|
|
23
|
+
const sccContent = readFileSync('captions.scc', 'utf8');
|
|
24
|
+
const vtt = convert(sccContent, 'scc', 'vtt');
|
|
25
|
+
|
|
26
|
+
// STL → SRT
|
|
27
|
+
const stlData = readFileSync('subtitles.stl'); // Buffer
|
|
28
|
+
const srt = convert(stlData, 'stl', 'srt');
|
|
29
|
+
|
|
30
|
+
// SRT → IMSC/TTML
|
|
31
|
+
const srtContent = readFileSync('captions.srt', 'utf8');
|
|
32
|
+
const ttml = convert(srtContent, 'srt', 'ttml');
|
|
33
|
+
|
|
34
|
+
// With reader/writer config and progress callback
|
|
35
|
+
const config: ConvertConfig = {
|
|
36
|
+
reader: { textAlign: 'center' }, // SccReaderConfiguration
|
|
37
|
+
writer: { textFormatting: false }, // SrtWriterConfig / VttWriterConfig / ImscWriterConfig
|
|
38
|
+
};
|
|
39
|
+
const result = convert(sccContent, 'scc', 'srt', config, (p) => console.log(`${Math.round(p * 100)}%`));
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Supported input formats:** `'scc'` | `'stl'` | `'srt'` | `'vtt'` | `'ttml'`
|
|
43
|
+
|
|
44
|
+
**Supported output formats:** `'srt'` | `'vtt'` | `'ttml'`
|
|
45
|
+
|
|
46
|
+
`input` is `string` for all text formats and `Buffer` for `'stl'`.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
### Format-specific convenience functions (async)
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { convertScc, convertStl } from 'omakase-ttconv-ts';
|
|
54
|
+
import { readFileSync } from 'fs';
|
|
55
|
+
|
|
56
|
+
// SCC → VTT
|
|
57
|
+
const sccContent = readFileSync('captions.scc', 'utf8');
|
|
58
|
+
const vtt = await convertScc(sccContent, 'vtt');
|
|
59
|
+
|
|
60
|
+
// SCC → SRT
|
|
61
|
+
const srt = await convertScc(sccContent, 'srt');
|
|
62
|
+
|
|
63
|
+
// SCC → IMSC/TTML
|
|
64
|
+
const ttml = await convertScc(sccContent, 'imsc');
|
|
65
|
+
|
|
66
|
+
// STL → VTT
|
|
67
|
+
const stlData = readFileSync('subtitles.stl');
|
|
68
|
+
const vttFromStl = await convertStl(stlData, 'vtt');
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Two-step conversion (reader → writer)
|
|
72
|
+
|
|
73
|
+
Use this approach to apply configuration or perform multiple conversions from the same parsed document.
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { sccToModel, srtFromModel, vttFromModel, imscFromModel } from 'omakase-ttconv-ts';
|
|
77
|
+
import { readFileSync } from 'fs';
|
|
78
|
+
|
|
79
|
+
const sccContent = readFileSync('captions.scc', 'utf8');
|
|
80
|
+
const doc = sccToModel(sccContent);
|
|
81
|
+
|
|
82
|
+
const srt = srtFromModel(doc);
|
|
83
|
+
const vtt = vttFromModel(doc);
|
|
84
|
+
const ttml = imscFromModel(doc);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Readers
|
|
88
|
+
|
|
89
|
+
### SCC (CTA-608 Closed Captions)
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { sccToModel } from 'omakase-ttconv-ts';
|
|
93
|
+
import type { SccReaderConfiguration } from 'omakase-ttconv-ts';
|
|
94
|
+
|
|
95
|
+
const config: SccReaderConfiguration = {
|
|
96
|
+
textAlign: 'auto', // 'auto' | 'left' | 'center' | 'right'
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const doc = sccToModel(sccContent, config);
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### STL (EBU STL binary)
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { stlToModel } from 'omakase-ttconv-ts';
|
|
106
|
+
import { readFileSync } from 'fs';
|
|
107
|
+
|
|
108
|
+
const stlData = readFileSync('subtitles.stl'); // Buffer
|
|
109
|
+
const doc = stlToModel(stlData);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### SRT
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import { srtToModel } from 'omakase-ttconv-ts';
|
|
116
|
+
|
|
117
|
+
const doc = srtToModel(srtContent);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Supports inline HTML tags: `<b>`, `<i>`, `<u>`, `<font color="...">`.
|
|
121
|
+
|
|
122
|
+
### VTT (WebVTT)
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
import { vttToModel } from 'omakase-ttconv-ts';
|
|
126
|
+
|
|
127
|
+
const doc = vttToModel(vttContent);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### TTML / IMSC
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
import { ttmlToModel } from 'omakase-ttconv-ts';
|
|
134
|
+
|
|
135
|
+
const doc = ttmlToModel(ttmlContent);
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Writers
|
|
139
|
+
|
|
140
|
+
### SRT
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
import { srtFromModel } from 'omakase-ttconv-ts';
|
|
144
|
+
import type { SrtWriterConfig } from 'omakase-ttconv-ts';
|
|
145
|
+
|
|
146
|
+
const config: SrtWriterConfig = {
|
|
147
|
+
textFormatting: true, // default true; set false to strip all HTML tags
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const srt = srtFromModel(doc, config);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### VTT (WebVTT)
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { vttFromModel } from 'omakase-ttconv-ts';
|
|
157
|
+
import type { VttWriterConfig } from 'omakase-ttconv-ts';
|
|
158
|
+
|
|
159
|
+
const config: VttWriterConfig = {
|
|
160
|
+
styleRegion: false, // default false; set true to emit VTT region/line position cues
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const vtt = vttFromModel(doc, config);
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### IMSC / TTML
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import { imscFromModel } from 'omakase-ttconv-ts';
|
|
170
|
+
import type { ImscWriterConfig } from 'omakase-ttconv-ts';
|
|
171
|
+
import { Fraction } from 'omakase-ttconv-ts';
|
|
172
|
+
|
|
173
|
+
const config: ImscWriterConfig = {
|
|
174
|
+
frameRate: new Fraction(30), // output frame rate
|
|
175
|
+
timeExpressionSyntax: 'clock_time', // 'clock_time' | 'frames' | 'clock_time_with_frames'
|
|
176
|
+
contentProfilesSignaling: 'content_profiles', // 'none' | 'content_profiles'
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const ttml = imscFromModel(doc, config);
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Progress Callbacks
|
|
183
|
+
|
|
184
|
+
All writers accept an optional progress callback as the third argument:
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
const srt = srtFromModel(doc, {}, (progress) => {
|
|
188
|
+
console.log(`${Math.round(progress * 100)}%`);
|
|
189
|
+
});
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Browser Bundle
|
|
193
|
+
|
|
194
|
+
A pre-built IIFE bundle is available at `dist/ttconv.browser.js`. It exposes the global `ttconvModule`:
|
|
195
|
+
|
|
196
|
+
```html
|
|
197
|
+
<script src="ttconv.browser.js"></script>
|
|
198
|
+
<script>
|
|
199
|
+
const doc = ttconvModule.sccToModel(sccContent);
|
|
200
|
+
const vtt = ttconvModule.vttFromModel(doc);
|
|
201
|
+
</script>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Working with the Document Model
|
|
205
|
+
|
|
206
|
+
Readers return a `ContentDocument` and writers consume one. You can also build or inspect a document directly using the model classes.
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
import {
|
|
210
|
+
ContentDocument, Body, Div, P, Span, Text, Region, Fraction,
|
|
211
|
+
StyleProperties, FontStyleType, FontWeightType, makeColor, LengthUnits, makeLengthType
|
|
212
|
+
} from 'omakase-ttconv-ts';
|
|
213
|
+
|
|
214
|
+
// Build a document from scratch
|
|
215
|
+
const doc = new ContentDocument();
|
|
216
|
+
doc.setLang('en');
|
|
217
|
+
|
|
218
|
+
const region = new Region('r1');
|
|
219
|
+
region.setStyle(StyleProperties.Origin, {
|
|
220
|
+
x: makeLengthType(10, LengthUnits.pct),
|
|
221
|
+
y: makeLengthType(85, LengthUnits.pct),
|
|
222
|
+
});
|
|
223
|
+
region.setStyle(StyleProperties.Extent, {
|
|
224
|
+
width: makeLengthType(80, LengthUnits.pct),
|
|
225
|
+
height: makeLengthType(10, LengthUnits.pct),
|
|
226
|
+
});
|
|
227
|
+
doc.putRegion(region);
|
|
228
|
+
|
|
229
|
+
const body = new Body(doc);
|
|
230
|
+
doc.setBody(body);
|
|
231
|
+
const div = new Div(doc);
|
|
232
|
+
body.pushChild(div);
|
|
233
|
+
|
|
234
|
+
const p = new P(doc);
|
|
235
|
+
p.setRegion(region);
|
|
236
|
+
p.setBegin(new Fraction(0)); // seconds as rational number
|
|
237
|
+
p.setEnd(new Fraction(5, 2)); // 2.5 seconds
|
|
238
|
+
div.pushChild(p);
|
|
239
|
+
|
|
240
|
+
const span = new Span(doc);
|
|
241
|
+
span.setStyle(StyleProperties.FontStyle, FontStyleType.italic);
|
|
242
|
+
span.setStyle(StyleProperties.Color, makeColor(255, 255, 255)); // white
|
|
243
|
+
span.pushChild(new Text(doc, 'Hello, world!'));
|
|
244
|
+
p.pushChild(span);
|
|
245
|
+
|
|
246
|
+
const srt = srtFromModel(doc);
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Fraction
|
|
250
|
+
|
|
251
|
+
`Fraction` represents an exact rational time value (numerator/denominator in seconds).
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
import { Fraction } from 'omakase-ttconv-ts';
|
|
255
|
+
|
|
256
|
+
const t = new Fraction(1001, 30000); // 1001/30000 seconds
|
|
257
|
+
const t2 = new Fraction(5); // 5 seconds
|
|
258
|
+
|
|
259
|
+
console.log(t.toNumber()); // 0.033366...
|
|
260
|
+
console.log(t2.toNumber()); // 5
|
|
261
|
+
|
|
262
|
+
const sum = t.add(t2);
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Style properties
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
import {
|
|
269
|
+
StyleProperties,
|
|
270
|
+
FontStyleType, // normal | italic | oblique
|
|
271
|
+
FontWeightType, // normal | bold
|
|
272
|
+
TextAlignType, // left | center | right | start | end | justify
|
|
273
|
+
DisplayAlignType, // before | center | after
|
|
274
|
+
NamedColors, // white, black, red, green, blue, cyan, magenta, yellow, transparent
|
|
275
|
+
makeColor, // makeColor(r, g, b, a?) → ColorType
|
|
276
|
+
} from 'omakase-ttconv-ts';
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## License
|
|
280
|
+
|
|
281
|
+
BSD-2-Clause
|