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 CHANGED
@@ -7,7 +7,7 @@ Star or watch the repo on GitHub to get updates!
7
7
 
8
8
  # Captions.js
9
9
 
10
- A modern JavaScript library for adding captions to HTML5 videos with ease.
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.forEach((line, i) => {
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 renderFrame = (captionsSettings, layoutSettings, captions, currentTime, targetSize, layer, toCoef, position) => {
1363
- const style = captionsSettings.style.name;
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 - 6,
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
- var group = new import_konva4.default.Group();
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() + xOffset + (captionsSettings.animation === "bounce" ? 8 : 0) + (captionsSettings.style.font.fontCapitalize ? 2 : 0);
1482
- groupWidth += text.width() + (isLastWordInLine ? 0 : xOffset);
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, xOffset);
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
- position?.type ?? captionsSettings.position,
1515
- position?.positionTopOffset ?? captionsSettings.positionTopOffset ?? 0,
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?.appendChild(container);
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.forEach((line, i) => {
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 renderFrame = (captionsSettings, layoutSettings, captions, currentTime, targetSize, layer, toCoef, position) => {
1321
- const style = captionsSettings.style.name;
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 - 6,
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
- var group = new Konva4.Group();
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() + xOffset + (captionsSettings.animation === "bounce" ? 8 : 0) + (captionsSettings.style.font.fontCapitalize ? 2 : 0);
1440
- groupWidth += text.width() + (isLastWordInLine ? 0 : xOffset);
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, xOffset);
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
- position?.type ?? captionsSettings.position,
1473
- position?.positionTopOffset ?? captionsSettings.positionTopOffset ?? 0,
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?.appendChild(container);
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
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "captions.js",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "repository": {