Skip to content

Commit 0c5da96

Browse files
committed
FIX: gaps between captions
1 parent 1e4f9ec commit 0c5da96

File tree

8 files changed

+1634
-71
lines changed

8 files changed

+1634
-71
lines changed

dist/editor/index.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/player/index.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/script/index.js

+109-56
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/script/index.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/common/captions.ts

+27
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,33 @@ export interface Caption {
1919
words: Word[];
2020
}
2121

22+
/**
23+
* Groups captions with same words into groups.
24+
* @param captions captions
25+
* @returns groups of captions with same words
26+
*/
27+
export function captionGroups(captions: Caption[]): Caption[][] {
28+
const groups: Caption[][] = [];
29+
let lastCaption: Caption | null = null;
30+
let lastGroup: Caption[] = [];
31+
32+
for (const caption of captions) {
33+
if (lastCaption && !haveSameWords(caption, lastCaption!)) {
34+
groups.push(lastGroup);
35+
lastGroup = [];
36+
}
37+
38+
lastGroup.push(caption);
39+
lastCaption = caption;
40+
}
41+
42+
if (lastGroup.length) {
43+
groups.push(lastGroup);
44+
}
45+
46+
return groups;
47+
}
48+
2249
export function haveSameWords(caption1: Caption, caption2: Caption): boolean {
2350
if (caption1.words.length != caption2.words.length) {
2451
return false;

src/script/step-recorder.ts

+36-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as puppeteer from 'puppeteer';
22
import * as cliProgress from 'cli-progress';
33
import {PNG, PNGWithMetadata} from 'pngjs';
4-
import {Caption} from '../common/captions';
4+
import {Caption, captionGroups} from '../common/captions';
55
import {StepRenderer} from './step-renderer';
66
import {Args} from './cli';
77
import {AbstractRecorder} from './abstract-recorder';
@@ -15,6 +15,8 @@ export class StepRecorder extends AbstractRecorder {
1515
}
1616

1717
public async recordCaptionsVideo(indexHtml: string) {
18+
const groups = captionGroups(this.captions);
19+
1820
this.progressBar.start(this.captions.length, 0);
1921

2022
try {
@@ -26,23 +28,27 @@ export class StepRecorder extends AbstractRecorder {
2628
const beginningTime = this.captions[0].startTimeMs;
2729
this.renderer.addEmptyFrame(beginningTime);
2830

29-
for (let i = 0; i < this.captions.length; i++) {
30-
const caption = this.captions[i];
31+
for (let i = 0; i < groups.length; i++) {
32+
const captionGroup = StepRecorder.adjustCaptionsDuration(groups[i]);
3133

32-
await this.nextStep();
34+
for (const caption of captionGroup) {
35+
await this.nextStep();
36+
const screenShot = await this.takeScreenShot(videoElem!);
37+
this.renderer.addFrame(caption, screenShot);
38+
this.progressBar.increment();
39+
}
3340

34-
const screenShot = await this.takeScreenShot(videoElem!);
35-
this.renderer.addFrame(caption, screenShot);
41+
// Add delay before the next caption group
42+
if (i < groups.length - 1) {
43+
const nextCaptionGroup = groups[i + 1];
44+
const lastCaption = captionGroup[captionGroup.length - 1];
45+
const nextCaption = nextCaptionGroup[0];
3646

37-
// Add delay before the next frame
38-
if (i < this.captions.length - 1) {
39-
const idleDelay = this.captions[i + 1].startTimeMs - caption.endTimeMs;
47+
const idleDelay = nextCaption.startTimeMs - lastCaption.endTimeMs;
4048
if (idleDelay) {
4149
this.renderer.addEmptyFrame(idleDelay);
4250
}
4351
}
44-
45-
this.progressBar.increment();
4652
}
4753

4854
this.progressBar.stop();
@@ -67,4 +73,23 @@ export class StepRecorder extends AbstractRecorder {
6773
});
6874
return PNG.sync.read(Buffer.from(screenshotBuffer));
6975
}
76+
77+
private static adjustCaptionsDuration(captionGroup: Caption[]): Caption[] {
78+
if (captionGroup.length < 2) {
79+
return captionGroup;
80+
}
81+
82+
const adjustedGroup: Caption[] = [];
83+
84+
for (let i = 0; i < captionGroup.length - 1; i++) {
85+
const caption = Object.assign({}, captionGroup[i]);
86+
const nextCaption = captionGroup[i + 1];
87+
caption.endTimeMs = nextCaption.startTimeMs;
88+
adjustedGroup.push(caption);
89+
}
90+
91+
adjustedGroup.push(captionGroup[captionGroup.length - 1]);
92+
93+
return adjustedGroup;
94+
}
7095
}

test/common/captions.test.ts

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import {expect} from 'chai';
2-
import {Caption, haveSameWords, readWords, splitText} from '../../src/common/captions';
2+
import {Caption, captionGroups, haveSameWords, readCaptions, readWords, splitText} from '../../src/common/captions';
3+
import {readFileSync} from 'fs';
4+
5+
const exampleSrt = readFileSync('test/resources/example.srt', 'utf-8');
36

47
it('haveSameWords', () => {
58
// Given
@@ -208,3 +211,18 @@ describe('readCaptions', () => {
208211
]);
209212
});
210213
});
214+
215+
it('captionGroups', () => {
216+
// Given
217+
const captions = readCaptions(exampleSrt);
218+
219+
// When
220+
const groups = captionGroups(captions);
221+
222+
// Then
223+
console.dir(groups[0], {depth:null});
224+
console.dir(groups[1], {depth:null});
225+
226+
expect(groups[0]).to.have.lengthOf(1);
227+
expect(groups[1]).to.have.lengthOf(4);
228+
});

0 commit comments

Comments
 (0)