@kodezen/player 1.0.2 → 1.0.4
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 +21 -1
- package/dist/index.cjs +244 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -3
- package/dist/index.d.ts +17 -3
- package/dist/index.js +244 -19
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +248 -21
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +2 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +248 -21
- package/dist/react/index.js.map +1 -1
- package/dist/styles.css +100 -9
- package/dist/{types-TFltFgey.d.cts → types-30yBj4ll.d.cts} +20 -1
- package/dist/{types-TFltFgey.d.ts → types-30yBj4ll.d.ts} +20 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -91,8 +91,7 @@ var Html5Provider = class {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
play() {
|
|
94
|
-
void this.video.play().catch(() =>
|
|
95
|
-
});
|
|
94
|
+
void this.video.play().catch(() => this.emitter.emit("pause"));
|
|
96
95
|
}
|
|
97
96
|
pause() {
|
|
98
97
|
this.video.pause();
|
|
@@ -374,8 +373,8 @@ var VimeoProvider = class {
|
|
|
374
373
|
this.emitter.emit("ready");
|
|
375
374
|
}
|
|
376
375
|
play() {
|
|
377
|
-
var _a, _b;
|
|
378
|
-
|
|
376
|
+
var _a, _b, _c, _d;
|
|
377
|
+
(_d = (_c = (_b = (_a = this.player) == null ? void 0 : _a.play) == null ? void 0 : _b.call(_a)) == null ? void 0 : _c.catch) == null ? void 0 : _d.call(_c, () => this.emitter.emit("pause"));
|
|
379
378
|
}
|
|
380
379
|
pause() {
|
|
381
380
|
var _a, _b;
|
|
@@ -445,13 +444,124 @@ function createProvider(source) {
|
|
|
445
444
|
}
|
|
446
445
|
}
|
|
447
446
|
|
|
447
|
+
// src/core/Captions.ts
|
|
448
|
+
var TIMING = /^\s*((?:\d+:)?\d{1,2}:\d{2}[.,]\d{1,3})\s+-->\s+((?:\d+:)?\d{1,2}:\d{2}[.,]\d{1,3})/;
|
|
449
|
+
var ENTITIES = {
|
|
450
|
+
amp: "&",
|
|
451
|
+
lt: "<",
|
|
452
|
+
gt: ">",
|
|
453
|
+
quot: '"',
|
|
454
|
+
apos: "'",
|
|
455
|
+
nbsp: "\xA0",
|
|
456
|
+
lrm: "\u200E",
|
|
457
|
+
rlm: "\u200F"
|
|
458
|
+
};
|
|
459
|
+
function toSeconds(stamp) {
|
|
460
|
+
const [clock = "", fraction = "0"] = stamp.replace(",", ".").split(".");
|
|
461
|
+
const seconds = clock.split(":").reduce((total, part) => total * 60 + Number(part), 0);
|
|
462
|
+
return seconds + Number(`0.${fraction}`);
|
|
463
|
+
}
|
|
464
|
+
function plainText(text) {
|
|
465
|
+
return text.replace(/<[^>]*>/g, "").replace(/&(amp|lt|gt|quot|apos|nbsp|lrm|rlm);/g, (_, name) => {
|
|
466
|
+
var _a;
|
|
467
|
+
return (_a = ENTITIES[name]) != null ? _a : "";
|
|
468
|
+
}).replace(/&#(\d+);/g, (_, code) => String.fromCodePoint(Number(code)));
|
|
469
|
+
}
|
|
470
|
+
function parseVtt(input) {
|
|
471
|
+
var _a;
|
|
472
|
+
const cues = [];
|
|
473
|
+
const blocks = input.replace(/^/, "").replace(/\r\n?/g, "\n").split(/\n{2,}/);
|
|
474
|
+
for (const block of blocks) {
|
|
475
|
+
const lines = block.split("\n");
|
|
476
|
+
const timingAt = lines.findIndex((line) => line.includes("-->"));
|
|
477
|
+
const timing = TIMING.exec((_a = lines[timingAt]) != null ? _a : "");
|
|
478
|
+
if (!(timing == null ? void 0 : timing[1]) || !timing[2]) continue;
|
|
479
|
+
const text = plainText(lines.slice(timingAt + 1).join("\n")).trim();
|
|
480
|
+
if (!text) continue;
|
|
481
|
+
cues.push({ start: toSeconds(timing[1]), end: toSeconds(timing[2]), text });
|
|
482
|
+
}
|
|
483
|
+
return cues.sort((a, b) => a.start - b.start);
|
|
484
|
+
}
|
|
485
|
+
var Captions = class {
|
|
486
|
+
/** `onChange` fires when the active track or track availability changes. */
|
|
487
|
+
constructor(tracks, onChange) {
|
|
488
|
+
this.onChange = onChange;
|
|
489
|
+
this.active = -1;
|
|
490
|
+
this.time = 0;
|
|
491
|
+
this.abort = new AbortController();
|
|
492
|
+
this.el = document.createElement("div");
|
|
493
|
+
this.el.className = "kzp-captions";
|
|
494
|
+
this.el.setAttribute("aria-live", "off");
|
|
495
|
+
this.text = document.createElement("span");
|
|
496
|
+
this.text.className = "kzp-captions-text";
|
|
497
|
+
this.text.hidden = true;
|
|
498
|
+
this.el.appendChild(this.text);
|
|
499
|
+
this.tracks = tracks.map((info) => ({ info, cues: null, failed: false }));
|
|
500
|
+
const preferred = tracks.findIndex((t) => t.default);
|
|
501
|
+
this.tracks.forEach((track, index) => {
|
|
502
|
+
void this.load(track).then(() => {
|
|
503
|
+
if (index === preferred && this.active === -1 && track.cues) this.select(index);
|
|
504
|
+
else this.onChange();
|
|
505
|
+
});
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
async load(track) {
|
|
509
|
+
try {
|
|
510
|
+
const res = await fetch(track.info.src, { signal: this.abort.signal, credentials: "same-origin" });
|
|
511
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
512
|
+
track.cues = parseVtt(await res.text());
|
|
513
|
+
} catch (err) {
|
|
514
|
+
if (this.abort.signal.aborted) return;
|
|
515
|
+
track.failed = true;
|
|
516
|
+
console.warn(`@kodezen/player: could not load captions from ${track.info.src}`, err);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
/** Labels for the menu, one per track (falls back to the language, then a number). */
|
|
520
|
+
labels() {
|
|
521
|
+
return this.tracks.map((t, i) => t.info.label || t.info.srclang || `Track ${i + 1}`);
|
|
522
|
+
}
|
|
523
|
+
/** Whether each track loaded (a failed track is hidden from the controls). */
|
|
524
|
+
available() {
|
|
525
|
+
return this.tracks.map((t) => !t.failed);
|
|
526
|
+
}
|
|
527
|
+
getActive() {
|
|
528
|
+
return this.active;
|
|
529
|
+
}
|
|
530
|
+
/** Show track `index`, or turn captions off with -1. */
|
|
531
|
+
select(index) {
|
|
532
|
+
var _a;
|
|
533
|
+
const track = this.tracks[index];
|
|
534
|
+
this.active = track && !track.failed ? index : -1;
|
|
535
|
+
this.el.lang = (_a = track == null ? void 0 : track.info.srclang) != null ? _a : "";
|
|
536
|
+
this.render();
|
|
537
|
+
this.onChange();
|
|
538
|
+
}
|
|
539
|
+
/** Called with the playhead position on every tick and after a seek. */
|
|
540
|
+
update(time) {
|
|
541
|
+
this.time = time;
|
|
542
|
+
this.render();
|
|
543
|
+
}
|
|
544
|
+
render() {
|
|
545
|
+
var _a, _b;
|
|
546
|
+
const cues = (_b = (_a = this.tracks[this.active]) == null ? void 0 : _a.cues) != null ? _b : [];
|
|
547
|
+
const text = cues.filter((cue) => this.time >= cue.start && this.time < cue.end).map((cue) => cue.text).join("\n");
|
|
548
|
+
if (text !== this.text.textContent) this.text.textContent = text;
|
|
549
|
+
this.text.hidden = !text;
|
|
550
|
+
}
|
|
551
|
+
destroy() {
|
|
552
|
+
this.abort.abort();
|
|
553
|
+
this.el.remove();
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
|
|
448
557
|
// src/core/Controls.ts
|
|
449
558
|
var ICONS = {
|
|
450
559
|
play: '<path d="M8 5v14l11-7z"/>',
|
|
451
560
|
pause: '<path d="M6 5h4v14H6zM14 5h4v14h-4z"/>',
|
|
452
561
|
volume: '<path d="M3 10v4h4l5 5V5L7 10H3zm13.5 2a4.5 4.5 0 0 0-2.5-4v8a4.5 4.5 0 0 0 2.5-4z"/>',
|
|
453
562
|
muted: '<path d="M3 10v4h4l5 5V5L7 10H3zm13 2 3 3 1-1-3-3 3-3-1-1-3 3-3-3-1 1 3 3-3 3 1 1z"/>',
|
|
454
|
-
full: '<path d="M4 4h6v2H6v4H4V4zm10 0h6v6h-2V6h-4V4zM4 14h2v4h4v2H4v-6zm14 0h2v6h-6v-2h4v-4z"/>'
|
|
563
|
+
full: '<path d="M4 4h6v2H6v4H4V4zm10 0h6v6h-2V6h-4V4zM4 14h2v4h4v2H4v-6zm14 0h2v6h-6v-2h4v-4z"/>',
|
|
564
|
+
captions: '<path d="M19 4H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1h3a1 1 0 0 1 1 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1a1 1 0 0 1-1 1h-3a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1h3a1 1 0 0 1 1 1v1z"/>'
|
|
455
565
|
};
|
|
456
566
|
function icon(paths) {
|
|
457
567
|
return `<svg viewBox="0 0 24 24" aria-hidden="true">${paths}</svg>`;
|
|
@@ -471,20 +581,34 @@ var DEFAULT_CONFIG = {
|
|
|
471
581
|
time: true,
|
|
472
582
|
volume: true,
|
|
473
583
|
speed: true,
|
|
584
|
+
captions: true,
|
|
474
585
|
fullscreen: true
|
|
475
586
|
};
|
|
476
587
|
var Controls = class {
|
|
477
588
|
constructor(cb, opts) {
|
|
478
589
|
this.cb = cb;
|
|
590
|
+
this.ccActive = -1;
|
|
591
|
+
// Icons currently drawn, so update() only rewrites a button's SVG when it
|
|
592
|
+
// actually changes (see update()).
|
|
593
|
+
this.playIcon = "";
|
|
594
|
+
this.volIcon = "";
|
|
479
595
|
this.scrubbing = false;
|
|
596
|
+
this.rate = 0;
|
|
597
|
+
this.onOutsideClick = (e) => {
|
|
598
|
+
if (this.el.contains(e.target)) return;
|
|
599
|
+
if (this.speedMenu) this.speedMenu.hidden = true;
|
|
600
|
+
if (this.ccMenu) this.ccMenu.hidden = true;
|
|
601
|
+
};
|
|
480
602
|
this.seekableMax = Infinity;
|
|
603
|
+
var _a;
|
|
481
604
|
this.config = { ...DEFAULT_CONFIG, ...opts.config };
|
|
482
605
|
this.lockSeek = opts.lockSeek;
|
|
483
606
|
this.el = document.createElement("div");
|
|
484
607
|
this.el.className = "kzp-controls";
|
|
485
|
-
this.build(opts.speeds);
|
|
608
|
+
this.build(opts.speeds, (_a = opts.captionLabels) != null ? _a : []);
|
|
609
|
+
document.addEventListener("click", this.onOutsideClick);
|
|
486
610
|
}
|
|
487
|
-
build(speeds) {
|
|
611
|
+
build(speeds, captionLabels) {
|
|
488
612
|
if (this.config.playPause) {
|
|
489
613
|
this.playBtn = this.button("kzp-play", "Play", ICONS.play);
|
|
490
614
|
this.playBtn.addEventListener("click", () => this.cb.onToggle());
|
|
@@ -561,16 +685,72 @@ var Controls = class {
|
|
|
561
685
|
}
|
|
562
686
|
this.speedBtn.addEventListener("click", () => {
|
|
563
687
|
this.speedMenu.hidden = !this.speedMenu.hidden;
|
|
688
|
+
if (this.ccMenu) this.ccMenu.hidden = true;
|
|
564
689
|
});
|
|
565
690
|
wrap.append(this.speedBtn, this.speedMenu);
|
|
566
691
|
this.el.appendChild(wrap);
|
|
567
692
|
}
|
|
693
|
+
if (this.config.captions && captionLabels.length) {
|
|
694
|
+
this.buildCaptions(captionLabels);
|
|
695
|
+
}
|
|
568
696
|
if (this.config.fullscreen) {
|
|
569
697
|
const btn = this.button("kzp-full", "Fullscreen", ICONS.full);
|
|
570
698
|
btn.addEventListener("click", () => this.cb.onFullscreen());
|
|
571
699
|
this.el.appendChild(btn);
|
|
572
700
|
}
|
|
573
701
|
}
|
|
702
|
+
/**
|
|
703
|
+
* One track: the CC button toggles it. Several: it opens a menu (Off + each
|
|
704
|
+
* track), styled like the speed menu. Sits left of the speed control.
|
|
705
|
+
*/
|
|
706
|
+
buildCaptions(labels) {
|
|
707
|
+
const wrap = document.createElement("div");
|
|
708
|
+
wrap.className = "kzp-cc";
|
|
709
|
+
this.ccBtn = this.button("kzp-cc-btn", "Subtitles/closed captions", ICONS.captions);
|
|
710
|
+
this.ccBtn.setAttribute("aria-pressed", "false");
|
|
711
|
+
wrap.appendChild(this.ccBtn);
|
|
712
|
+
if (labels.length === 1) {
|
|
713
|
+
this.ccBtn.addEventListener("click", () => this.cb.onCaptions(this.ccActive === -1 ? 0 : -1));
|
|
714
|
+
} else {
|
|
715
|
+
this.ccMenu = document.createElement("div");
|
|
716
|
+
this.ccMenu.className = "kzp-speed-menu kzp-cc-menu";
|
|
717
|
+
this.ccMenu.hidden = true;
|
|
718
|
+
const items = [{ index: -1, label: "Off" }, ...labels.map((label, index) => ({ index, label }))];
|
|
719
|
+
for (const { index, label } of items) {
|
|
720
|
+
const item = document.createElement("button");
|
|
721
|
+
item.type = "button";
|
|
722
|
+
item.textContent = label;
|
|
723
|
+
item.dataset.track = String(index);
|
|
724
|
+
item.addEventListener("click", () => {
|
|
725
|
+
this.cb.onCaptions(index);
|
|
726
|
+
this.ccMenu.hidden = true;
|
|
727
|
+
});
|
|
728
|
+
this.ccMenu.appendChild(item);
|
|
729
|
+
}
|
|
730
|
+
this.ccBtn.addEventListener("click", () => {
|
|
731
|
+
this.ccMenu.hidden = !this.ccMenu.hidden;
|
|
732
|
+
if (this.speedMenu) this.speedMenu.hidden = true;
|
|
733
|
+
});
|
|
734
|
+
wrap.appendChild(this.ccMenu);
|
|
735
|
+
}
|
|
736
|
+
this.ccWrap = wrap;
|
|
737
|
+
const speed = this.el.querySelector(".kzp-speed");
|
|
738
|
+
this.el.insertBefore(wrap, speed);
|
|
739
|
+
}
|
|
740
|
+
/** Reflect the active caption track, and hide tracks (or the whole control) that failed to load. */
|
|
741
|
+
setCaptions(active, available) {
|
|
742
|
+
var _a;
|
|
743
|
+
this.ccActive = active;
|
|
744
|
+
if (!this.ccBtn || !this.ccWrap) return;
|
|
745
|
+
this.ccWrap.hidden = !available.some(Boolean);
|
|
746
|
+
this.ccBtn.classList.toggle("kzp-cc-btn--on", active !== -1);
|
|
747
|
+
this.ccBtn.setAttribute("aria-pressed", String(active !== -1));
|
|
748
|
+
(_a = this.ccMenu) == null ? void 0 : _a.querySelectorAll("button").forEach((item) => {
|
|
749
|
+
const index = Number(item.dataset.track);
|
|
750
|
+
item.hidden = index !== -1 && !available[index];
|
|
751
|
+
item.classList.toggle("kzp-menu-item--active", index === active);
|
|
752
|
+
});
|
|
753
|
+
}
|
|
574
754
|
button(cls, label, svg) {
|
|
575
755
|
const b = document.createElement("button");
|
|
576
756
|
b.type = "button";
|
|
@@ -587,9 +767,14 @@ var Controls = class {
|
|
|
587
767
|
}
|
|
588
768
|
/** Push the latest state into the DOM. Called on every player timeupdate. */
|
|
589
769
|
update(state, extras) {
|
|
770
|
+
var _a;
|
|
590
771
|
if (this.playBtn) {
|
|
591
|
-
|
|
592
|
-
|
|
772
|
+
const next = state.playing ? ICONS.pause : ICONS.play;
|
|
773
|
+
if (next !== this.playIcon) {
|
|
774
|
+
this.playIcon = next;
|
|
775
|
+
this.playBtn.innerHTML = icon(next);
|
|
776
|
+
this.playBtn.setAttribute("aria-label", state.playing ? "Pause" : "Play");
|
|
777
|
+
}
|
|
593
778
|
}
|
|
594
779
|
if (this.scrubber) {
|
|
595
780
|
this.seekableMax = this.lockSeek ? state.furthest : Infinity;
|
|
@@ -600,14 +785,25 @@ var Controls = class {
|
|
|
600
785
|
this.timeEl.textContent = `${fmt(state.current)} / ${fmt(state.duration)}`;
|
|
601
786
|
}
|
|
602
787
|
if (this.volBtn) {
|
|
603
|
-
|
|
788
|
+
const next = extras.muted || extras.volume === 0 ? ICONS.muted : ICONS.volume;
|
|
789
|
+
if (next !== this.volIcon) {
|
|
790
|
+
this.volIcon = next;
|
|
791
|
+
this.volBtn.innerHTML = icon(next);
|
|
792
|
+
}
|
|
604
793
|
}
|
|
605
794
|
if (this.volRange && document.activeElement !== this.volRange) {
|
|
606
795
|
this.volRange.value = String(extras.muted ? 0 : extras.volume);
|
|
607
796
|
}
|
|
608
|
-
if (this.speedBtn
|
|
797
|
+
if (this.speedBtn && extras.rate !== this.rate) {
|
|
798
|
+
this.rate = extras.rate;
|
|
799
|
+
this.speedBtn.textContent = `${extras.rate}x`;
|
|
800
|
+
(_a = this.speedMenu) == null ? void 0 : _a.querySelectorAll("button").forEach((item) => {
|
|
801
|
+
item.classList.toggle("kzp-menu-item--active", Number(item.dataset.rate) === extras.rate);
|
|
802
|
+
});
|
|
803
|
+
}
|
|
609
804
|
}
|
|
610
805
|
destroy() {
|
|
806
|
+
document.removeEventListener("click", this.onOutsideClick);
|
|
611
807
|
this.el.remove();
|
|
612
808
|
}
|
|
613
809
|
};
|
|
@@ -620,13 +816,14 @@ var Player = class {
|
|
|
620
816
|
this.container = container;
|
|
621
817
|
this.options = options;
|
|
622
818
|
this.emitter = new Emitter();
|
|
819
|
+
this.captions = null;
|
|
623
820
|
this.furthest = 0;
|
|
624
821
|
this.lastTick = 0;
|
|
625
822
|
this.duration = 0;
|
|
626
823
|
this.playing = false;
|
|
627
824
|
this.ready = false;
|
|
628
825
|
this.disposers = [];
|
|
629
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
826
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
630
827
|
const speeds = (_a = options.speeds) != null ? _a : DEFAULT_SPEEDS;
|
|
631
828
|
this.root = document.createElement("div");
|
|
632
829
|
this.root.className = "kzp" + (options.className ? ` ${options.className}` : "");
|
|
@@ -641,6 +838,10 @@ var Player = class {
|
|
|
641
838
|
this.stage.appendChild(hitLayer);
|
|
642
839
|
this.provider = createProvider(options.source);
|
|
643
840
|
const caps = this.provider.capabilities;
|
|
841
|
+
if ((_b = options.tracks) == null ? void 0 : _b.length) {
|
|
842
|
+
this.captions = new Captions(options.tracks, () => this.syncCaptions());
|
|
843
|
+
this.root.appendChild(this.captions.el);
|
|
844
|
+
}
|
|
644
845
|
this.controls = new Controls(
|
|
645
846
|
{
|
|
646
847
|
onToggle: () => this.toggle(),
|
|
@@ -658,17 +859,22 @@ var Player = class {
|
|
|
658
859
|
this.provider.setRate(r);
|
|
659
860
|
this.render();
|
|
660
861
|
},
|
|
862
|
+
onCaptions: (index) => {
|
|
863
|
+
var _a2;
|
|
864
|
+
return (_a2 = this.captions) == null ? void 0 : _a2.select(index);
|
|
865
|
+
},
|
|
661
866
|
onFullscreen: () => this.toggleFullscreen()
|
|
662
867
|
},
|
|
663
868
|
{
|
|
664
869
|
config: {
|
|
665
870
|
...options.controls,
|
|
666
|
-
seek: ((
|
|
667
|
-
speed: ((
|
|
668
|
-
volume: ((
|
|
871
|
+
seek: ((_d = (_c = options.controls) == null ? void 0 : _c.seek) != null ? _d : true) && caps.seekable,
|
|
872
|
+
speed: ((_f = (_e = options.controls) == null ? void 0 : _e.speed) != null ? _f : true) && caps.rate,
|
|
873
|
+
volume: ((_h = (_g = options.controls) == null ? void 0 : _g.volume) != null ? _h : true) && caps.volume
|
|
669
874
|
},
|
|
670
875
|
speeds,
|
|
671
|
-
lockSeek: !!options.lockSeek
|
|
876
|
+
lockSeek: !!options.lockSeek,
|
|
877
|
+
captionLabels: (_i = this.captions) == null ? void 0 : _i.labels()
|
|
672
878
|
}
|
|
673
879
|
);
|
|
674
880
|
this.root.appendChild(this.controls.el);
|
|
@@ -721,6 +927,7 @@ var Player = class {
|
|
|
721
927
|
this.render();
|
|
722
928
|
}
|
|
723
929
|
onTimeUpdate(current) {
|
|
930
|
+
var _a;
|
|
724
931
|
const advance = current - this.lastTick;
|
|
725
932
|
if (advance > 0 && advance <= NATURAL_ADVANCE_MAX && current > this.furthest) {
|
|
726
933
|
this.furthest = current;
|
|
@@ -728,9 +935,14 @@ var Player = class {
|
|
|
728
935
|
this.provider.seek(this.furthest);
|
|
729
936
|
}
|
|
730
937
|
this.lastTick = current;
|
|
938
|
+
(_a = this.captions) == null ? void 0 : _a.update(current);
|
|
731
939
|
this.emitter.emit("timeupdate", this.snapshot());
|
|
732
940
|
this.render();
|
|
733
941
|
}
|
|
942
|
+
syncCaptions() {
|
|
943
|
+
if (!this.captions) return;
|
|
944
|
+
this.controls.setCaptions(this.captions.getActive(), this.captions.available());
|
|
945
|
+
}
|
|
734
946
|
snapshot() {
|
|
735
947
|
const current = this.provider.getCurrentTime();
|
|
736
948
|
const duration = this.duration || this.provider.getDuration();
|
|
@@ -753,21 +965,32 @@ var Player = class {
|
|
|
753
965
|
}
|
|
754
966
|
}
|
|
755
967
|
// ---- Public API ----
|
|
968
|
+
// play()/pause() record the intent at once instead of waiting for the
|
|
969
|
+
// provider to confirm: YouTube only reports PLAYING after buffering, and
|
|
970
|
+
// until then a second click read "not playing" and called play() again
|
|
971
|
+
// (a no-op) instead of pausing. The provider's play/pause/ended events
|
|
972
|
+
// still correct it, e.g. when the browser blocks playback.
|
|
756
973
|
play() {
|
|
974
|
+
this.playing = true;
|
|
757
975
|
this.provider.play();
|
|
976
|
+
this.render();
|
|
758
977
|
}
|
|
759
978
|
pause() {
|
|
979
|
+
this.playing = false;
|
|
760
980
|
this.provider.pause();
|
|
981
|
+
this.render();
|
|
761
982
|
}
|
|
762
983
|
toggle() {
|
|
763
|
-
if (this.
|
|
764
|
-
else this.
|
|
984
|
+
if (this.playing) this.pause();
|
|
985
|
+
else this.play();
|
|
765
986
|
}
|
|
766
987
|
seek(seconds) {
|
|
988
|
+
var _a;
|
|
767
989
|
if (!this.provider.capabilities.seekable) return;
|
|
768
990
|
const target = this.options.lockSeek && seconds > this.furthest ? this.furthest : Math.max(0, seconds);
|
|
769
991
|
this.provider.seek(target);
|
|
770
992
|
this.lastTick = target;
|
|
993
|
+
(_a = this.captions) == null ? void 0 : _a.update(target);
|
|
771
994
|
this.render();
|
|
772
995
|
}
|
|
773
996
|
setLockSeek(locked) {
|
|
@@ -786,9 +1009,11 @@ var Player = class {
|
|
|
786
1009
|
this.emitter.off(event, cb);
|
|
787
1010
|
}
|
|
788
1011
|
destroy() {
|
|
1012
|
+
var _a;
|
|
789
1013
|
for (const dispose of this.disposers) dispose();
|
|
790
1014
|
this.disposers = [];
|
|
791
1015
|
this.provider.destroy();
|
|
1016
|
+
(_a = this.captions) == null ? void 0 : _a.destroy();
|
|
792
1017
|
this.controls.destroy();
|
|
793
1018
|
this.emitter.clear();
|
|
794
1019
|
this.root.remove();
|
|
@@ -800,6 +1025,6 @@ function createPlayer(container, options) {
|
|
|
800
1025
|
return new Player(container, options);
|
|
801
1026
|
}
|
|
802
1027
|
|
|
803
|
-
export { Player, createPlayer };
|
|
1028
|
+
export { Player, createPlayer, parseVtt };
|
|
804
1029
|
//# sourceMappingURL=index.js.map
|
|
805
1030
|
//# sourceMappingURL=index.js.map
|