videojs-rewind 0.1.0 → 0.2.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 +79 -10
- package/dist/dom.d.ts +11 -0
- package/dist/index.js +295 -56382
- package/dist/plugin.d.ts +32 -13
- package/dist/schema.d.ts +49 -3
- package/dist/types.d.ts +5 -11
- package/dist/utils.d.ts +9 -0
- package/dist/videojs-rewind.css +6 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# videojs-rewind
|
|
2
2
|
|
|
3
|
-
A Live DVR Rewind Plugin for video.js — full-stream seek bar, rewind-to-VOD, quality enforcement, and storyboard thumbnails for live HLS playback.
|
|
3
|
+
A Live DVR Rewind Plugin for video.js — full-stream seek bar, rewind-to-VOD, quality enforcement, and storyboard thumbnails for **both live and VOD** HLS playback.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **Custom Seek Bar** — Full-width seek bar that replaces the native `ProgressControl`. Shows stream position relative to the full stream duration (not just the DVR window).
|
|
7
|
+
- **Custom Seek Bar** — Full-width seek bar that replaces the native `ProgressControl`. Shows stream position relative to the full stream duration (not just the DVR window). Works on both live and finite VOD sources.
|
|
8
8
|
- **Live/VOD Timer** — Displays "Live" when at the live edge, or `currentTime / totalTime` (e.g., `1:23:45 / 5:15:00`) when seeking through VOD content.
|
|
9
9
|
- **Rewind-to-VOD** — When the user seeks behind the DVR window, automatically fetches a VOD HLS URL and swaps the source. Provides a "Go Live" button to return to the live stream.
|
|
10
10
|
- **Quality Enforcement** — Locks the player to a user-preferred quality level (e.g., 1080p) across source swaps, with an ABR suppression window to avoid thrashing during initial ramp-up.
|
|
@@ -13,7 +13,7 @@ A Live DVR Rewind Plugin for video.js — full-stream seek bar, rewind-to-VOD, q
|
|
|
13
13
|
## Installation
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
npm install
|
|
16
|
+
npm install videojs-rewind
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
## Usage
|
|
@@ -22,7 +22,7 @@ npm install @ashleyjackson/videojs-rewind
|
|
|
22
22
|
import videojs from 'video.js';
|
|
23
23
|
import '@videojs/http-streaming';
|
|
24
24
|
import 'videojs-contrib-quality-levels';
|
|
25
|
-
import '
|
|
25
|
+
import 'videojs-rewind';
|
|
26
26
|
|
|
27
27
|
const player = videojs('my-player', {
|
|
28
28
|
controls: true,
|
|
@@ -36,24 +36,85 @@ const player = videojs('my-player', {
|
|
|
36
36
|
},
|
|
37
37
|
plugins: {
|
|
38
38
|
rewind: {
|
|
39
|
+
channelName: 'ashley', // host-supplied, generic (not Twitch-specific)
|
|
39
40
|
preferredQuality: 1080,
|
|
40
41
|
enableRewindToVod: true,
|
|
41
|
-
resolveVodUrl: async (channel, seekTime) => {
|
|
42
|
-
|
|
42
|
+
resolveVodUrl: async (channel, seekTime, context) => {
|
|
43
|
+
// context.currentVodId is set when the host already knows the VOD.
|
|
44
|
+
// context.liveTotalElapsed is set when the seek originated from a live
|
|
45
|
+
// source (seconds the broadcast has been live), so the host can pick the
|
|
46
|
+
// VOD matching the current broadcast without re-deriving it.
|
|
47
|
+
const vodId = context?.currentVodId ?? await fetchVodForChannel(channel, seekTime, context?.liveTotalElapsed);
|
|
43
48
|
const hlsUrl = await getSignedVodUrl(vodId);
|
|
44
49
|
return { vodId, hlsUrl };
|
|
45
50
|
},
|
|
51
|
+
resolveLiveUrl: async (channel) => {
|
|
52
|
+
// Required when enableRewindToVod is true; used to return to live after VOD playback
|
|
53
|
+
const res = await fetch(`/api/live/${channel}`);
|
|
54
|
+
const { hlsUrl } = await res.json();
|
|
55
|
+
return hlsUrl;
|
|
56
|
+
},
|
|
57
|
+
// Quality persistence: delegate to host storage instead of the plugin's
|
|
58
|
+
// own localStorage key. When set, persistQuality is ignored.
|
|
59
|
+
loadQuality: () => getSync('vjsQuality'),
|
|
60
|
+
saveQuality: (q) => setSync('vjsQuality', q),
|
|
46
61
|
storyboard: {
|
|
62
|
+
// fetchInfo returns the RAW provider response (single entry, array, or null).
|
|
63
|
+
// The plugin validates it with a Zod schema and selects an entry.
|
|
47
64
|
fetchInfo: async (vodId, cdnBaseUrl) => {
|
|
48
65
|
const res = await fetch(`${cdnBaseUrl}/../storyboards/${vodId}-info.json`);
|
|
49
66
|
return res.json();
|
|
50
|
-
}
|
|
67
|
+
},
|
|
68
|
+
// Resolve a sprite image ref (filename or URL) to a fully-qualified URL.
|
|
69
|
+
// Optional — if omitted, images entries are treated as already-qualified.
|
|
70
|
+
resolveImageUrl: (ref, _entry, cdnBaseUrl) => `${cdnBaseUrl}storyboards/${ref}`,
|
|
71
|
+
preferredQuality: 'high' // pick this entry when info is an array
|
|
51
72
|
}
|
|
52
73
|
}
|
|
53
74
|
}
|
|
54
75
|
});
|
|
55
76
|
```
|
|
56
77
|
|
|
78
|
+
> **Live and VOD sources.** The plugin auto-detects the source type on `loadedmetadata`: a non-finite duration is treated as a finite VOD (full seek bar over `[0, duration]`, "Go Live" hidden, no rewind-to-VOD swaps), while a live stream uses the DVR window and live edge. No configuration is needed to switch between them — just call `player.src()` with the new HLS URL.
|
|
79
|
+
|
|
80
|
+
## Programmatic API
|
|
81
|
+
|
|
82
|
+
The plugin is registered as a video.js advanced (class-based) plugin. After construction, obtain the instance via the player's plugin accessor and cast it to the exported class to reach the typed methods:
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
import videojs from 'video.js';
|
|
86
|
+
import RewindPlugin from 'videojs-rewind';
|
|
87
|
+
|
|
88
|
+
const player = videojs('my-player', { /* ... */ });
|
|
89
|
+
// plugin is constructed via the `plugins.rewind` config (see Usage) or:
|
|
90
|
+
player.rewind();
|
|
91
|
+
|
|
92
|
+
const plugin = player.rewind() as RewindPlugin;
|
|
93
|
+
plugin.seek(120); // seek to 120s (clamped, runs rewind-to-VOD detection)
|
|
94
|
+
plugin.goLive(); // swap back to the live source
|
|
95
|
+
plugin.setQuality(1080);
|
|
96
|
+
plugin.getQuality();
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
- `seek(time)` — clamps to `[0, maxTime]`, runs rewind-to-VOD detection, and seeks in-place when no source swap is needed. No-op after `dispose()`.
|
|
100
|
+
- `goLive()` — returns to the live source via `resolveLiveUrl` / `liveUrl`. No-op after `dispose()`.
|
|
101
|
+
|
|
102
|
+
### `rewindmodechange` event
|
|
103
|
+
|
|
104
|
+
When the plugin swaps the source between live and VOD (in either direction), it triggers a `rewindmodechange` event on the player **after** the new source's `loadedmetadata` fires, so the host can react once playback is actually ready. The event is not fired on an aborted transition (e.g., resolver returned `null`).
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
player.on('rewindmodechange', (e) => {
|
|
108
|
+
// e.mode === 'vod' | 'live'
|
|
109
|
+
// e.vodId === '<id>' (present only when mode === 'vod')
|
|
110
|
+
if (e.mode === 'vod') {
|
|
111
|
+
updateUrlBar(`/videos/${e.vodId}`);
|
|
112
|
+
} else {
|
|
113
|
+
updateUrlBar(`/${channel}`);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
57
118
|
## Options
|
|
58
119
|
|
|
59
120
|
| Option | Type | Default | Description |
|
|
@@ -61,13 +122,21 @@ const player = videojs('my-player', {
|
|
|
61
122
|
| `customSeekBar` | `boolean` | `true` | Enable custom seek bar (replaces native ProgressControl) |
|
|
62
123
|
| `showTotalTime` | `boolean` | `true` | Show total stream time in timer display |
|
|
63
124
|
| `enableRewindToVod` | `boolean` | `true` | Enable rewind-to-VOD flow |
|
|
64
|
-
| `
|
|
125
|
+
| `channelName` | `string` | `undefined` | Host-supplied channel identifier, passed to `resolveVodUrl` / `resolveLiveUrl`. Required when using rewind-to-VOD with a resolver. |
|
|
126
|
+
| `liveUrl` | `string` | `undefined` | Static live HLS URL used by "Go Live". Takes precedence over `resolveLiveUrl`. |
|
|
127
|
+
| `cdnBaseUrl` | `string` | `undefined` | Explicit CDN base URL for storyboard `fetchInfo`. Overrides automatic capture from VHS playlist responses. |
|
|
128
|
+
| `resolveVodUrl` | `function` | `null` | `(channelName, seekTime, context?) => Promise<{ vodId, hlsUrl } \| null>` — resolve a VOD URL when seeking behind the DVR window. `context.currentVodId` is set when the host already knows the VOD; `context.liveTotalElapsed` is set (seconds) when the seek originated from a live source. |
|
|
129
|
+
| `resolveLiveUrl` | `function` | `null` | `(channelName) => Promise<string \| null>` — resolve the live HLS URL for "Go Live". Required when `enableRewindToVod` is `true` and `liveUrl` is not set. |
|
|
65
130
|
| `preferredQuality` | `number \| "auto"` | `"auto"` | Preferred quality height (e.g., `1080`) or `"auto"` for ABR |
|
|
66
|
-
| `persistQuality` | `boolean` | `true` | Persist quality preference to localStorage |
|
|
131
|
+
| `persistQuality` | `boolean` | `true` | Persist quality preference to localStorage (ignored when `loadQuality`/`saveQuality` are set) |
|
|
67
132
|
| `storageKeyPrefix` | `string` | `"videojs-rewind:"` | Prefix for localStorage keys |
|
|
68
|
-
| `
|
|
133
|
+
| `loadQuality` | `function` | `null` | `() => number \| "auto" \| null` — host-supplied quality reader. Takes precedence over localStorage. |
|
|
134
|
+
| `saveQuality` | `function` | `null` | `(quality) => void` — host-supplied quality writer. Takes precedence over localStorage. |
|
|
135
|
+
| `storyboard` | `object` | `null` | Storyboard configuration (`fetchInfo`, `resolveImageUrl`, `preferredQuality`, `previewWidth`, `previewHeight`) |
|
|
69
136
|
| `dvrWindowThreshold` | `number` | `120` | Seconds before rewind-to-VOD triggers |
|
|
70
137
|
| `showToasts` | `boolean` | `true` | Show toast notifications |
|
|
138
|
+
| `enableKeyboardSeek` | `boolean` | `true` | Wire the plugin's `ArrowLeft`/`ArrowRight` keyboard seek handler. Disable when the host supplies its own keyboard shortcuts to avoid a double-seek. Keyboard seeks route through `seek()` (so they trigger rewind-to-VOD detection). |
|
|
139
|
+
| `keyboardSeekStep` | `number` | `5` | Seconds sought per `ArrowLeft`/`ArrowRight` press (when `enableKeyboardSeek` is `true`). |
|
|
71
140
|
|
|
72
141
|
## Development
|
|
73
142
|
|
package/dist/dom.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM construction helpers for videojs-rewind.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Create a DOM element with attributes and optional text content.
|
|
6
|
+
*
|
|
7
|
+
* @param tag - HTML tag name (e.g. 'div', 'span', 'button')
|
|
8
|
+
* @param attrs - Attributes to set on the element
|
|
9
|
+
* @param text - Optional text content
|
|
10
|
+
*/
|
|
11
|
+
export declare function createEl<K extends keyof HTMLElementTagNameMap>(tag: K, attrs: Record<string, string>, text?: string): HTMLElementTagNameMap[K];
|