eb-player 2.2.0 → 2.3.0
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.
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.EBPlayer = {}));
|
|
5
5
|
})(this, (function (exports) { 'use strict';
|
|
6
6
|
|
|
7
|
-
var __EB_PLAYER_VERSION__ = "2.
|
|
7
|
+
var __EB_PLAYER_VERSION__ = "2.3.0";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Finite State Machine for player playback state transitions.
|
|
@@ -4388,6 +4388,170 @@
|
|
|
4388
4388
|
};
|
|
4389
4389
|
}
|
|
4390
4390
|
|
|
4391
|
+
var subtitlesParserVtt = {exports: {}};
|
|
4392
|
+
|
|
4393
|
+
var hasRequiredSubtitlesParserVtt;
|
|
4394
|
+
|
|
4395
|
+
function requireSubtitlesParserVtt () {
|
|
4396
|
+
if (hasRequiredSubtitlesParserVtt) return subtitlesParserVtt.exports;
|
|
4397
|
+
hasRequiredSubtitlesParserVtt = 1;
|
|
4398
|
+
(function (module, exports) {
|
|
4399
|
+
var parser = (function () {
|
|
4400
|
+
var pItems = {};
|
|
4401
|
+
|
|
4402
|
+
/**
|
|
4403
|
+
* Converts SubRip subtitles into array of objects
|
|
4404
|
+
* [{
|
|
4405
|
+
* id: `Number of subtitle`
|
|
4406
|
+
* startTime: `Start time of subtitle`
|
|
4407
|
+
* endTime: `End time of subtitle
|
|
4408
|
+
* text: `Text of subtitle`
|
|
4409
|
+
* }]
|
|
4410
|
+
*
|
|
4411
|
+
* @param {String} data SubRip suntitles string
|
|
4412
|
+
* @param {Boolean} ms Optional: use milliseconds for startTime and endTime
|
|
4413
|
+
* @return {Array}
|
|
4414
|
+
*/
|
|
4415
|
+
pItems.fromVtt = function (data, timeFormat, isYoutubeAutoTranscript) {
|
|
4416
|
+
var useYoutubeAutoTranscript = isYoutubeAutoTranscript ? true : false;
|
|
4417
|
+
data = data.replace(/\r/g, "");
|
|
4418
|
+
var regex = /(\d+)?\n?(\d{2}:\d{2}:\d{2}[,.]\d{3}) --> (\d{2}:\d{2}:\d{2}[,.]\d{3}).*\n/g;
|
|
4419
|
+
data = data.split(regex);
|
|
4420
|
+
data.shift();
|
|
4421
|
+
var items = [];
|
|
4422
|
+
for (var i = 0; i < data.length; i += 4) {
|
|
4423
|
+
var text = data[i + 3];
|
|
4424
|
+
if (useYoutubeAutoTranscript) {
|
|
4425
|
+
text = text.split("\n");
|
|
4426
|
+
text.shift();
|
|
4427
|
+
text = text.join("\n");
|
|
4428
|
+
}
|
|
4429
|
+
if (text.trim().length === 0) continue;
|
|
4430
|
+
items.push({
|
|
4431
|
+
id: data[i] ? +data[i].trim() : items.length + 1,
|
|
4432
|
+
startTime: changeTimeFormat(data[i + 1].trim(), timeFormat),
|
|
4433
|
+
endTime: changeTimeFormat(data[i + 2].trim(), timeFormat),
|
|
4434
|
+
text: text.trim(),
|
|
4435
|
+
});
|
|
4436
|
+
}
|
|
4437
|
+
return items;
|
|
4438
|
+
};
|
|
4439
|
+
|
|
4440
|
+
/**
|
|
4441
|
+
* Converts Array of objects created by this module to SubRip subtitles
|
|
4442
|
+
* @param {Array} data
|
|
4443
|
+
* @return {String} SubRip subtitles string
|
|
4444
|
+
*/
|
|
4445
|
+
pItems.toVtt = function (data) {
|
|
4446
|
+
if (!data instanceof Array) return "";
|
|
4447
|
+
var res = "";
|
|
4448
|
+
|
|
4449
|
+
for (var i = 0; i < data.length; i++) {
|
|
4450
|
+
var s = data[i];
|
|
4451
|
+
|
|
4452
|
+
if (!isNaN(s.startTime) && !isNaN(s.endTime)) {
|
|
4453
|
+
s.startTime = msTime(parseInt(s.startTime, 10));
|
|
4454
|
+
s.endTime = msTime(parseInt(s.endTime, 10));
|
|
4455
|
+
}
|
|
4456
|
+
|
|
4457
|
+
res += s.id + "\r\n";
|
|
4458
|
+
res += s.startTime + " --> " + s.endTime + "\r\n";
|
|
4459
|
+
res += s.text.replace("\n", "\r\n") + "\r\n\r\n";
|
|
4460
|
+
}
|
|
4461
|
+
|
|
4462
|
+
return res;
|
|
4463
|
+
};
|
|
4464
|
+
|
|
4465
|
+
var changeTimeFormat = function (time, format) {
|
|
4466
|
+
if (format === "ms") {
|
|
4467
|
+
return timeMs(time);
|
|
4468
|
+
} else if (format === "s") {
|
|
4469
|
+
return timeMs(time) / 1000;
|
|
4470
|
+
} else {
|
|
4471
|
+
return time;
|
|
4472
|
+
}
|
|
4473
|
+
};
|
|
4474
|
+
|
|
4475
|
+
var timeMs = function (val) {
|
|
4476
|
+
var regex = /(\d+):(\d{2}):(\d{2})[,.](\d{3})/;
|
|
4477
|
+
var parts = regex.exec(val);
|
|
4478
|
+
|
|
4479
|
+
if (parts === null) {
|
|
4480
|
+
return 0;
|
|
4481
|
+
}
|
|
4482
|
+
|
|
4483
|
+
for (var i = 1; i < 5; i++) {
|
|
4484
|
+
parts[i] = parseInt(parts[i], 10);
|
|
4485
|
+
if (isNaN(parts[i])) parts[i] = 0;
|
|
4486
|
+
}
|
|
4487
|
+
|
|
4488
|
+
// hours + minutes + seconds + ms
|
|
4489
|
+
return parts[1] * 3600000 + parts[2] * 60000 + parts[3] * 1000 + parts[4];
|
|
4490
|
+
};
|
|
4491
|
+
|
|
4492
|
+
var msTime = function (val) {
|
|
4493
|
+
var measures = [3600000, 60000, 1000];
|
|
4494
|
+
var time = [];
|
|
4495
|
+
|
|
4496
|
+
for (var i in measures) {
|
|
4497
|
+
var res = ((val / measures[i]) >> 0).toString();
|
|
4498
|
+
|
|
4499
|
+
if (res.length < 2) res = "0" + res;
|
|
4500
|
+
val %= measures[i];
|
|
4501
|
+
time.push(res);
|
|
4502
|
+
}
|
|
4503
|
+
|
|
4504
|
+
var ms = val.toString();
|
|
4505
|
+
if (ms.length < 3) {
|
|
4506
|
+
for (i = 0; i <= 3 - ms.length; i++) ms = "0" + ms;
|
|
4507
|
+
}
|
|
4508
|
+
|
|
4509
|
+
return time.join(":") + "," + ms;
|
|
4510
|
+
};
|
|
4511
|
+
|
|
4512
|
+
return pItems;
|
|
4513
|
+
})();
|
|
4514
|
+
|
|
4515
|
+
// ignore exports for browser
|
|
4516
|
+
{
|
|
4517
|
+
module.exports = parser;
|
|
4518
|
+
}
|
|
4519
|
+
} (subtitlesParserVtt));
|
|
4520
|
+
return subtitlesParserVtt.exports;
|
|
4521
|
+
}
|
|
4522
|
+
|
|
4523
|
+
var subtitlesParserVttExports = requireSubtitlesParserVtt();
|
|
4524
|
+
|
|
4525
|
+
/**
|
|
4526
|
+
* Parses a WebVTT string into an array of ChapterMark objects.
|
|
4527
|
+
* Returns an empty array if the content is empty or contains no parseable cues.
|
|
4528
|
+
*/
|
|
4529
|
+
function parseChapters(vttContent) {
|
|
4530
|
+
if (!vttContent || !vttContent.trim()) {
|
|
4531
|
+
return [];
|
|
4532
|
+
}
|
|
4533
|
+
const cues = subtitlesParserVttExports.fromVtt(vttContent, 's');
|
|
4534
|
+
return cues.map((cue) => ({
|
|
4535
|
+
title: cue.text,
|
|
4536
|
+
startTime: cue.startTime,
|
|
4537
|
+
endTime: cue.endTime
|
|
4538
|
+
}));
|
|
4539
|
+
}
|
|
4540
|
+
/**
|
|
4541
|
+
* Fetches a WebVTT chapters file from a URL and parses it.
|
|
4542
|
+
* Returns an empty array if the fetch or parse fails.
|
|
4543
|
+
*/
|
|
4544
|
+
async function fetchChapters(url) {
|
|
4545
|
+
try {
|
|
4546
|
+
const response = await fetch(url);
|
|
4547
|
+
const text = await response.text();
|
|
4548
|
+
return parseChapters(text);
|
|
4549
|
+
}
|
|
4550
|
+
catch {
|
|
4551
|
+
return [];
|
|
4552
|
+
}
|
|
4553
|
+
}
|
|
4554
|
+
|
|
4391
4555
|
/**
|
|
4392
4556
|
* PlayerController manages the complete lifecycle of a player instance.
|
|
4393
4557
|
*
|
|
@@ -4588,6 +4752,25 @@
|
|
|
4588
4752
|
// CRITICAL: AbortController is one-shot. Create a fresh one for re-mount.
|
|
4589
4753
|
this.abortController = new AbortController();
|
|
4590
4754
|
}
|
|
4755
|
+
/**
|
|
4756
|
+
* Populate state.chapters from config.chapters.
|
|
4757
|
+
*
|
|
4758
|
+
* The value is either an inline WebVTT string or an http(s) URL pointing at a
|
|
4759
|
+
* .vtt file. A remote fetch is fire-and-forget and non-critical: fetchChapters
|
|
4760
|
+
* resolves to an empty array on failure, and a result arriving after dispose()
|
|
4761
|
+
* is discarded rather than written into a torn-down state.
|
|
4762
|
+
*/
|
|
4763
|
+
loadChapters(source, state, signal) {
|
|
4764
|
+
if (/^https?:\/\//i.test(source.trim())) {
|
|
4765
|
+
void fetchChapters(source).then((chapters) => {
|
|
4766
|
+
if (!signal.aborted) {
|
|
4767
|
+
state.chapters = chapters;
|
|
4768
|
+
}
|
|
4769
|
+
});
|
|
4770
|
+
return;
|
|
4771
|
+
}
|
|
4772
|
+
state.chapters = parseChapters(source);
|
|
4773
|
+
}
|
|
4591
4774
|
/**
|
|
4592
4775
|
* Initialize integration managers based on config flags.
|
|
4593
4776
|
* All integrations are async and non-critical — errors are caught and logged.
|
|
@@ -4630,6 +4813,10 @@
|
|
|
4630
4813
|
});
|
|
4631
4814
|
}
|
|
4632
4815
|
}
|
|
4816
|
+
// Chapters: skip when config.chapters is not set
|
|
4817
|
+
if (config.chapters) {
|
|
4818
|
+
this.loadChapters(config.chapters, state, signal);
|
|
4819
|
+
}
|
|
4633
4820
|
// IntroStreamManager: skip when config.preroll is false (D-02)
|
|
4634
4821
|
if (config.preroll && this.skinRoot !== null) {
|
|
4635
4822
|
const introManager = new IntroStreamManager();
|