@kodezen/player 1.0.1 → 1.0.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/README.md +21 -1
- package/dist/index.cjs +200 -8
- 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 +200 -9
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +204 -11
- 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 +204 -11
- package/dist/react/index.js.map +1 -1
- package/dist/styles.css +72 -0
- 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/README.md
CHANGED
|
@@ -70,7 +70,8 @@ import '@kodezen/player/styles.css';
|
|
|
70
70
|
`createPlayer(container, options)` → instance.
|
|
71
71
|
|
|
72
72
|
**Options:** `source {type,url,id,poster,mime}`, `resumeAt`, `lockSeek`,
|
|
73
|
-
`autoplay`, `muted`, `speeds[]`, `controls{}`, `className
|
|
73
|
+
`autoplay`, `muted`, `speeds[]`, `controls{}`, `className`,
|
|
74
|
+
`tracks[] {src,label,srclang,default}`.
|
|
74
75
|
|
|
75
76
|
**Instance:** `play()`, `pause()`, `toggle()`, `seek(s)`, `getState()`,
|
|
76
77
|
`on(event, cb)`, `off(event, cb)`, `destroy()`.
|
|
@@ -80,6 +81,25 @@ import '@kodezen/player/styles.css';
|
|
|
80
81
|
(`percent` = furthest / duration, so it reflects watched coverage, not the
|
|
81
82
|
scrub position).
|
|
82
83
|
|
|
84
|
+
## Subtitles / captions
|
|
85
|
+
|
|
86
|
+
Pass WebVTT files as `tracks`. The player fetches and renders them itself in
|
|
87
|
+
an overlay, so the same `.vtt` works for `html5`, `youtube` and `vimeo`
|
|
88
|
+
(YouTube/Vimeo iframes can't load an external caption file). A CC button
|
|
89
|
+
toggles a single track, or opens a menu when there are several. A track with
|
|
90
|
+
`default: true` is shown as soon as it loads; otherwise captions start off.
|
|
91
|
+
|
|
92
|
+
```js
|
|
93
|
+
createPlayer(el, {
|
|
94
|
+
source: { type: 'youtube', id: 'dQw4w9WgXcQ' },
|
|
95
|
+
tracks: [{ src: '/uploads/lesson-1.vtt', label: 'English', srclang: 'en', default: true }],
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The file must be same-origin or served with CORS. Cue settings
|
|
100
|
+
(position/alignment) and styling blocks are ignored — cues render as plain
|
|
101
|
+
centred text. `parseVtt(text)` is exported if you need the cues yourself.
|
|
102
|
+
|
|
83
103
|
## Host integration notes
|
|
84
104
|
|
|
85
105
|
- **Resume** = pass `resumeAt`; player seeks on `ready` unless within 2s of end.
|
package/dist/index.cjs
CHANGED
|
@@ -447,13 +447,124 @@ function createProvider(source) {
|
|
|
447
447
|
}
|
|
448
448
|
}
|
|
449
449
|
|
|
450
|
+
// src/core/Captions.ts
|
|
451
|
+
var TIMING = /^\s*((?:\d+:)?\d{1,2}:\d{2}[.,]\d{1,3})\s+-->\s+((?:\d+:)?\d{1,2}:\d{2}[.,]\d{1,3})/;
|
|
452
|
+
var ENTITIES = {
|
|
453
|
+
amp: "&",
|
|
454
|
+
lt: "<",
|
|
455
|
+
gt: ">",
|
|
456
|
+
quot: '"',
|
|
457
|
+
apos: "'",
|
|
458
|
+
nbsp: "\xA0",
|
|
459
|
+
lrm: "\u200E",
|
|
460
|
+
rlm: "\u200F"
|
|
461
|
+
};
|
|
462
|
+
function toSeconds(stamp) {
|
|
463
|
+
const [clock = "", fraction = "0"] = stamp.replace(",", ".").split(".");
|
|
464
|
+
const seconds = clock.split(":").reduce((total, part) => total * 60 + Number(part), 0);
|
|
465
|
+
return seconds + Number(`0.${fraction}`);
|
|
466
|
+
}
|
|
467
|
+
function plainText(text) {
|
|
468
|
+
return text.replace(/<[^>]*>/g, "").replace(/&(amp|lt|gt|quot|apos|nbsp|lrm|rlm);/g, (_, name) => {
|
|
469
|
+
var _a;
|
|
470
|
+
return (_a = ENTITIES[name]) != null ? _a : "";
|
|
471
|
+
}).replace(/&#(\d+);/g, (_, code) => String.fromCodePoint(Number(code)));
|
|
472
|
+
}
|
|
473
|
+
function parseVtt(input) {
|
|
474
|
+
var _a;
|
|
475
|
+
const cues = [];
|
|
476
|
+
const blocks = input.replace(/^/, "").replace(/\r\n?/g, "\n").split(/\n{2,}/);
|
|
477
|
+
for (const block of blocks) {
|
|
478
|
+
const lines = block.split("\n");
|
|
479
|
+
const timingAt = lines.findIndex((line) => line.includes("-->"));
|
|
480
|
+
const timing = TIMING.exec((_a = lines[timingAt]) != null ? _a : "");
|
|
481
|
+
if (!(timing == null ? void 0 : timing[1]) || !timing[2]) continue;
|
|
482
|
+
const text = plainText(lines.slice(timingAt + 1).join("\n")).trim();
|
|
483
|
+
if (!text) continue;
|
|
484
|
+
cues.push({ start: toSeconds(timing[1]), end: toSeconds(timing[2]), text });
|
|
485
|
+
}
|
|
486
|
+
return cues.sort((a, b) => a.start - b.start);
|
|
487
|
+
}
|
|
488
|
+
var Captions = class {
|
|
489
|
+
/** `onChange` fires when the active track or track availability changes. */
|
|
490
|
+
constructor(tracks, onChange) {
|
|
491
|
+
this.onChange = onChange;
|
|
492
|
+
this.active = -1;
|
|
493
|
+
this.time = 0;
|
|
494
|
+
this.abort = new AbortController();
|
|
495
|
+
this.el = document.createElement("div");
|
|
496
|
+
this.el.className = "kzp-captions";
|
|
497
|
+
this.el.setAttribute("aria-live", "off");
|
|
498
|
+
this.text = document.createElement("span");
|
|
499
|
+
this.text.className = "kzp-captions-text";
|
|
500
|
+
this.text.hidden = true;
|
|
501
|
+
this.el.appendChild(this.text);
|
|
502
|
+
this.tracks = tracks.map((info) => ({ info, cues: null, failed: false }));
|
|
503
|
+
const preferred = tracks.findIndex((t) => t.default);
|
|
504
|
+
this.tracks.forEach((track, index) => {
|
|
505
|
+
void this.load(track).then(() => {
|
|
506
|
+
if (index === preferred && this.active === -1 && track.cues) this.select(index);
|
|
507
|
+
else this.onChange();
|
|
508
|
+
});
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
async load(track) {
|
|
512
|
+
try {
|
|
513
|
+
const res = await fetch(track.info.src, { signal: this.abort.signal, credentials: "same-origin" });
|
|
514
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
515
|
+
track.cues = parseVtt(await res.text());
|
|
516
|
+
} catch (err) {
|
|
517
|
+
if (this.abort.signal.aborted) return;
|
|
518
|
+
track.failed = true;
|
|
519
|
+
console.warn(`@kodezen/player: could not load captions from ${track.info.src}`, err);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
/** Labels for the menu, one per track (falls back to the language, then a number). */
|
|
523
|
+
labels() {
|
|
524
|
+
return this.tracks.map((t, i) => t.info.label || t.info.srclang || `Track ${i + 1}`);
|
|
525
|
+
}
|
|
526
|
+
/** Whether each track loaded (a failed track is hidden from the controls). */
|
|
527
|
+
available() {
|
|
528
|
+
return this.tracks.map((t) => !t.failed);
|
|
529
|
+
}
|
|
530
|
+
getActive() {
|
|
531
|
+
return this.active;
|
|
532
|
+
}
|
|
533
|
+
/** Show track `index`, or turn captions off with -1. */
|
|
534
|
+
select(index) {
|
|
535
|
+
var _a;
|
|
536
|
+
const track = this.tracks[index];
|
|
537
|
+
this.active = track && !track.failed ? index : -1;
|
|
538
|
+
this.el.lang = (_a = track == null ? void 0 : track.info.srclang) != null ? _a : "";
|
|
539
|
+
this.render();
|
|
540
|
+
this.onChange();
|
|
541
|
+
}
|
|
542
|
+
/** Called with the playhead position on every tick and after a seek. */
|
|
543
|
+
update(time) {
|
|
544
|
+
this.time = time;
|
|
545
|
+
this.render();
|
|
546
|
+
}
|
|
547
|
+
render() {
|
|
548
|
+
var _a, _b;
|
|
549
|
+
const cues = (_b = (_a = this.tracks[this.active]) == null ? void 0 : _a.cues) != null ? _b : [];
|
|
550
|
+
const text = cues.filter((cue) => this.time >= cue.start && this.time < cue.end).map((cue) => cue.text).join("\n");
|
|
551
|
+
if (text !== this.text.textContent) this.text.textContent = text;
|
|
552
|
+
this.text.hidden = !text;
|
|
553
|
+
}
|
|
554
|
+
destroy() {
|
|
555
|
+
this.abort.abort();
|
|
556
|
+
this.el.remove();
|
|
557
|
+
}
|
|
558
|
+
};
|
|
559
|
+
|
|
450
560
|
// src/core/Controls.ts
|
|
451
561
|
var ICONS = {
|
|
452
562
|
play: '<path d="M8 5v14l11-7z"/>',
|
|
453
563
|
pause: '<path d="M6 5h4v14H6zM14 5h4v14h-4z"/>',
|
|
454
564
|
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"/>',
|
|
455
565
|
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"/>',
|
|
456
|
-
full: '<path d="M4 4h6v2H6v4H4V4zm10 0h6v6h-2V6h-4V4zM4 14h2v4h4v2H4v-6zm14 0h2v6h-6v-2h4v-4z"/>'
|
|
566
|
+
full: '<path d="M4 4h6v2H6v4H4V4zm10 0h6v6h-2V6h-4V4zM4 14h2v4h4v2H4v-6zm14 0h2v6h-6v-2h4v-4z"/>',
|
|
567
|
+
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"/>'
|
|
457
568
|
};
|
|
458
569
|
function icon(paths) {
|
|
459
570
|
return `<svg viewBox="0 0 24 24" aria-hidden="true">${paths}</svg>`;
|
|
@@ -473,20 +584,23 @@ var DEFAULT_CONFIG = {
|
|
|
473
584
|
time: true,
|
|
474
585
|
volume: true,
|
|
475
586
|
speed: true,
|
|
587
|
+
captions: true,
|
|
476
588
|
fullscreen: true
|
|
477
589
|
};
|
|
478
590
|
var Controls = class {
|
|
479
591
|
constructor(cb, opts) {
|
|
480
592
|
this.cb = cb;
|
|
593
|
+
this.ccActive = -1;
|
|
481
594
|
this.scrubbing = false;
|
|
482
595
|
this.seekableMax = Infinity;
|
|
596
|
+
var _a;
|
|
483
597
|
this.config = { ...DEFAULT_CONFIG, ...opts.config };
|
|
484
598
|
this.lockSeek = opts.lockSeek;
|
|
485
599
|
this.el = document.createElement("div");
|
|
486
600
|
this.el.className = "kzp-controls";
|
|
487
|
-
this.build(opts.speeds);
|
|
601
|
+
this.build(opts.speeds, (_a = opts.captionLabels) != null ? _a : []);
|
|
488
602
|
}
|
|
489
|
-
build(speeds) {
|
|
603
|
+
build(speeds, captionLabels) {
|
|
490
604
|
if (this.config.playPause) {
|
|
491
605
|
this.playBtn = this.button("kzp-play", "Play", ICONS.play);
|
|
492
606
|
this.playBtn.addEventListener("click", () => this.cb.onToggle());
|
|
@@ -563,16 +677,72 @@ var Controls = class {
|
|
|
563
677
|
}
|
|
564
678
|
this.speedBtn.addEventListener("click", () => {
|
|
565
679
|
this.speedMenu.hidden = !this.speedMenu.hidden;
|
|
680
|
+
if (this.ccMenu) this.ccMenu.hidden = true;
|
|
566
681
|
});
|
|
567
682
|
wrap.append(this.speedBtn, this.speedMenu);
|
|
568
683
|
this.el.appendChild(wrap);
|
|
569
684
|
}
|
|
685
|
+
if (this.config.captions && captionLabels.length) {
|
|
686
|
+
this.buildCaptions(captionLabels);
|
|
687
|
+
}
|
|
570
688
|
if (this.config.fullscreen) {
|
|
571
689
|
const btn = this.button("kzp-full", "Fullscreen", ICONS.full);
|
|
572
690
|
btn.addEventListener("click", () => this.cb.onFullscreen());
|
|
573
691
|
this.el.appendChild(btn);
|
|
574
692
|
}
|
|
575
693
|
}
|
|
694
|
+
/**
|
|
695
|
+
* One track: the CC button toggles it. Several: it opens a menu (Off + each
|
|
696
|
+
* track), styled like the speed menu. Sits left of the speed control.
|
|
697
|
+
*/
|
|
698
|
+
buildCaptions(labels) {
|
|
699
|
+
const wrap = document.createElement("div");
|
|
700
|
+
wrap.className = "kzp-cc";
|
|
701
|
+
this.ccBtn = this.button("kzp-cc-btn", "Subtitles/closed captions", ICONS.captions);
|
|
702
|
+
this.ccBtn.setAttribute("aria-pressed", "false");
|
|
703
|
+
wrap.appendChild(this.ccBtn);
|
|
704
|
+
if (labels.length === 1) {
|
|
705
|
+
this.ccBtn.addEventListener("click", () => this.cb.onCaptions(this.ccActive === -1 ? 0 : -1));
|
|
706
|
+
} else {
|
|
707
|
+
this.ccMenu = document.createElement("div");
|
|
708
|
+
this.ccMenu.className = "kzp-speed-menu kzp-cc-menu";
|
|
709
|
+
this.ccMenu.hidden = true;
|
|
710
|
+
const items = [{ index: -1, label: "Off" }, ...labels.map((label, index) => ({ index, label }))];
|
|
711
|
+
for (const { index, label } of items) {
|
|
712
|
+
const item = document.createElement("button");
|
|
713
|
+
item.type = "button";
|
|
714
|
+
item.textContent = label;
|
|
715
|
+
item.dataset.track = String(index);
|
|
716
|
+
item.addEventListener("click", () => {
|
|
717
|
+
this.cb.onCaptions(index);
|
|
718
|
+
this.ccMenu.hidden = true;
|
|
719
|
+
});
|
|
720
|
+
this.ccMenu.appendChild(item);
|
|
721
|
+
}
|
|
722
|
+
this.ccBtn.addEventListener("click", () => {
|
|
723
|
+
this.ccMenu.hidden = !this.ccMenu.hidden;
|
|
724
|
+
if (this.speedMenu) this.speedMenu.hidden = true;
|
|
725
|
+
});
|
|
726
|
+
wrap.appendChild(this.ccMenu);
|
|
727
|
+
}
|
|
728
|
+
this.ccWrap = wrap;
|
|
729
|
+
const speed = this.el.querySelector(".kzp-speed");
|
|
730
|
+
this.el.insertBefore(wrap, speed);
|
|
731
|
+
}
|
|
732
|
+
/** Reflect the active caption track, and hide tracks (or the whole control) that failed to load. */
|
|
733
|
+
setCaptions(active, available) {
|
|
734
|
+
var _a;
|
|
735
|
+
this.ccActive = active;
|
|
736
|
+
if (!this.ccBtn || !this.ccWrap) return;
|
|
737
|
+
this.ccWrap.hidden = !available.some(Boolean);
|
|
738
|
+
this.ccBtn.classList.toggle("kzp-cc-btn--on", active !== -1);
|
|
739
|
+
this.ccBtn.setAttribute("aria-pressed", String(active !== -1));
|
|
740
|
+
(_a = this.ccMenu) == null ? void 0 : _a.querySelectorAll("button").forEach((item) => {
|
|
741
|
+
const index = Number(item.dataset.track);
|
|
742
|
+
item.hidden = index !== -1 && !available[index];
|
|
743
|
+
item.classList.toggle("kzp-menu-item--active", index === active);
|
|
744
|
+
});
|
|
745
|
+
}
|
|
576
746
|
button(cls, label, svg) {
|
|
577
747
|
const b = document.createElement("button");
|
|
578
748
|
b.type = "button";
|
|
@@ -622,16 +792,18 @@ var Player = class {
|
|
|
622
792
|
this.container = container;
|
|
623
793
|
this.options = options;
|
|
624
794
|
this.emitter = new Emitter();
|
|
795
|
+
this.captions = null;
|
|
625
796
|
this.furthest = 0;
|
|
626
797
|
this.lastTick = 0;
|
|
627
798
|
this.duration = 0;
|
|
628
799
|
this.playing = false;
|
|
629
800
|
this.ready = false;
|
|
630
801
|
this.disposers = [];
|
|
631
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
802
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
632
803
|
const speeds = (_a = options.speeds) != null ? _a : DEFAULT_SPEEDS;
|
|
633
804
|
this.root = document.createElement("div");
|
|
634
805
|
this.root.className = "kzp" + (options.className ? ` ${options.className}` : "");
|
|
806
|
+
this.root.classList.add(`kzp--${options.source.type}`);
|
|
635
807
|
if (options.lockSeek) this.root.classList.add("kzp--locked");
|
|
636
808
|
this.stage = document.createElement("div");
|
|
637
809
|
this.stage.className = "kzp-stage";
|
|
@@ -642,6 +814,10 @@ var Player = class {
|
|
|
642
814
|
this.stage.appendChild(hitLayer);
|
|
643
815
|
this.provider = createProvider(options.source);
|
|
644
816
|
const caps = this.provider.capabilities;
|
|
817
|
+
if ((_b = options.tracks) == null ? void 0 : _b.length) {
|
|
818
|
+
this.captions = new Captions(options.tracks, () => this.syncCaptions());
|
|
819
|
+
this.root.appendChild(this.captions.el);
|
|
820
|
+
}
|
|
645
821
|
this.controls = new Controls(
|
|
646
822
|
{
|
|
647
823
|
onToggle: () => this.toggle(),
|
|
@@ -659,17 +835,22 @@ var Player = class {
|
|
|
659
835
|
this.provider.setRate(r);
|
|
660
836
|
this.render();
|
|
661
837
|
},
|
|
838
|
+
onCaptions: (index) => {
|
|
839
|
+
var _a2;
|
|
840
|
+
return (_a2 = this.captions) == null ? void 0 : _a2.select(index);
|
|
841
|
+
},
|
|
662
842
|
onFullscreen: () => this.toggleFullscreen()
|
|
663
843
|
},
|
|
664
844
|
{
|
|
665
845
|
config: {
|
|
666
846
|
...options.controls,
|
|
667
|
-
seek: ((
|
|
668
|
-
speed: ((
|
|
669
|
-
volume: ((
|
|
847
|
+
seek: ((_d = (_c = options.controls) == null ? void 0 : _c.seek) != null ? _d : true) && caps.seekable,
|
|
848
|
+
speed: ((_f = (_e = options.controls) == null ? void 0 : _e.speed) != null ? _f : true) && caps.rate,
|
|
849
|
+
volume: ((_h = (_g = options.controls) == null ? void 0 : _g.volume) != null ? _h : true) && caps.volume
|
|
670
850
|
},
|
|
671
851
|
speeds,
|
|
672
|
-
lockSeek: !!options.lockSeek
|
|
852
|
+
lockSeek: !!options.lockSeek,
|
|
853
|
+
captionLabels: (_i = this.captions) == null ? void 0 : _i.labels()
|
|
673
854
|
}
|
|
674
855
|
);
|
|
675
856
|
this.root.appendChild(this.controls.el);
|
|
@@ -722,6 +903,7 @@ var Player = class {
|
|
|
722
903
|
this.render();
|
|
723
904
|
}
|
|
724
905
|
onTimeUpdate(current) {
|
|
906
|
+
var _a;
|
|
725
907
|
const advance = current - this.lastTick;
|
|
726
908
|
if (advance > 0 && advance <= NATURAL_ADVANCE_MAX && current > this.furthest) {
|
|
727
909
|
this.furthest = current;
|
|
@@ -729,9 +911,14 @@ var Player = class {
|
|
|
729
911
|
this.provider.seek(this.furthest);
|
|
730
912
|
}
|
|
731
913
|
this.lastTick = current;
|
|
914
|
+
(_a = this.captions) == null ? void 0 : _a.update(current);
|
|
732
915
|
this.emitter.emit("timeupdate", this.snapshot());
|
|
733
916
|
this.render();
|
|
734
917
|
}
|
|
918
|
+
syncCaptions() {
|
|
919
|
+
if (!this.captions) return;
|
|
920
|
+
this.controls.setCaptions(this.captions.getActive(), this.captions.available());
|
|
921
|
+
}
|
|
735
922
|
snapshot() {
|
|
736
923
|
const current = this.provider.getCurrentTime();
|
|
737
924
|
const duration = this.duration || this.provider.getDuration();
|
|
@@ -765,10 +952,12 @@ var Player = class {
|
|
|
765
952
|
else this.provider.play();
|
|
766
953
|
}
|
|
767
954
|
seek(seconds) {
|
|
955
|
+
var _a;
|
|
768
956
|
if (!this.provider.capabilities.seekable) return;
|
|
769
957
|
const target = this.options.lockSeek && seconds > this.furthest ? this.furthest : Math.max(0, seconds);
|
|
770
958
|
this.provider.seek(target);
|
|
771
959
|
this.lastTick = target;
|
|
960
|
+
(_a = this.captions) == null ? void 0 : _a.update(target);
|
|
772
961
|
this.render();
|
|
773
962
|
}
|
|
774
963
|
setLockSeek(locked) {
|
|
@@ -787,9 +976,11 @@ var Player = class {
|
|
|
787
976
|
this.emitter.off(event, cb);
|
|
788
977
|
}
|
|
789
978
|
destroy() {
|
|
979
|
+
var _a;
|
|
790
980
|
for (const dispose of this.disposers) dispose();
|
|
791
981
|
this.disposers = [];
|
|
792
982
|
this.provider.destroy();
|
|
983
|
+
(_a = this.captions) == null ? void 0 : _a.destroy();
|
|
793
984
|
this.controls.destroy();
|
|
794
985
|
this.emitter.clear();
|
|
795
986
|
this.root.remove();
|
|
@@ -803,5 +994,6 @@ function createPlayer(container, options) {
|
|
|
803
994
|
|
|
804
995
|
exports.Player = Player;
|
|
805
996
|
exports.createPlayer = createPlayer;
|
|
997
|
+
exports.parseVtt = parseVtt;
|
|
806
998
|
//# sourceMappingURL=index.cjs.map
|
|
807
999
|
//# sourceMappingURL=index.cjs.map
|