captions.js 0.3.1 → 0.4.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/README.md +1 -1
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +64 -25
- package/dist/index.mjs +64 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Star or watch the repo on GitHub to get updates!
|
|
|
7
7
|
|
|
8
8
|
# Captions.js
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Render styled animated captions on canvas — works both on client and server side using Node.js and FFmpeg.
|
|
11
11
|
|
|
12
12
|
[**Live Demo**](https://maskin25.github.io/captions.js/)
|
|
13
13
|
|
package/dist/index.d.mts
CHANGED
|
@@ -138,6 +138,8 @@ type CaptionsOptions = {
|
|
|
138
138
|
captions?: Caption[] | null;
|
|
139
139
|
/** When false, caller must invoke {@link Captions.enable} manually. */
|
|
140
140
|
autoEnable?: boolean;
|
|
141
|
+
/** Show debug bounding boxes around lines/blocks. */
|
|
142
|
+
debug?: boolean;
|
|
141
143
|
};
|
|
142
144
|
/**
|
|
143
145
|
* Imperative controller that owns the Konva stage lifecycle for a single video element.
|
|
@@ -158,6 +160,7 @@ declare class Captions {
|
|
|
158
160
|
private animationFrameId;
|
|
159
161
|
private videoWidth;
|
|
160
162
|
private videoHeight;
|
|
163
|
+
private readonly debug;
|
|
161
164
|
private readonly handleResize;
|
|
162
165
|
private readonly handleMetadata;
|
|
163
166
|
private readonly animationLoop;
|
package/dist/index.d.ts
CHANGED
|
@@ -138,6 +138,8 @@ type CaptionsOptions = {
|
|
|
138
138
|
captions?: Caption[] | null;
|
|
139
139
|
/** When false, caller must invoke {@link Captions.enable} manually. */
|
|
140
140
|
autoEnable?: boolean;
|
|
141
|
+
/** Show debug bounding boxes around lines/blocks. */
|
|
142
|
+
debug?: boolean;
|
|
141
143
|
};
|
|
142
144
|
/**
|
|
143
145
|
* Imperative controller that owns the Konva stage lifecycle for a single video element.
|
|
@@ -158,6 +160,7 @@ declare class Captions {
|
|
|
158
160
|
private animationFrameId;
|
|
159
161
|
private videoWidth;
|
|
160
162
|
private videoHeight;
|
|
163
|
+
private readonly debug;
|
|
161
164
|
private readonly handleResize;
|
|
162
165
|
private readonly handleMetadata;
|
|
163
166
|
private readonly animationLoop;
|
package/dist/index.js
CHANGED
|
@@ -1229,13 +1229,14 @@ var splitCaptionsBytotalWordsToDisplay = (captions, totalWordsToDisplay, linesPe
|
|
|
1229
1229
|
let currentLine = 1;
|
|
1230
1230
|
const maxWordGapSec = 1;
|
|
1231
1231
|
const isValidBlockGap = (currentBlock2, caption) => {
|
|
1232
|
+
return true;
|
|
1232
1233
|
return currentBlock2.length > 0 && caption.startTime - currentBlock2[currentBlock2.length - 1].endTime < maxWordGapSec || currentBlock2.length === 0;
|
|
1233
1234
|
};
|
|
1234
1235
|
while (currentCaptionIndex < captions.length) {
|
|
1235
1236
|
const caption = captions[currentCaptionIndex];
|
|
1236
|
-
if (currentSymbolsLength + caption.word.length <= totalWordsToDisplay && isValidBlockGap(currentBlock, caption)) {
|
|
1237
|
+
if (currentSymbolsLength + caption.word.length + 1 <= totalWordsToDisplay && isValidBlockGap(currentBlock, caption)) {
|
|
1237
1238
|
currentBlock.push(caption);
|
|
1238
|
-
currentSymbolsLength += caption.word.length;
|
|
1239
|
+
currentSymbolsLength += caption.word.length + 1;
|
|
1239
1240
|
currentCaptionIndex++;
|
|
1240
1241
|
} else if (linesPerPage > currentLine && isValidBlockGap(currentBlock, caption)) {
|
|
1241
1242
|
currentBlock.push(caption);
|
|
@@ -1304,14 +1305,23 @@ var getCaptionsGroupY = (groupHeight, canvasWidth, canvasHeight, position, offse
|
|
|
1304
1305
|
}
|
|
1305
1306
|
};
|
|
1306
1307
|
var alignLinesInGroup = (group, maxGroupWidth, xOffset) => {
|
|
1307
|
-
group.children.
|
|
1308
|
+
return group.children.map((line) => {
|
|
1308
1309
|
const lineWords = line.children;
|
|
1309
1310
|
const lineWordsWidth = lineWords.reduce(
|
|
1310
1311
|
(acc, word, currentIndex) => acc + word.width() + (currentIndex > 0 ? xOffset : 0),
|
|
1311
1312
|
0
|
|
1312
1313
|
);
|
|
1314
|
+
const lineHeight = lineWords.reduce(
|
|
1315
|
+
(acc, word) => Math.max(acc, word.height()),
|
|
1316
|
+
0
|
|
1317
|
+
);
|
|
1313
1318
|
const lineX = (maxGroupWidth - lineWordsWidth) / 2;
|
|
1314
1319
|
line.x(lineX);
|
|
1320
|
+
return {
|
|
1321
|
+
line,
|
|
1322
|
+
width: lineWordsWidth,
|
|
1323
|
+
height: lineHeight
|
|
1324
|
+
};
|
|
1315
1325
|
});
|
|
1316
1326
|
};
|
|
1317
1327
|
var alphabetEN = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
@@ -1359,10 +1369,24 @@ function isArabic(text) {
|
|
|
1359
1369
|
// src/canvas-captions/index.ts
|
|
1360
1370
|
var import_object_hash = __toESM(require("object-hash"));
|
|
1361
1371
|
var memo = {};
|
|
1362
|
-
var
|
|
1363
|
-
const
|
|
1372
|
+
var drawDebugBoundingBox = (parent, width, height, stroke, dash = [6, 4]) => {
|
|
1373
|
+
const rect = new import_konva4.default.Rect({
|
|
1374
|
+
x: 0,
|
|
1375
|
+
y: 0,
|
|
1376
|
+
width,
|
|
1377
|
+
height,
|
|
1378
|
+
stroke,
|
|
1379
|
+
strokeWidth: 4,
|
|
1380
|
+
dash,
|
|
1381
|
+
listening: false
|
|
1382
|
+
});
|
|
1383
|
+
parent.add(rect);
|
|
1384
|
+
rect.moveToTop();
|
|
1385
|
+
};
|
|
1386
|
+
var renderFrame = (captionsSettings, layoutSettings, captions, currentTime, targetSize, layer, toCoef, debug) => {
|
|
1364
1387
|
const [width, height] = targetSize;
|
|
1365
1388
|
const targetFontSize = captionsSettings.style.font.fontSize * (toCoef ?? 1);
|
|
1389
|
+
const showDebugBoundingBoxes = Boolean(debug);
|
|
1366
1390
|
let totalSymbolInLine = 0;
|
|
1367
1391
|
const hash = (0, import_object_hash.default)({ captionsSettings });
|
|
1368
1392
|
if (memo[hash]) {
|
|
@@ -1397,24 +1421,28 @@ var renderFrame = (captionsSettings, layoutSettings, captions, currentTime, targ
|
|
|
1397
1421
|
}
|
|
1398
1422
|
const chunks = splitCaptionsBytotalWordsToDisplay(
|
|
1399
1423
|
captions,
|
|
1400
|
-
totalSymbolInLine
|
|
1424
|
+
totalSymbolInLine,
|
|
1401
1425
|
captionsSettings.linesPerPage
|
|
1402
1426
|
);
|
|
1403
1427
|
const currentChunk = chunks.find(
|
|
1404
1428
|
(chunk) => chunk[0].startTime <= currentTime && chunk[chunk.length - 1].endTime >= currentTime
|
|
1405
1429
|
);
|
|
1406
1430
|
const xOffset = targetFontSize * 0.1;
|
|
1431
|
+
const wordSpacing = xOffset + (captionsSettings.animation === "bounce" ? 8 : 0) + (captionsSettings.style.font.fontCapitalize ? 2 : 0);
|
|
1407
1432
|
const yOffset = captionsSettings.lineSpacing ?? 4;
|
|
1408
1433
|
if (currentChunk) {
|
|
1409
|
-
|
|
1434
|
+
const group = new import_konva4.default.Group({
|
|
1435
|
+
drawBorder: true
|
|
1436
|
+
});
|
|
1410
1437
|
let x = 0;
|
|
1411
1438
|
let y = 0;
|
|
1412
1439
|
let maxGroupWidth = 0;
|
|
1413
1440
|
let groupWidth = 0;
|
|
1414
1441
|
let groupHeight = 0;
|
|
1415
|
-
let line = new import_konva4.default.Group(
|
|
1442
|
+
let line = new import_konva4.default.Group({
|
|
1443
|
+
drawBorder: true
|
|
1444
|
+
});
|
|
1416
1445
|
let currentSymbolsLength = 0;
|
|
1417
|
-
let box = new import_konva4.default.Group();
|
|
1418
1446
|
let current = void 0;
|
|
1419
1447
|
currentChunk.forEach((caption, index) => {
|
|
1420
1448
|
const isCurrentCaption = caption.startTime <= currentTime && caption.endTime >= currentTime;
|
|
@@ -1449,7 +1477,9 @@ var renderFrame = (captionsSettings, layoutSettings, captions, currentTime, targ
|
|
|
1449
1477
|
shadowOffset: captionsSettings2.style.font.shadow ? {
|
|
1450
1478
|
x: captionsSettings2.style.font.shadow?.fontShadowOffsetX ?? 0,
|
|
1451
1479
|
y: captionsSettings2.style.font.shadow?.fontShadowOffsetY ?? 0
|
|
1452
|
-
} : void 0
|
|
1480
|
+
} : void 0,
|
|
1481
|
+
listening: false,
|
|
1482
|
+
perfectDrawEnabled: false
|
|
1453
1483
|
});
|
|
1454
1484
|
};
|
|
1455
1485
|
const text = createKonvaText(
|
|
@@ -1478,8 +1508,8 @@ var renderFrame = (captionsSettings, layoutSettings, captions, currentTime, targ
|
|
|
1478
1508
|
//progress: Math.min(1, (currentTime - caption.start_time) / 0.5),
|
|
1479
1509
|
};
|
|
1480
1510
|
}
|
|
1481
|
-
x += text.width() +
|
|
1482
|
-
groupWidth += text.width() + (isLastWordInLine ? 0 :
|
|
1511
|
+
x += text.width() + wordSpacing;
|
|
1512
|
+
groupWidth += text.width() + (isLastWordInLine ? 0 : wordSpacing);
|
|
1483
1513
|
line.y(y);
|
|
1484
1514
|
line.add(text);
|
|
1485
1515
|
if (isLastWordInLine) {
|
|
@@ -1492,13 +1522,15 @@ var renderFrame = (captionsSettings, layoutSettings, captions, currentTime, targ
|
|
|
1492
1522
|
maxGroupWidth = groupWidth;
|
|
1493
1523
|
}
|
|
1494
1524
|
groupWidth = 0;
|
|
1495
|
-
line = new import_konva4.default.Group(
|
|
1525
|
+
line = new import_konva4.default.Group({
|
|
1526
|
+
drawBorder: true
|
|
1527
|
+
});
|
|
1496
1528
|
currentSymbolsLength = 0;
|
|
1497
1529
|
} else {
|
|
1498
|
-
currentSymbolsLength += caption.word.length;
|
|
1530
|
+
currentSymbolsLength += caption.word.length + 1;
|
|
1499
1531
|
}
|
|
1500
1532
|
});
|
|
1501
|
-
alignLinesInGroup(group, maxGroupWidth,
|
|
1533
|
+
const lineMetrics = alignLinesInGroup(group, maxGroupWidth, wordSpacing);
|
|
1502
1534
|
const progress = Math.min(
|
|
1503
1535
|
1,
|
|
1504
1536
|
(currentTime - currentChunk[0].startTime) / 0.2
|
|
@@ -1511,8 +1543,8 @@ var renderFrame = (captionsSettings, layoutSettings, captions, currentTime, targ
|
|
|
1511
1543
|
groupHeight,
|
|
1512
1544
|
width,
|
|
1513
1545
|
height,
|
|
1514
|
-
|
|
1515
|
-
|
|
1546
|
+
captionsSettings.position,
|
|
1547
|
+
captionsSettings.positionTopOffset ?? 0,
|
|
1516
1548
|
toCoef ?? 1
|
|
1517
1549
|
)
|
|
1518
1550
|
);
|
|
@@ -1526,6 +1558,12 @@ var renderFrame = (captionsSettings, layoutSettings, captions, currentTime, targ
|
|
|
1526
1558
|
},
|
|
1527
1559
|
current
|
|
1528
1560
|
);
|
|
1561
|
+
if (showDebugBoundingBoxes) {
|
|
1562
|
+
drawDebugBoundingBox(group, maxGroupWidth, groupHeight, "#ff4081");
|
|
1563
|
+
lineMetrics.forEach(({ line: line2, width: width2, height: height2 }) => {
|
|
1564
|
+
drawDebugBoundingBox(line2, width2, height2, "#2196f3", [4, 3]);
|
|
1565
|
+
});
|
|
1566
|
+
}
|
|
1529
1567
|
if (current?.text && captionsSettings.animation === "box-word") {
|
|
1530
1568
|
current.text?.zIndex(10);
|
|
1531
1569
|
}
|
|
@@ -1566,6 +1604,7 @@ var Captions = class {
|
|
|
1566
1604
|
this.providedContainer = options.container;
|
|
1567
1605
|
this.presetState = options.preset;
|
|
1568
1606
|
this.captionsState = options.captions ?? null;
|
|
1607
|
+
this.debug = options.debug ?? false;
|
|
1569
1608
|
if (options.autoEnable ?? true) {
|
|
1570
1609
|
this.enable();
|
|
1571
1610
|
}
|
|
@@ -1582,7 +1621,7 @@ var Captions = class {
|
|
|
1582
1621
|
this.stage = new import_konva5.default.Stage({
|
|
1583
1622
|
container: this.containerElement
|
|
1584
1623
|
});
|
|
1585
|
-
this.layer = new import_konva5.default.Layer();
|
|
1624
|
+
this.layer = new import_konva5.default.Layer({ listening: false });
|
|
1586
1625
|
this.stage.add(this.layer);
|
|
1587
1626
|
this.videoWidth = this.video.videoWidth;
|
|
1588
1627
|
this.videoHeight = this.video.videoHeight;
|
|
@@ -1681,19 +1720,15 @@ var Captions = class {
|
|
|
1681
1720
|
return;
|
|
1682
1721
|
}
|
|
1683
1722
|
this.layer.destroyChildren();
|
|
1684
|
-
const captionsSettings = this.presetState.captionsSettings;
|
|
1685
1723
|
renderFrame(
|
|
1686
|
-
captionsSettings,
|
|
1724
|
+
this.presetState.captionsSettings,
|
|
1687
1725
|
void 0,
|
|
1688
1726
|
this.captionsState || [],
|
|
1689
1727
|
this.video.currentTime,
|
|
1690
1728
|
[this.videoWidth, this.videoHeight],
|
|
1691
1729
|
this.layer,
|
|
1692
1730
|
2,
|
|
1693
|
-
|
|
1694
|
-
type: captionsSettings.position ?? "bottom",
|
|
1695
|
-
positionTopOffset: captionsSettings.positionTopOffset ?? 0
|
|
1696
|
-
}
|
|
1731
|
+
this.debug
|
|
1697
1732
|
);
|
|
1698
1733
|
}
|
|
1699
1734
|
syncStageDimensions() {
|
|
@@ -1734,7 +1769,11 @@ var Captions = class {
|
|
|
1734
1769
|
container.style.width = "100%";
|
|
1735
1770
|
container.style.height = "100%";
|
|
1736
1771
|
container.style.pointerEvents = "none";
|
|
1737
|
-
this.video.parentElement
|
|
1772
|
+
const parent = this.video.parentElement;
|
|
1773
|
+
parent?.appendChild(container);
|
|
1774
|
+
if (parent) {
|
|
1775
|
+
parent.style.position = "relative";
|
|
1776
|
+
}
|
|
1738
1777
|
return container;
|
|
1739
1778
|
}
|
|
1740
1779
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -1187,13 +1187,14 @@ var splitCaptionsBytotalWordsToDisplay = (captions, totalWordsToDisplay, linesPe
|
|
|
1187
1187
|
let currentLine = 1;
|
|
1188
1188
|
const maxWordGapSec = 1;
|
|
1189
1189
|
const isValidBlockGap = (currentBlock2, caption) => {
|
|
1190
|
+
return true;
|
|
1190
1191
|
return currentBlock2.length > 0 && caption.startTime - currentBlock2[currentBlock2.length - 1].endTime < maxWordGapSec || currentBlock2.length === 0;
|
|
1191
1192
|
};
|
|
1192
1193
|
while (currentCaptionIndex < captions.length) {
|
|
1193
1194
|
const caption = captions[currentCaptionIndex];
|
|
1194
|
-
if (currentSymbolsLength + caption.word.length <= totalWordsToDisplay && isValidBlockGap(currentBlock, caption)) {
|
|
1195
|
+
if (currentSymbolsLength + caption.word.length + 1 <= totalWordsToDisplay && isValidBlockGap(currentBlock, caption)) {
|
|
1195
1196
|
currentBlock.push(caption);
|
|
1196
|
-
currentSymbolsLength += caption.word.length;
|
|
1197
|
+
currentSymbolsLength += caption.word.length + 1;
|
|
1197
1198
|
currentCaptionIndex++;
|
|
1198
1199
|
} else if (linesPerPage > currentLine && isValidBlockGap(currentBlock, caption)) {
|
|
1199
1200
|
currentBlock.push(caption);
|
|
@@ -1262,14 +1263,23 @@ var getCaptionsGroupY = (groupHeight, canvasWidth, canvasHeight, position, offse
|
|
|
1262
1263
|
}
|
|
1263
1264
|
};
|
|
1264
1265
|
var alignLinesInGroup = (group, maxGroupWidth, xOffset) => {
|
|
1265
|
-
group.children.
|
|
1266
|
+
return group.children.map((line) => {
|
|
1266
1267
|
const lineWords = line.children;
|
|
1267
1268
|
const lineWordsWidth = lineWords.reduce(
|
|
1268
1269
|
(acc, word, currentIndex) => acc + word.width() + (currentIndex > 0 ? xOffset : 0),
|
|
1269
1270
|
0
|
|
1270
1271
|
);
|
|
1272
|
+
const lineHeight = lineWords.reduce(
|
|
1273
|
+
(acc, word) => Math.max(acc, word.height()),
|
|
1274
|
+
0
|
|
1275
|
+
);
|
|
1271
1276
|
const lineX = (maxGroupWidth - lineWordsWidth) / 2;
|
|
1272
1277
|
line.x(lineX);
|
|
1278
|
+
return {
|
|
1279
|
+
line,
|
|
1280
|
+
width: lineWordsWidth,
|
|
1281
|
+
height: lineHeight
|
|
1282
|
+
};
|
|
1273
1283
|
});
|
|
1274
1284
|
};
|
|
1275
1285
|
var alphabetEN = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
@@ -1317,10 +1327,24 @@ function isArabic(text) {
|
|
|
1317
1327
|
// src/canvas-captions/index.ts
|
|
1318
1328
|
import objectHash from "object-hash";
|
|
1319
1329
|
var memo = {};
|
|
1320
|
-
var
|
|
1321
|
-
const
|
|
1330
|
+
var drawDebugBoundingBox = (parent, width, height, stroke, dash = [6, 4]) => {
|
|
1331
|
+
const rect = new Konva4.Rect({
|
|
1332
|
+
x: 0,
|
|
1333
|
+
y: 0,
|
|
1334
|
+
width,
|
|
1335
|
+
height,
|
|
1336
|
+
stroke,
|
|
1337
|
+
strokeWidth: 4,
|
|
1338
|
+
dash,
|
|
1339
|
+
listening: false
|
|
1340
|
+
});
|
|
1341
|
+
parent.add(rect);
|
|
1342
|
+
rect.moveToTop();
|
|
1343
|
+
};
|
|
1344
|
+
var renderFrame = (captionsSettings, layoutSettings, captions, currentTime, targetSize, layer, toCoef, debug) => {
|
|
1322
1345
|
const [width, height] = targetSize;
|
|
1323
1346
|
const targetFontSize = captionsSettings.style.font.fontSize * (toCoef ?? 1);
|
|
1347
|
+
const showDebugBoundingBoxes = Boolean(debug);
|
|
1324
1348
|
let totalSymbolInLine = 0;
|
|
1325
1349
|
const hash = objectHash({ captionsSettings });
|
|
1326
1350
|
if (memo[hash]) {
|
|
@@ -1355,24 +1379,28 @@ var renderFrame = (captionsSettings, layoutSettings, captions, currentTime, targ
|
|
|
1355
1379
|
}
|
|
1356
1380
|
const chunks = splitCaptionsBytotalWordsToDisplay(
|
|
1357
1381
|
captions,
|
|
1358
|
-
totalSymbolInLine
|
|
1382
|
+
totalSymbolInLine,
|
|
1359
1383
|
captionsSettings.linesPerPage
|
|
1360
1384
|
);
|
|
1361
1385
|
const currentChunk = chunks.find(
|
|
1362
1386
|
(chunk) => chunk[0].startTime <= currentTime && chunk[chunk.length - 1].endTime >= currentTime
|
|
1363
1387
|
);
|
|
1364
1388
|
const xOffset = targetFontSize * 0.1;
|
|
1389
|
+
const wordSpacing = xOffset + (captionsSettings.animation === "bounce" ? 8 : 0) + (captionsSettings.style.font.fontCapitalize ? 2 : 0);
|
|
1365
1390
|
const yOffset = captionsSettings.lineSpacing ?? 4;
|
|
1366
1391
|
if (currentChunk) {
|
|
1367
|
-
|
|
1392
|
+
const group = new Konva4.Group({
|
|
1393
|
+
drawBorder: true
|
|
1394
|
+
});
|
|
1368
1395
|
let x = 0;
|
|
1369
1396
|
let y = 0;
|
|
1370
1397
|
let maxGroupWidth = 0;
|
|
1371
1398
|
let groupWidth = 0;
|
|
1372
1399
|
let groupHeight = 0;
|
|
1373
|
-
let line = new Konva4.Group(
|
|
1400
|
+
let line = new Konva4.Group({
|
|
1401
|
+
drawBorder: true
|
|
1402
|
+
});
|
|
1374
1403
|
let currentSymbolsLength = 0;
|
|
1375
|
-
let box = new Konva4.Group();
|
|
1376
1404
|
let current = void 0;
|
|
1377
1405
|
currentChunk.forEach((caption, index) => {
|
|
1378
1406
|
const isCurrentCaption = caption.startTime <= currentTime && caption.endTime >= currentTime;
|
|
@@ -1407,7 +1435,9 @@ var renderFrame = (captionsSettings, layoutSettings, captions, currentTime, targ
|
|
|
1407
1435
|
shadowOffset: captionsSettings2.style.font.shadow ? {
|
|
1408
1436
|
x: captionsSettings2.style.font.shadow?.fontShadowOffsetX ?? 0,
|
|
1409
1437
|
y: captionsSettings2.style.font.shadow?.fontShadowOffsetY ?? 0
|
|
1410
|
-
} : void 0
|
|
1438
|
+
} : void 0,
|
|
1439
|
+
listening: false,
|
|
1440
|
+
perfectDrawEnabled: false
|
|
1411
1441
|
});
|
|
1412
1442
|
};
|
|
1413
1443
|
const text = createKonvaText(
|
|
@@ -1436,8 +1466,8 @@ var renderFrame = (captionsSettings, layoutSettings, captions, currentTime, targ
|
|
|
1436
1466
|
//progress: Math.min(1, (currentTime - caption.start_time) / 0.5),
|
|
1437
1467
|
};
|
|
1438
1468
|
}
|
|
1439
|
-
x += text.width() +
|
|
1440
|
-
groupWidth += text.width() + (isLastWordInLine ? 0 :
|
|
1469
|
+
x += text.width() + wordSpacing;
|
|
1470
|
+
groupWidth += text.width() + (isLastWordInLine ? 0 : wordSpacing);
|
|
1441
1471
|
line.y(y);
|
|
1442
1472
|
line.add(text);
|
|
1443
1473
|
if (isLastWordInLine) {
|
|
@@ -1450,13 +1480,15 @@ var renderFrame = (captionsSettings, layoutSettings, captions, currentTime, targ
|
|
|
1450
1480
|
maxGroupWidth = groupWidth;
|
|
1451
1481
|
}
|
|
1452
1482
|
groupWidth = 0;
|
|
1453
|
-
line = new Konva4.Group(
|
|
1483
|
+
line = new Konva4.Group({
|
|
1484
|
+
drawBorder: true
|
|
1485
|
+
});
|
|
1454
1486
|
currentSymbolsLength = 0;
|
|
1455
1487
|
} else {
|
|
1456
|
-
currentSymbolsLength += caption.word.length;
|
|
1488
|
+
currentSymbolsLength += caption.word.length + 1;
|
|
1457
1489
|
}
|
|
1458
1490
|
});
|
|
1459
|
-
alignLinesInGroup(group, maxGroupWidth,
|
|
1491
|
+
const lineMetrics = alignLinesInGroup(group, maxGroupWidth, wordSpacing);
|
|
1460
1492
|
const progress = Math.min(
|
|
1461
1493
|
1,
|
|
1462
1494
|
(currentTime - currentChunk[0].startTime) / 0.2
|
|
@@ -1469,8 +1501,8 @@ var renderFrame = (captionsSettings, layoutSettings, captions, currentTime, targ
|
|
|
1469
1501
|
groupHeight,
|
|
1470
1502
|
width,
|
|
1471
1503
|
height,
|
|
1472
|
-
|
|
1473
|
-
|
|
1504
|
+
captionsSettings.position,
|
|
1505
|
+
captionsSettings.positionTopOffset ?? 0,
|
|
1474
1506
|
toCoef ?? 1
|
|
1475
1507
|
)
|
|
1476
1508
|
);
|
|
@@ -1484,6 +1516,12 @@ var renderFrame = (captionsSettings, layoutSettings, captions, currentTime, targ
|
|
|
1484
1516
|
},
|
|
1485
1517
|
current
|
|
1486
1518
|
);
|
|
1519
|
+
if (showDebugBoundingBoxes) {
|
|
1520
|
+
drawDebugBoundingBox(group, maxGroupWidth, groupHeight, "#ff4081");
|
|
1521
|
+
lineMetrics.forEach(({ line: line2, width: width2, height: height2 }) => {
|
|
1522
|
+
drawDebugBoundingBox(line2, width2, height2, "#2196f3", [4, 3]);
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1487
1525
|
if (current?.text && captionsSettings.animation === "box-word") {
|
|
1488
1526
|
current.text?.zIndex(10);
|
|
1489
1527
|
}
|
|
@@ -1524,6 +1562,7 @@ var Captions = class {
|
|
|
1524
1562
|
this.providedContainer = options.container;
|
|
1525
1563
|
this.presetState = options.preset;
|
|
1526
1564
|
this.captionsState = options.captions ?? null;
|
|
1565
|
+
this.debug = options.debug ?? false;
|
|
1527
1566
|
if (options.autoEnable ?? true) {
|
|
1528
1567
|
this.enable();
|
|
1529
1568
|
}
|
|
@@ -1540,7 +1579,7 @@ var Captions = class {
|
|
|
1540
1579
|
this.stage = new Konva5.Stage({
|
|
1541
1580
|
container: this.containerElement
|
|
1542
1581
|
});
|
|
1543
|
-
this.layer = new Konva5.Layer();
|
|
1582
|
+
this.layer = new Konva5.Layer({ listening: false });
|
|
1544
1583
|
this.stage.add(this.layer);
|
|
1545
1584
|
this.videoWidth = this.video.videoWidth;
|
|
1546
1585
|
this.videoHeight = this.video.videoHeight;
|
|
@@ -1639,19 +1678,15 @@ var Captions = class {
|
|
|
1639
1678
|
return;
|
|
1640
1679
|
}
|
|
1641
1680
|
this.layer.destroyChildren();
|
|
1642
|
-
const captionsSettings = this.presetState.captionsSettings;
|
|
1643
1681
|
renderFrame(
|
|
1644
|
-
captionsSettings,
|
|
1682
|
+
this.presetState.captionsSettings,
|
|
1645
1683
|
void 0,
|
|
1646
1684
|
this.captionsState || [],
|
|
1647
1685
|
this.video.currentTime,
|
|
1648
1686
|
[this.videoWidth, this.videoHeight],
|
|
1649
1687
|
this.layer,
|
|
1650
1688
|
2,
|
|
1651
|
-
|
|
1652
|
-
type: captionsSettings.position ?? "bottom",
|
|
1653
|
-
positionTopOffset: captionsSettings.positionTopOffset ?? 0
|
|
1654
|
-
}
|
|
1689
|
+
this.debug
|
|
1655
1690
|
);
|
|
1656
1691
|
}
|
|
1657
1692
|
syncStageDimensions() {
|
|
@@ -1692,7 +1727,11 @@ var Captions = class {
|
|
|
1692
1727
|
container.style.width = "100%";
|
|
1693
1728
|
container.style.height = "100%";
|
|
1694
1729
|
container.style.pointerEvents = "none";
|
|
1695
|
-
this.video.parentElement
|
|
1730
|
+
const parent = this.video.parentElement;
|
|
1731
|
+
parent?.appendChild(container);
|
|
1732
|
+
if (parent) {
|
|
1733
|
+
parent.style.position = "relative";
|
|
1734
|
+
}
|
|
1696
1735
|
return container;
|
|
1697
1736
|
}
|
|
1698
1737
|
};
|