bloom-player 2.20.0-alpha.2 → 2.20.0-alpha.3
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/dist/{bloomPlayer-CpTXugnQ.css → bloomPlayer-QXwbsTI2.css} +1 -1
- package/dist/{bloomPlayer.CdHp5c3Q.js → bloomPlayer.CyOA-cvW.js} +5 -5
- package/dist/bloomplayer.htm +2 -2
- package/lib/shared.es.js +1376 -1356
- package/lib/shared.es.js.map +1 -1
- package/package.json +1 -1
- package/src/shared/narration.ts +73 -23
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "A library for displaying Bloom books in iframes or WebViews",
|
|
4
4
|
"author": "SIL Global",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "2.20.0-alpha.
|
|
6
|
+
"version": "2.20.0-alpha.3",
|
|
7
7
|
"packageManager": "pnpm@11.1.2",
|
|
8
8
|
"private": false,
|
|
9
9
|
"// sideeffects might need to be ['*.css'] to avoid 'shaking' our CSS, if we ever get tree shaking working": "",
|
package/src/shared/narration.ts
CHANGED
|
@@ -1454,6 +1454,74 @@ function playAllVideoInternal(
|
|
|
1454
1454
|
hideVideoError(video);
|
|
1455
1455
|
hideVideoAutoplayBlockedHint(video);
|
|
1456
1456
|
setCurrentPlaybackMode(PlaybackMode.VideoPlaying);
|
|
1457
|
+
// Always play each queued video from the beginning.
|
|
1458
|
+
// Without this, a previously played element may remain at end-of-stream
|
|
1459
|
+
// and fail to raise the expected ended event for sequencing.
|
|
1460
|
+
video.currentTime = 0;
|
|
1461
|
+
// Note that we get a new instance of this for each recursive call to playAllVideoInternal.
|
|
1462
|
+
// It serves to make sure we don't try to advance twice if we get both an ended and a pause event.
|
|
1463
|
+
let advanced = false;
|
|
1464
|
+
let watchdogTimerId: number | undefined;
|
|
1465
|
+
const watchdogGraceMs = 250;
|
|
1466
|
+
const clearWatchdog = () => {
|
|
1467
|
+
if (watchdogTimerId !== undefined) {
|
|
1468
|
+
window.clearTimeout(watchdogTimerId);
|
|
1469
|
+
watchdogTimerId = undefined;
|
|
1470
|
+
}
|
|
1471
|
+
};
|
|
1472
|
+
const scheduleWatchdogFromDuration = () => {
|
|
1473
|
+
const duration = video.duration;
|
|
1474
|
+
if (!Number.isFinite(duration) || duration <= 0) {
|
|
1475
|
+
return;
|
|
1476
|
+
}
|
|
1477
|
+
clearWatchdog();
|
|
1478
|
+
const playbackRate =
|
|
1479
|
+
Number.isFinite(video.playbackRate) && video.playbackRate > 0
|
|
1480
|
+
? video.playbackRate
|
|
1481
|
+
: 1;
|
|
1482
|
+
const timeoutMs = Math.max(
|
|
1483
|
+
duration * 1000 / playbackRate + watchdogGraceMs,
|
|
1484
|
+
watchdogGraceMs,
|
|
1485
|
+
);
|
|
1486
|
+
watchdogTimerId = window.setTimeout(() => {
|
|
1487
|
+
advanceToNextVideo();
|
|
1488
|
+
}, timeoutMs);
|
|
1489
|
+
};
|
|
1490
|
+
const advanceToNextVideo = () => {
|
|
1491
|
+
if (advanced) {
|
|
1492
|
+
return;
|
|
1493
|
+
}
|
|
1494
|
+
advanced = true;
|
|
1495
|
+
clearWatchdog();
|
|
1496
|
+
video.removeEventListener("ended", endedHandler);
|
|
1497
|
+
video.removeEventListener("pause", pauseHandler);
|
|
1498
|
+
video.removeEventListener("loadedmetadata", metadataHandler);
|
|
1499
|
+
if (generation !== playAllVideoGeneration) {
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1502
|
+
playAllVideoInternal(elements.slice(1), then, generation);
|
|
1503
|
+
};
|
|
1504
|
+
const endedHandler = () => {
|
|
1505
|
+
advanceToNextVideo();
|
|
1506
|
+
};
|
|
1507
|
+
// In some environments, playback can pause at the end without raising ended.
|
|
1508
|
+
// Treat that as completion so a short first video can't stall the sequence.
|
|
1509
|
+
const pauseHandler = () => {
|
|
1510
|
+
const duration = video.duration;
|
|
1511
|
+
if (!Number.isFinite(duration) || duration <= 0) {
|
|
1512
|
+
return;
|
|
1513
|
+
}
|
|
1514
|
+
if (video.currentTime >= duration - 0.05) {
|
|
1515
|
+
advanceToNextVideo();
|
|
1516
|
+
}
|
|
1517
|
+
};
|
|
1518
|
+
const metadataHandler = () => {
|
|
1519
|
+
scheduleWatchdogFromDuration();
|
|
1520
|
+
};
|
|
1521
|
+
// Register ended before play() so we don't miss extremely fast end transitions.
|
|
1522
|
+
video.addEventListener("ended", endedHandler, { once: true });
|
|
1523
|
+
video.addEventListener("pause", pauseHandler);
|
|
1524
|
+
video.addEventListener("loadedmetadata", metadataHandler);
|
|
1457
1525
|
const promise = video.play();
|
|
1458
1526
|
promise
|
|
1459
1527
|
.then(() => {
|
|
@@ -1462,34 +1530,16 @@ function playAllVideoInternal(
|
|
|
1462
1530
|
}
|
|
1463
1531
|
transientVideoRetryCounts.delete(video);
|
|
1464
1532
|
hideVideoAutoplayBlockedHint(video);
|
|
1465
|
-
|
|
1466
|
-
// Note: in Bloom Desktop, sometimes this event does not fire normally, even when the video is
|
|
1467
|
-
// played to the end. I have not figured out why. It may be something to do with how we are
|
|
1468
|
-
// trimming the videos.
|
|
1469
|
-
// In Bloom Desktop, this is worked around by raising the ended event when we detect that it has
|
|
1470
|
-
// paused past the end point in resetToStartAfterPlayingToEndPoint.
|
|
1471
|
-
// In BloomPlayer,I don't think this is a problem. Videos are trimmed when published, so we always
|
|
1472
|
-
// play to the real end (unless the user pauses). So one way or another, we should get the ended
|
|
1473
|
-
// event.
|
|
1474
|
-
video.addEventListener(
|
|
1475
|
-
"ended",
|
|
1476
|
-
() => {
|
|
1477
|
-
if (generation !== playAllVideoGeneration) {
|
|
1478
|
-
return;
|
|
1479
|
-
}
|
|
1480
|
-
playAllVideoInternal(
|
|
1481
|
-
elements.slice(1),
|
|
1482
|
-
then,
|
|
1483
|
-
generation,
|
|
1484
|
-
);
|
|
1485
|
-
},
|
|
1486
|
-
{ once: true },
|
|
1487
|
-
);
|
|
1533
|
+
scheduleWatchdogFromDuration();
|
|
1488
1534
|
})
|
|
1489
1535
|
.catch((reason) => {
|
|
1490
1536
|
if (generation !== playAllVideoGeneration) {
|
|
1491
1537
|
return;
|
|
1492
1538
|
}
|
|
1539
|
+
clearWatchdog();
|
|
1540
|
+
video.removeEventListener("ended", endedHandler);
|
|
1541
|
+
video.removeEventListener("pause", pauseHandler);
|
|
1542
|
+
video.removeEventListener("loadedmetadata", metadataHandler);
|
|
1493
1543
|
if (reason?.name === "NotAllowedError") {
|
|
1494
1544
|
console.debug(
|
|
1495
1545
|
"Video autoplay blocked until user interaction",
|