-
Notifications
You must be signed in to change notification settings - Fork 30
/
segmenter.js
118 lines (91 loc) · 3.04 KB
/
segmenter.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
'use strict';
const parse = require('./parser').parse;
function segment (input, segmentLength) {
segmentLength = segmentLength || 10;
const parsed = parse(input);
const segments = [];
let cues = [];
let queuedCue = null;
let currentSegmentDuration = 0;
let totalSegmentsDuration = 0;
/**
* One pass segmenting of cues
*/
parsed.cues.forEach((cue, i) => {
const firstCue = i === 0;
const lastCue = i === parsed.cues.length - 1;
const start = cue.start;
const end = cue.end;
const nextStart = lastCue ? Infinity : parsed.cues[i + 1].start;
const cueLength = firstCue ? end : end - start;
const silence = firstCue ? 0 : (start - parsed.cues[i - 1].end);
currentSegmentDuration = currentSegmentDuration + cueLength + silence;
debug('------------');
debug(`Cue #${i}, segment #${segments.length + 1}`);
debug(`Start ${start}`);
debug(`End ${end}`);
debug(`Length ${cueLength}`);
debug(`Total segment duration = ${totalSegmentsDuration}`);
debug(`Current segment duration = ${currentSegmentDuration}`);
debug(`Start of next = ${nextStart}`);
// if there's a boundary cue queued, push and clear queue
if (queuedCue) {
cues.push(queuedCue);
currentSegmentDuration += queuedCue.end - totalSegmentsDuration;
queuedCue = null;
}
cues.push(cue);
// if a cue passes a segment boundary, it appears in both
let shouldQueue = nextStart - end < segmentLength &&
silence < segmentLength &&
currentSegmentDuration > segmentLength;
if (shouldSegment(totalSegmentsDuration, segmentLength, nextStart,
silence)) {
const duration = segmentDuration(lastCue, end, segmentLength,
currentSegmentDuration,
totalSegmentsDuration);
segments.push({ duration, cues });
totalSegmentsDuration += duration;
currentSegmentDuration = 0;
cues = [];
} else {
shouldQueue = false;
}
if (shouldQueue) {
queuedCue = cue;
}
});
return segments;
}
function shouldSegment (total, length, nextStart, silence) {
// this is stupid, but gets one case fixed...
const x = alignToSegmentLength(silence, length);
const nextCueIsInNextSegment = silence <= length ||
x + total < nextStart;
return nextCueIsInNextSegment && nextStart - total >= length;
}
function segmentDuration (lastCue, end, length, currentSegment, totalSegments) {
let duration = length;
if (currentSegment > length) {
duration = alignToSegmentLength(currentSegment - length, length);
}
// make sure the last cue covers the whole time of the cues
if (lastCue) {
duration = parseFloat((end - totalSegments).toFixed(2));
} else {
duration = Math.round(duration);
}
return duration;
}
function alignToSegmentLength (n, segmentLength) {
n += segmentLength - n % segmentLength;
return n;
}
const debugging = false;
/* istanbul ignore next */
function debug (m) {
if (debugging) {
console.log(m);
}
}
module.exports = { segment };