Skip to content

Commit 984adb5

Browse files
authored
Merge pull request #1 from goatandsheep/init
init commit
2 parents 57dcc8b + 510a3c9 commit 984adb5

14 files changed

Lines changed: 113 additions & 423 deletions

README.md

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
# WebVTT compiler parser and segmenter
1+
# Subrip (.srt) compiler parser and segmenter
22

3-
Compiles, parses WebVTT files, segments and generates HLS playlists for them.
3+
Compiles, parses Subrip files, segments and generates HLS playlists for them.
44

5-
[![CircleCI](https://circleci.com/gh/osk/node-webvtt.svg?style=svg)](https://circleci.com/gh/osk/node-webvtt)
5+
[![CircleCI](https://circleci.com/gh/goatandsheep/node-srt.svg?style=svg)](https://circleci.com/gh/goatandsheep/node-srt)
6+
7+
This is a sister package to [osk/node-webvtt](https://github.com/osk/node-webvtt).
68

79
## Usage
810

9-
For a WebVTT file:
11+
For a Subrip file:
1012

1113
```text
12-
WEBVTT
13-
1414
00:00:00.000 --> 00:00:01.000
1515
Hello world!
1616
@@ -24,24 +24,24 @@ Foo
2424
Bar
2525
```
2626

27-
We can parse, segment and create HLS playlists, and compile back to WebVTT format:
27+
We can parse, segment and create HLS playlists, and compile back to Subrip format:
2828

2929
```javascript
30-
const webvtt = require('node-webvtt');
30+
const subrip = require('node-srt');
3131

3232
const segmentDuration = 10; // default to 10
3333
const startOffset = 0; // Starting MPEG TS offset to be used in timestamp map, default 900000
3434

35-
const parsed = webvtt.parse(input);
36-
const compile = webvtt.compile(input);
37-
const segmented = webvtt.parse(input, segmentDuration);
38-
const playlist = webvtt.hls.hlsSegmentPlaylist(input, segmentDuration);
39-
const segments = webvtt.hls.hlsSegment(input, segmentDuration, startOffset);
35+
const parsed = subrip.parse(input);
36+
const compile = subrip.compile(input);
37+
const segmented = subrip.parse(input, segmentDuration);
38+
const playlist = subrip.hls.hlsSegmentPlaylist(input, segmentDuration);
39+
const segments = subrip.hls.hlsSegment(input, segmentDuration, startOffset);
4040
```
4141

4242
### Parsing
4343

44-
Parses the WebVTT file and returns an object with `valid === true` if parsed correctly and an array of cues parsed.
44+
Parses the Subrip file and returns an object with `valid === true` if parsed correctly and an array of cues parsed.
4545

4646
Each cue can have:
4747

@@ -51,7 +51,7 @@ Each cue can have:
5151
* `text` - Text of the subtitle
5252
* `styles` - If any of the cue
5353

54-
If the WebVTT file is invalid, the parser will throw a `ParserError` exception. So for safety, calls to `parse` should be in `try catch`.
54+
If the Subrip file is invalid, the parser will throw a `ParserError` exception. So for safety, calls to `parse` should be in `try catch`.
5555

5656
For the above example we'd get:
5757

@@ -124,21 +124,17 @@ result = {
124124

125125
### Metadata
126126

127-
Some WebVTT strings may also contain lines of metadata after the initial `WEBVTT` line, for example:
127+
Some Subrip strings may also contain lines of metadata after the initial `WEBVTT` line, for example:
128128

129129
```text
130-
WEBVTT
131-
Kind: captions
132-
Language: en
133-
134130
00:00:00.000 --> 00:00:01.000
135131
Hello world!
136132
```
137133

138134
By passing `{ meta: true }` to the `parse` method, these metadata will be returned as an object called `meta`. For example, parsing the above example:
139135

140136
```javascript
141-
parse(webvtt, { meta: true });
137+
parse(subrip, { meta: true });
142138
```
143139

144140
would return the following:
@@ -166,7 +162,7 @@ If no metadata is available, `meta` will be set to `null` in the result if the o
166162

167163
### Compiling
168164

169-
Compiles JSON from the above format back into a WebVTT string. If a `meta` key is in the input,
165+
Compiles JSON from the above format back into a Subrip string. If a `meta` key is in the input,
170166
it will be compiled as well. The `meta` value must be an object and each key and value must be a string.
171167

172168
If the object is missing any attributes, the compiler will throw a `CompilerError` exception. So
@@ -191,10 +187,6 @@ const input = {
191187
const result = compile(input);
192188

193189
/*
194-
WEBVTT
195-
Kind: captions
196-
Language: en
197-
198190
1
199191
00:02:15.001 --> 00:02:20.000
200192
Hello world
@@ -267,16 +259,16 @@ Creates a list of HLS segments for the subtitles, returning an array of them wit
267259

268260
## CLI
269261

270-
For segmenting a WebVTT file quickly, you can use the included CLI tool:
262+
For segmenting a Subrip file quickly, you can use the included CLI tool:
271263

272264
```bash
273-
./webvtt-segment.js -v --target-duration 10 -o ./subs subs.vtt
265+
./subrip-segment.js -v --target-duration 10 -o ./subs subs.vtt
274266
```
275267

276268
```bash
277-
$ ./webvtt-segment.js --help
269+
$ ./subrip-segment.js --help
278270

279-
Usage: webvtt-segment [options] <webvtt file>
271+
Usage: subrip-segment [options] <subrip file>
280272

281273
Options:
282274

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const program = require('commander');
88

99
program
1010
.version('0.0.1')
11-
.usage('[options] <webvtt file>')
11+
.usage('[options] <subrip file>')
1212
.option('-t, --target-duration [duration]',
1313
'Target duration for each segment in secods, defaults to 10',
1414
parseInt,
@@ -24,7 +24,7 @@ const input = program.args;
2424
const t = program.targetDuration || 10;
2525
const outputDir = program.outputDirectory || './';
2626

27-
log('Hi there! Let’s try and parse and segment a webvtt file, shall we');
27+
log('Hi there! Let’s try and parse and segment a subrip file, shall we');
2828
log(`Output directory is: ${outputDir}`);
2929
log(`Target duration is: ${t}`);
3030

lib/compiler.js

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,12 @@ function compile (input) {
2929
throw new CompilerError('Input must be valid');
3030
}
3131

32-
let output = 'WEBVTT\n';
33-
34-
if (input.meta) {
35-
if (typeof input.meta !== 'object' || Array.isArray(input.meta)) {
36-
throw new CompilerError('Metadata must be an object');
37-
}
38-
39-
Object.entries(input.meta).forEach((i) => {
40-
if (typeof i[1] !== 'string') {
41-
throw new CompilerError(`Metadata value for "${i[0]}" must be string`);
42-
}
43-
44-
output += `${i[0]}: ${i[1]}\n`;
45-
});
32+
if (input && (!input.cues || input.cues.length < 1)) {
33+
return '';
4634
}
4735

36+
let output = '';
37+
4838
let lastTime = null;
4939

5040
input.cues.forEach((cue, index) => {
@@ -55,12 +45,11 @@ function compile (input) {
5545

5646
lastTime = cue.start;
5747

58-
output += '\n';
5948
output += compileCue(cue);
60-
output += '\n';
49+
output += '\n\n';
6150
});
6251

63-
return output;
52+
return output.slice(0, -1);
6453
}
6554

6655
/**

lib/hls.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ function hlsSegment (input, segmentLength, startOffset) {
1313
const result = [];
1414
segments.forEach((seg, i) => {
1515

16-
const content = `WEBVTT
17-
X-TIMESTAMP-MAP=MPEGTS:${startOffset},LOCAL:00:00:00.000
16+
const content = `X-TIMESTAMP-MAP=MPEGTS:${startOffset},LOCAL:00:00:00.000
1817
1918
${printableCues(seg.cues)}
2019
`;
@@ -49,7 +48,7 @@ function pad (num, n) {
4948
}
5049

5150
function generateSegmentFilename (index) {
52-
return `${index}.vtt`;
51+
return `${index}.srt`;
5352
}
5453

5554
function printableSegments (segments) {

lib/parser.js

Lines changed: 4 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ function parse (input, options) {
1818
options = {};
1919
}
2020

21-
const { meta = false, strict = true } = options;
21+
const { strict = true } = options;
2222

2323
if (typeof input !== 'string') {
2424
throw new ParserError('Input must be a string');
@@ -29,59 +29,23 @@ function parse (input, options) {
2929
input = input.replace(/\r/g, '\n');
3030

3131
const parts = input.split('\n\n');
32-
const header = parts.shift();
33-
34-
if (!header.startsWith('WEBVTT')) {
35-
throw new ParserError('Must start with "WEBVTT"');
36-
}
37-
38-
const headerParts = header.split('\n');
39-
40-
const headerComments = headerParts[0].replace('WEBVTT', '');
41-
42-
if (headerComments.length > 0
43-
&& (headerComments[0] !== ' ' && headerComments[0] !== '\t')
44-
) {
45-
throw new ParserError('Header comment must start with space or tab');
46-
}
4732

4833
// nothing of interests, return early
49-
if (parts.length === 0 && headerParts.length === 1) {
34+
if (parts.length === 0) {
5035
return { valid: true, strict, cues: [], errors: [] };
5136
}
5237

53-
if (!meta && headerParts.length > 1 && headerParts[1] !== '') {
54-
throw new ParserError('Missing blank line after signature');
55-
}
56-
5738
const { cues, errors } = parseCues(parts, strict);
5839

5940
if (strict && errors.length > 0) {
6041
throw errors[0];
6142
}
6243

63-
const headerMeta = meta ? parseMeta(headerParts) : null;
64-
6544
const result = { valid: errors.length === 0, strict, cues, errors };
6645

67-
if (meta) {
68-
result.meta = headerMeta;
69-
}
70-
7146
return result;
7247
}
7348

74-
function parseMeta (headerParts) {
75-
const meta = {};
76-
headerParts.slice(1).forEach(header => {
77-
const splitIdx = header.indexOf(':');
78-
const key = header.slice(0, splitIdx).trim();
79-
const value = header.slice(splitIdx + 1).trim();
80-
meta[key] = value;
81-
});
82-
return Object.keys(meta).length > 0 ? meta : null;
83-
}
84-
8549
function parseCues (cues, strict) {
8650
const errors = [];
8751

@@ -145,6 +109,8 @@ function parseCue (cue, i, strict) {
145109
!validTimestamp(times[0]) ||
146110
!validTimestamp(times[1])) {
147111

112+
console.log('times', times);
113+
console.log('lines', lines);
148114
throw new ParserError(`Invalid cue timestamp (cue #${i})`);
149115
}
150116

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
{
2-
"name": "node-webvtt",
2+
"name": "node-srt",
33
"version": "1.9.3",
4-
"description": "WebVTT parser, compiler, and segmenter with HLS support",
4+
"description": "SRT parser, compiler, and segmenter with HLS support",
55
"main": "index.js",
66
"scripts": {
77
"eslint": "eslint *.js **/*.js",
88
"test": "npm run eslint -s && nyc mocha -R dot"
99
},
1010
"keywords": [
11-
"webvtt",
12-
"vtt",
1311
"segment",
1412
"hls",
1513
"subtitle",
1614
"closed",
17-
"caption"
15+
"caption",
16+
"srt",
17+
"subrip"
1818
],
1919
"repository": {
2020
"type": "git",
21-
"url": "git://github.com/osk/node-webvtt"
21+
"url": "git://github.com/goatandsheep/node-srt"
2222
},
23-
"author": "Ólafur Sverrir Kjartansson <kjarni@gmail.com>",
23+
"author": "Kemal Ahmed <goatandsheep@gmail.com>",
2424
"license": "MIT",
2525
"devDependencies": {
2626
"chai": "^4.2.0",
@@ -40,7 +40,7 @@
4040
"index.js"
4141
],
4242
"bin": {
43-
"webvtt-segment": "./bin/webvtt-segment.js"
43+
"subrip-segment": "./bin/subrip-segment.js"
4444
},
4545
"nyc": {
4646
"extension": [

0 commit comments

Comments
 (0)