@molecule/api-media-streaming-hls 1.0.0 → 1.0.1
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 +268 -0
- package/package.json +5 -4
package/README.md
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
AUTO-GENERATED — DO NOT EDIT THIS FILE.
|
|
3
|
+
Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
|
|
4
|
+
Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
|
|
5
|
+
To change this document, edit the module-level JSDoc in src/index.ts.
|
|
6
|
+
Generated: 2026-08-04T01:48:38.551Z
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
# @molecule/api-media-streaming-hls
|
|
10
|
+
|
|
11
|
+
> **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
|
|
12
|
+
> It is written to be read by coding agents as much as by people, and is generated from this
|
|
13
|
+
> package's source — edit `src/index.ts` JSDoc, not this file.
|
|
14
|
+
|
|
15
|
+
HLS media streaming provider for molecule.dev.
|
|
16
|
+
|
|
17
|
+
Provides HLS (HTTP Live Streaming) support via ffmpeg for media segmentation
|
|
18
|
+
and transcoding, with pure-TypeScript M3U8 playlist generation. Requires
|
|
19
|
+
ffmpeg to be installed on the host system.
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { setProvider, createStream } from '@molecule/api-media-streaming'
|
|
25
|
+
import { provider } from '@molecule/api-media-streaming-hls'
|
|
26
|
+
|
|
27
|
+
setProvider(provider)
|
|
28
|
+
|
|
29
|
+
const manifest = await createStream('/path/to/video.mp4', {
|
|
30
|
+
segmentDuration: 6,
|
|
31
|
+
protocol: 'hls',
|
|
32
|
+
})
|
|
33
|
+
console.log(manifest.manifestUri) // '/hls-…/index.m3u8'
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Type
|
|
37
|
+
|
|
38
|
+
`provider`
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install @molecule/api-media-streaming-hls @molecule/api-media-streaming
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## API
|
|
47
|
+
|
|
48
|
+
### Interfaces
|
|
49
|
+
|
|
50
|
+
#### `HlsConfig`
|
|
51
|
+
|
|
52
|
+
Configuration options for the HLS streaming provider.
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
interface HlsConfig {
|
|
56
|
+
/** Path to the ffmpeg binary. Defaults to `'ffmpeg'` (resolved via PATH). */
|
|
57
|
+
ffmpegPath?: string
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Path to the ffprobe binary. RESERVED for future use — the current
|
|
61
|
+
* provider never invokes ffprobe (segment durations are taken from
|
|
62
|
+
* `segmentDuration`, not probed). Setting this has no effect today.
|
|
63
|
+
*/
|
|
64
|
+
ffprobePath?: string
|
|
65
|
+
|
|
66
|
+
/** Base directory where stream output files are written. Defaults to `os.tmpdir()`. */
|
|
67
|
+
outputBasePath?: string
|
|
68
|
+
|
|
69
|
+
/** Default segment duration in seconds. Defaults to `6`. */
|
|
70
|
+
segmentDuration?: number
|
|
71
|
+
|
|
72
|
+
/** HLS playlist version. Defaults to `3`. */
|
|
73
|
+
hlsVersion?: number
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
#### `M3u8PlaylistOptions`
|
|
78
|
+
|
|
79
|
+
Options for generating an M3U8 media playlist.
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
interface M3u8PlaylistOptions {
|
|
83
|
+
/** HLS playlist version. Defaults to `3`. */
|
|
84
|
+
version?: number
|
|
85
|
+
|
|
86
|
+
/** Target segment duration in seconds. Defaults to the maximum segment duration. */
|
|
87
|
+
targetDuration?: number
|
|
88
|
+
|
|
89
|
+
/** Whether this is a VOD (complete) or live (in-progress) playlist. Defaults to `'vod'`. */
|
|
90
|
+
playlistType?: 'vod' | 'event'
|
|
91
|
+
|
|
92
|
+
/** Media sequence number for the first segment. Defaults to `0`. */
|
|
93
|
+
mediaSequence?: number
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Functions
|
|
98
|
+
|
|
99
|
+
#### `assertSafePathComponent(value, label)`
|
|
100
|
+
|
|
101
|
+
Asserts that a caller-supplied value is a safe single path component.
|
|
102
|
+
|
|
103
|
+
Rejects empty strings, the relative segments `.` and `..`, anything
|
|
104
|
+
containing a path separator or NUL byte, and anything outside the
|
|
105
|
+
`[A-Za-z0-9._-]` allow-list (which also rejects shell metacharacters).
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
function assertSafePathComponent(value: string, label: string): string
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
- `value` — The caller-supplied component (e.g. a stream id or profile name).
|
|
112
|
+
- `label` — Human-readable name of the field, used in the error message.
|
|
113
|
+
|
|
114
|
+
**Returns:** The validated component, unchanged.
|
|
115
|
+
|
|
116
|
+
#### `assertSegmentIndex(index)`
|
|
117
|
+
|
|
118
|
+
Asserts that a caller-supplied segment index is a non-negative integer.
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
function assertSegmentIndex(index: number): number
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
- `index` — The caller-supplied segment index.
|
|
125
|
+
|
|
126
|
+
**Returns:** The validated index, unchanged.
|
|
127
|
+
|
|
128
|
+
#### `createProvider(config)`
|
|
129
|
+
|
|
130
|
+
Creates an HLS streaming provider.
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
function createProvider(config?: HlsConfig): StreamingProvider
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- `config` — Optional provider configuration.
|
|
137
|
+
|
|
138
|
+
**Returns:** A `StreamingProvider` backed by HLS / ffmpeg.
|
|
139
|
+
|
|
140
|
+
#### `generateMasterPlaylist(variants)`
|
|
141
|
+
|
|
142
|
+
Generates an M3U8 master playlist for adaptive bitrate streaming.
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
function generateMasterPlaylist(variants: TranscodeVariant[]): string
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
- `variants` — The transcoded variant streams.
|
|
149
|
+
|
|
150
|
+
**Returns:** The master M3U8 playlist content as a string.
|
|
151
|
+
|
|
152
|
+
#### `generateMediaPlaylist(segments, options)`
|
|
153
|
+
|
|
154
|
+
Generates an M3U8 media playlist from a list of stream segments.
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
function generateMediaPlaylist(segments: StreamSegment[], options?: M3u8PlaylistOptions): string
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
- `segments` — Ordered list of stream segments.
|
|
161
|
+
- `options` — Playlist generation options.
|
|
162
|
+
|
|
163
|
+
**Returns:** The M3U8 playlist content as a string.
|
|
164
|
+
|
|
165
|
+
#### `resolveWithinBase(base, parts)`
|
|
166
|
+
|
|
167
|
+
Resolves `parts` against `base` and asserts the result stays within `base`.
|
|
168
|
+
|
|
169
|
+
Defense-in-depth on top of {@link assertSafePathComponent}: even if a
|
|
170
|
+
component slipped through, the resolved absolute path is rejected unless it
|
|
171
|
+
is `base` itself or a descendant of it.
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
function resolveWithinBase(base: string, parts?: string[]): string
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
- `base` — The intended base directory.
|
|
178
|
+
- `parts` — Path segments to append.
|
|
179
|
+
|
|
180
|
+
**Returns:** The resolved absolute path, guaranteed to be inside `base`.
|
|
181
|
+
|
|
182
|
+
### Constants
|
|
183
|
+
|
|
184
|
+
#### `provider`
|
|
185
|
+
|
|
186
|
+
The provider implementation with default configuration.
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
const provider: StreamingProvider
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Core Interface
|
|
193
|
+
|
|
194
|
+
Implements `@molecule/api-media-streaming` interface.
|
|
195
|
+
|
|
196
|
+
## Bond Wiring
|
|
197
|
+
|
|
198
|
+
Setup function to register this provider with the core interface:
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
import { setProvider } from '@molecule/api-media-streaming'
|
|
202
|
+
import { provider } from '@molecule/api-media-streaming-hls'
|
|
203
|
+
|
|
204
|
+
export function setupMediaStreamingHls(): void {
|
|
205
|
+
setProvider(provider)
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Injection Notes
|
|
210
|
+
|
|
211
|
+
### Requirements
|
|
212
|
+
|
|
213
|
+
Peer dependencies:
|
|
214
|
+
|
|
215
|
+
- `@molecule/api-media-streaming` ^1.0.1
|
|
216
|
+
|
|
217
|
+
### Runtime Dependencies
|
|
218
|
+
|
|
219
|
+
- `@molecule/api-media-streaming`
|
|
220
|
+
|
|
221
|
+
- **Requires the `ffmpeg` binary on the host** (resolved via PATH, or set
|
|
222
|
+
`createProvider({ ffmpegPath })`). A missing binary fails at first
|
|
223
|
+
`createStream()`/`transcode()` call with `spawn ffmpeg ENOENT` — verify
|
|
224
|
+
with `ffmpeg -version` before shipping.
|
|
225
|
+
- **The default output directory is `os.tmpdir()`** — volatile and served by
|
|
226
|
+
nothing. Pass `createProvider({ outputBasePath })` pointing at a directory
|
|
227
|
+
your server exposes (see the core remarks), or serve bytes through
|
|
228
|
+
`getSegment()` / `generateManifest()` endpoints.
|
|
229
|
+
- `createStream()` also caches every segment `Buffer` in an in-process map
|
|
230
|
+
(never evicted) so `getSegment()` is fast; memory grows by the full video
|
|
231
|
+
size per stream. `getSegment()` disk fallback looks ONLY under
|
|
232
|
+
`outputBasePath/<streamId>/` — a per-call `createStream(..., { outputPath })`
|
|
233
|
+
override writes segments where the fallback cannot find them after a
|
|
234
|
+
restart, and `transcode()` ignores `outputPath` entirely (always writes
|
|
235
|
+
under `outputBasePath`).
|
|
236
|
+
- `ffprobePath` in `HlsConfig` is currently RESERVED — no ffprobe call exists
|
|
237
|
+
yet; segment durations come from the requested `segmentDuration`.
|
|
238
|
+
|
|
239
|
+
## E2E Tests
|
|
240
|
+
|
|
241
|
+
Integration checklist — drive the real UI (live preview, no mocks), adapt
|
|
242
|
+
each item to this app's actual upload/player screens, and check every box
|
|
243
|
+
off one by one. A box you can't check is an integration bug to fix — not a
|
|
244
|
+
skip. You can't judge real transcode QUALITY or a live A/V feed in the
|
|
245
|
+
sandbox; verify the pipeline + playback WIRING you own:
|
|
246
|
+
|
|
247
|
+
- [ ] Uploading/ingesting a media asset produces a real PLAYABLE stream: the
|
|
248
|
+
returned `manifestUri` (`.m3u8` for HLS / `.mpd` for DASH) loads in the
|
|
249
|
+
app's video player and actually plays — frames advance and the player
|
|
250
|
+
fetches segments (watch the network panel), never a broken/blank player.
|
|
251
|
+
- [ ] The stream is served from/through the APP'S OWN origin — an
|
|
252
|
+
`outputPath` under a directory the server exposes, or endpoints that return
|
|
253
|
+
`generateManifest(segments)` and stream `getSegment(streamId, index)` bytes.
|
|
254
|
+
The player must NOT hotlink a raw expiring provider URL, and no manifest or
|
|
255
|
+
segment request may 404.
|
|
256
|
+
- [ ] Processing STATE is observable and playback is gated on it: an asset
|
|
257
|
+
moves pending → processing → ready (StreamStatus), the UI reflects that,
|
|
258
|
+
and the player mounts only once status is 'ready' — never a dead player on
|
|
259
|
+
a still-transcoding asset.
|
|
260
|
+
- [ ] If adaptive bitrate is exposed, `transcode()` produced multiple
|
|
261
|
+
renditions: the master manifest (`masterManifestUri`) lists more than one
|
|
262
|
+
`variant` and the player can switch quality across them.
|
|
263
|
+
- [ ] If the app exposes a poster/thumbnail for an asset, it generates and
|
|
264
|
+
renders before playback (no blank tile).
|
|
265
|
+
- [ ] SECURITY — private media is AUTHORIZED on playback: the manifest and
|
|
266
|
+
segment endpoints check the requester (or hand out a signed/expiring URL),
|
|
267
|
+
so a user CANNOT fetch another user's stream by guessing its `id`/URL; and
|
|
268
|
+
provider keys stay server-side (never shipped to the client bundle).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@molecule/api-media-streaming-hls",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "HLS media streaming provider for molecule.dev — ffmpeg-based segmentation, transcoding, and M3U8 playlist generation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
20
|
-
"dist"
|
|
20
|
+
"dist",
|
|
21
|
+
"README.md"
|
|
21
22
|
],
|
|
22
23
|
"keywords": [
|
|
23
24
|
"molecule",
|
|
@@ -30,10 +31,10 @@
|
|
|
30
31
|
],
|
|
31
32
|
"license": "Apache-2.0",
|
|
32
33
|
"peerDependencies": {
|
|
33
|
-
"@molecule/api-media-streaming": "^1.0.
|
|
34
|
+
"@molecule/api-media-streaming": "^1.0.1"
|
|
34
35
|
},
|
|
35
36
|
"devDependencies": {
|
|
36
|
-
"@molecule/api-media-streaming": "1.0.
|
|
37
|
+
"@molecule/api-media-streaming": "1.0.1",
|
|
37
38
|
"@types/node": "26.1.2",
|
|
38
39
|
"typescript": "6.0.3",
|
|
39
40
|
"vitest": "4.1.10"
|