Skip to content

Commit 8a23415

Browse files
committed
feat(player): load chapters from vimeo embed
1 parent c8b871f commit 8a23415

2 files changed

Lines changed: 38 additions & 5 deletions

File tree

packages/vidstack/mangle.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,5 +641,6 @@
641641
"_preferredLang": "Rk",
642642
"_save": "Tk",
643643
"_selectCaptions": "Wk",
644-
"_storage": "Sk"
644+
"_storage": "Sk",
645+
"_onChaptersChange": "Yk"
645646
}

packages/vidstack/src/providers/vimeo/provider.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
type DeferredPromise,
88
} from 'maverick.js/std';
99

10-
import { TimeRange, type MediaSrc } from '../../core';
10+
import { TextTrack, TimeRange, type MediaSrc } from '../../core';
1111
import { QualitySymbol } from '../../core/quality/symbols';
1212
import { ListSymbol } from '../../foundation/list/symbols';
1313
import { RAFLoop } from '../../foundation/observers/raf-loop';
@@ -24,7 +24,7 @@ import {
2424
type VimeoEventPayload,
2525
} from './embed/event';
2626
import type { VimeoMessage } from './embed/message';
27-
import type { VimeoOEmbedData, VimeoQuality, VimeoVideoInfo } from './embed/misc';
27+
import type { VimeoChapter, VimeoQuality, VimeoVideoInfo } from './embed/misc';
2828
import type { VimeoParams } from './embed/params';
2929
import { getVimeoVideoInfo, resolveVimeoVideoId } from './utils';
3030

@@ -67,6 +67,7 @@ export class VimeoProvider
6767
protected _currentSrc: MediaSrc<string> | null = null;
6868
protected _currentCue: VTTCue | null = null;
6969
protected _timeRAF = new RAFLoop(this._onAnimationFrame.bind(this));
70+
private _chaptersTrack: TextTrack | null = null;
7071

7172
protected get _notify() {
7273
return this._ctx.delegate._notify;
@@ -350,8 +351,7 @@ export class VimeoProvider
350351
// We can't control visibility of vimeo captions whilst getting complete info on cues.
351352
// this._remote('getTextTracks');
352353

353-
// TODO: need a test video to implement.
354-
// this._remote('getChapters');
354+
this._remote('getChapters');
355355
})
356356
.catch((e) => {
357357
if (videoId !== this._videoId()) return;
@@ -385,6 +385,7 @@ export class VimeoProvider
385385
// this._onTextTracksChange(data as VimeoTextTrack[], trigger);
386386
// break;
387387
case 'getChapters':
388+
this._onChaptersChange(data as VimeoChapter[]);
388389
break;
389390
case 'getQualities':
390391
this._onQualitiesChange(data as VimeoQuality[], trigger);
@@ -482,6 +483,36 @@ export class VimeoProvider
482483
// track?.addCue(this._currentCue, trigger);
483484
// }
484485

486+
protected _onChaptersChange(chapters: VimeoChapter[]) {
487+
this._removeChapters();
488+
489+
if (!chapters.length) return;
490+
491+
const track = new TextTrack({
492+
kind: 'chapters',
493+
default: true,
494+
}),
495+
{ duration } = this._ctx.$state;
496+
497+
for (let i = 0; i < chapters.length; i++) {
498+
const chapter = chapters[i],
499+
nextChapter = chapters[i + 1];
500+
501+
track.addCue(
502+
new window.VTTCue(chapter.startTime, nextChapter?.startTime ?? duration(), chapter.title),
503+
);
504+
}
505+
506+
this._chaptersTrack = track;
507+
this._ctx.textTracks.add(track);
508+
}
509+
510+
protected _removeChapters() {
511+
if (!this._chaptersTrack) return;
512+
this._ctx.textTracks.remove(this._chaptersTrack);
513+
this._chaptersTrack = null;
514+
}
515+
485516
protected _onQualitiesChange(qualities: VimeoQuality[], trigger: Event) {
486517
this._ctx.qualities[QualitySymbol._enableAuto] = qualities.some((q) => q.id === 'auto')
487518
? () => {
@@ -646,5 +677,6 @@ export class VimeoProvider
646677
this._videoInfoPromise = null;
647678
this._currentCue = null;
648679
this._pro.set(false);
680+
this._removeChapters();
649681
}
650682
}

0 commit comments

Comments
 (0)