hls-streamer 4.0.2 → 4.5.0
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 +218 -17
- package/dist/Interfaces/HlsStreamer.d.ts +12 -2
- package/dist/Interfaces/HlsStreamer.d.ts.map +1 -1
- package/dist/Interfaces/IStorageProvider.d.ts +9 -0
- package/dist/Interfaces/IStorageProvider.d.ts.map +1 -0
- package/dist/Interfaces/IStorageProvider.js +2 -0
- package/dist/Interfaces/IStorageProvider.js.map +1 -0
- package/dist/Providers/LocalFileProvider.d.ts +12 -0
- package/dist/Providers/LocalFileProvider.d.ts.map +1 -0
- package/dist/Providers/LocalFileProvider.js +53 -0
- package/dist/Providers/LocalFileProvider.js.map +1 -0
- package/dist/Providers/S3Provider.d.ts +26 -0
- package/dist/Providers/S3Provider.d.ts.map +1 -0
- package/dist/Providers/S3Provider.js +117 -0
- package/dist/Providers/S3Provider.js.map +1 -0
- package/dist/Providers/index.d.ts +4 -0
- package/dist/Providers/index.d.ts.map +1 -0
- package/dist/Providers/index.js +3 -0
- package/dist/Providers/index.js.map +1 -0
- package/dist/cjs/Interfaces/HlsStreamer.d.ts +12 -2
- package/dist/cjs/Interfaces/HlsStreamer.d.ts.map +1 -1
- package/dist/cjs/Interfaces/IStorageProvider.d.ts +9 -0
- package/dist/cjs/Interfaces/IStorageProvider.d.ts.map +1 -0
- package/dist/cjs/Interfaces/IStorageProvider.js +3 -0
- package/dist/cjs/Interfaces/IStorageProvider.js.map +1 -0
- package/dist/cjs/Providers/LocalFileProvider.d.ts +12 -0
- package/dist/cjs/Providers/LocalFileProvider.d.ts.map +1 -0
- package/dist/cjs/Providers/LocalFileProvider.js +60 -0
- package/dist/cjs/Providers/LocalFileProvider.js.map +1 -0
- package/dist/cjs/Providers/S3Provider.d.ts +26 -0
- package/dist/cjs/Providers/S3Provider.d.ts.map +1 -0
- package/dist/cjs/Providers/S3Provider.js +121 -0
- package/dist/cjs/Providers/S3Provider.js.map +1 -0
- package/dist/cjs/Providers/index.d.ts +4 -0
- package/dist/cjs/Providers/index.d.ts.map +1 -0
- package/dist/cjs/Providers/index.js +8 -0
- package/dist/cjs/Providers/index.js.map +1 -0
- package/dist/cjs/errors/HlsStreamerErrors.d.ts +4 -0
- package/dist/cjs/errors/HlsStreamerErrors.d.ts.map +1 -1
- package/dist/cjs/errors/HlsStreamerErrors.js +14 -1
- package/dist/cjs/errors/HlsStreamerErrors.js.map +1 -1
- package/dist/cjs/index.d.ts +5 -2
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +52 -48
- package/dist/cjs/index.js.map +1 -1
- package/dist/errors/HlsStreamerErrors.d.ts +4 -0
- package/dist/errors/HlsStreamerErrors.d.ts.map +1 -1
- package/dist/errors/HlsStreamerErrors.js +12 -0
- package/dist/errors/HlsStreamerErrors.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +50 -45
- package/dist/index.js.map +1 -1
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
<img src="assets/header.png" alt="HLS Streamer" width="100%">
|
|
3
|
-
</div>
|
|
1
|
+

|
|
4
2
|
|
|
5
3
|
# HLS Streamer
|
|
6
4
|
|
|
@@ -16,6 +14,7 @@ HLS Streamer converts audio and video files (MP3, AAC, M4A, OGG Vorbis, FLAC, WA
|
|
|
16
14
|
- [How It Works](#how-it-works)
|
|
17
15
|
- [Quick Start](#quick-start)
|
|
18
16
|
- [Serving Over HTTP](#serving-over-http)
|
|
17
|
+
- [Remote Storage (S3 / MinIO)](#remote-storage-s3--minio)
|
|
19
18
|
- [Configuration Reference](#configuration-reference)
|
|
20
19
|
- [Playlist Anatomy](#playlist-anatomy)
|
|
21
20
|
- [Operational Tips](#operational-tips)
|
|
@@ -28,6 +27,7 @@ HLS Streamer converts audio and video files (MP3, AAC, M4A, OGG Vorbis, FLAC, WA
|
|
|
28
27
|
- **Multi-format support** – handles MP3, AAC, M4A, OGG Vorbis, FLAC, WAV, MP4, MOV, and M4V with automatic format detection.
|
|
29
28
|
- **Audio + Video** – audio files produce standard HLS v6 playlists; video files produce HLS v7 fMP4 playlists with an `EXT-X-MAP` init segment and keyframe-aligned boundaries.
|
|
30
29
|
- **Zero dependencies** – no shared libraries, no ffmpeg, no native compilation. Pure TypeScript parsers for all formats. Drop it into Docker, serverless, or edge runtimes.
|
|
30
|
+
- **Remote storage** – stream directly from S3, MinIO, or any compatible object storage via the `IStorageProvider` interface — no local file required.
|
|
31
31
|
- **Accurate segments** – real frame/packet parsing provides true durations, `#EXTINF` metadata, and target durations that match playback.
|
|
32
32
|
- **Frame-aligned byte ranges** – every segment begins and ends on verified frame boundaries; video segments snap to keyframes to prevent decoding artifacts.
|
|
33
33
|
- **No temp files** – streams straight from the source file using byte-range reads.
|
|
@@ -36,11 +36,12 @@ HLS Streamer converts audio and video files (MP3, AAC, M4A, OGG Vorbis, FLAC, WA
|
|
|
36
36
|
|
|
37
37
|
## How It Works
|
|
38
38
|
|
|
39
|
-
1. **
|
|
40
|
-
2. **
|
|
41
|
-
3. **
|
|
42
|
-
4. **
|
|
43
|
-
5. **
|
|
39
|
+
1. **Storage abstraction** – the source is either a local file (via `filePath`) or any object storage (via `storageProvider`). Both expose the same byte-range interface internally.
|
|
40
|
+
2. **Format detection** – automatically detects format from file content (magic bytes / `ftyp` brand) or extension, with optional manual override.
|
|
41
|
+
3. **Metadata analysis** – format-specific parsers extract frame/packet tables with offsets, durations, and (for video) keyframe markers.
|
|
42
|
+
4. **Segment planning** – boundaries are calculated from the frame table so each segment contains whole frames while respecting your target size. Video segments snap to I-frame boundaries.
|
|
43
|
+
5. **Playlist generation** – `createM3U8()` emits an `#EXTM3U` playlist. Audio files use HLS v6; video files use HLS v7 with `EXT-X-MAP` pointing to the `moov` init segment.
|
|
44
|
+
6. **On-demand byte ranges** – `getFileBuffer(start, end)` reads only the requested bytes — from disk or object storage — without buffering the full file.
|
|
44
45
|
|
|
45
46
|
```
|
|
46
47
|
┌──────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────────────┐
|
|
@@ -147,16 +148,189 @@ For video files, an additional init segment URL is emitted as `EXT-X-MAP`:
|
|
|
147
148
|
- `index` is zero-padded to three digits (`000`, `001`, ...).
|
|
148
149
|
- Serve the exact byte range from the original file — no transcoding needed.
|
|
149
150
|
|
|
151
|
+
## Remote Storage (S3 / MinIO)
|
|
152
|
+
|
|
153
|
+
HLS Streamer can stream directly from object storage — no local file needed. Pass a `storageProvider` instead of `filePath`. The built-in `S3Provider` works with AWS S3, MinIO, Wasabi, Backblaze B2, and any S3-compatible service.
|
|
154
|
+
|
|
155
|
+
### Installation
|
|
156
|
+
|
|
157
|
+
The AWS SDK is a **peer dependency** and only required when using `S3Provider`. Install it separately:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
npm install @aws-sdk/client-s3
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### AWS S3
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
import { HlsStreamer, S3Provider } from 'hls-streamer';
|
|
167
|
+
|
|
168
|
+
const provider = new S3Provider({
|
|
169
|
+
bucket: 'my-media-bucket',
|
|
170
|
+
key: 'podcasts/episode-42.mp3',
|
|
171
|
+
clientConfig: {
|
|
172
|
+
region: 'us-east-1',
|
|
173
|
+
// credentials resolved automatically from env / IAM role
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const streamer = new HlsStreamer({
|
|
178
|
+
storageProvider: provider,
|
|
179
|
+
fileName: 'episode',
|
|
180
|
+
baseUrl: 'streams/ep42',
|
|
181
|
+
segmentSizeKB: 512,
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const playlist = await streamer.createM3U8();
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Passing explicit credentials:
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
191
|
+
import { HlsStreamer, S3Provider } from 'hls-streamer';
|
|
192
|
+
|
|
193
|
+
const s3Client = new S3Client({
|
|
194
|
+
region: 'eu-west-1',
|
|
195
|
+
credentials: {
|
|
196
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
197
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
const provider = new S3Provider({
|
|
202
|
+
bucket: 'my-media-bucket',
|
|
203
|
+
key: 'videos/clip.mp4',
|
|
204
|
+
client: s3Client, // reuse an existing client
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
const streamer = new HlsStreamer({ storageProvider: provider });
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### MinIO
|
|
211
|
+
|
|
212
|
+
MinIO is fully S3-compatible. Point `endpoint` at your MinIO server and set `forcePathStyle: true`:
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
216
|
+
import { HlsStreamer, S3Provider } from 'hls-streamer';
|
|
217
|
+
|
|
218
|
+
const minioClient = new S3Client({
|
|
219
|
+
endpoint: 'http://localhost:9000', // your MinIO server
|
|
220
|
+
region: 'us-east-1', // any non-empty string
|
|
221
|
+
forcePathStyle: true, // required for MinIO
|
|
222
|
+
credentials: {
|
|
223
|
+
accessKeyId: 'minioadmin',
|
|
224
|
+
secretAccessKey: 'minioadmin',
|
|
225
|
+
},
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
const provider = new S3Provider({
|
|
229
|
+
bucket: 'media',
|
|
230
|
+
key: 'audio/track.mp3',
|
|
231
|
+
client: minioClient,
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
const streamer = new HlsStreamer({
|
|
235
|
+
storageProvider: provider,
|
|
236
|
+
fileName: 'track',
|
|
237
|
+
baseUrl: 'streams/track',
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
const playlist = await streamer.createM3U8();
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Serving S3 / MinIO streams over HTTP (Express)
|
|
244
|
+
|
|
245
|
+
The HTTP handler is identical to the local-file version — only the streamer construction changes:
|
|
246
|
+
|
|
247
|
+
```ts
|
|
248
|
+
import express from 'express';
|
|
249
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
250
|
+
import { HlsStreamer, S3Provider } from 'hls-streamer';
|
|
251
|
+
|
|
252
|
+
const app = express();
|
|
253
|
+
|
|
254
|
+
// Reuse one client for the lifetime of the process
|
|
255
|
+
const s3 = new S3Client({ region: 'us-east-1' });
|
|
256
|
+
|
|
257
|
+
function makeStreamer(bucket: string, key: string, sessionId: string) {
|
|
258
|
+
return new HlsStreamer({
|
|
259
|
+
storageProvider: new S3Provider({ bucket, key, client: s3 }),
|
|
260
|
+
baseUrl: `streams/${sessionId}`,
|
|
261
|
+
fileName: 'segment',
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
app.get('/streams/:session/playlist.m3u8', async (req, res, next) => {
|
|
266
|
+
try {
|
|
267
|
+
const streamer = makeStreamer('my-bucket', resolveKey(req.params.session), req.params.session);
|
|
268
|
+
res.type('application/vnd.apple.mpegurl');
|
|
269
|
+
res.send(await streamer.createM3U8());
|
|
270
|
+
} catch (err) { next(err); }
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
app.get('/streams/:session/:start/:end/:filename', async (req, res, next) => {
|
|
274
|
+
try {
|
|
275
|
+
const streamer = makeStreamer('my-bucket', resolveKey(req.params.session), req.params.session);
|
|
276
|
+
const mediaType = await streamer.getMediaType();
|
|
277
|
+
res.type(mediaType === 'video' ? 'video/mp4' : 'audio/mpeg');
|
|
278
|
+
res.set('Accept-Ranges', 'bytes');
|
|
279
|
+
res.send(await streamer.getFileBuffer(Number(req.params.start), Number(req.params.end)));
|
|
280
|
+
} catch (err) { next(err); }
|
|
281
|
+
});
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Custom storage provider
|
|
285
|
+
|
|
286
|
+
Implement `IStorageProvider` to connect any storage backend (GCS, Azure Blob, HTTP, etc.):
|
|
287
|
+
|
|
288
|
+
```ts
|
|
289
|
+
import { IStorageProvider } from 'hls-streamer';
|
|
290
|
+
|
|
291
|
+
class MyProvider implements IStorageProvider {
|
|
292
|
+
readonly resourceId = 'custom://my-source';
|
|
293
|
+
|
|
294
|
+
async getSize(): Promise<number> { /* return total file size */ }
|
|
295
|
+
async getRange(start: number, end: number): Promise<Buffer> { /* [start, end) bytes */ }
|
|
296
|
+
async getHeader(): Promise<Buffer> { return this.getRange(0, 64); }
|
|
297
|
+
async getBuffer(): Promise<Buffer> { /* full file */ }
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const streamer = new HlsStreamer({ storageProvider: new MyProvider() });
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
> **Tip:** `getRange` is the hot path — use HTTP byte-range requests (`Range: bytes=start-end`) to avoid downloading the full file for each segment.
|
|
304
|
+
|
|
305
|
+
### Error handling
|
|
306
|
+
|
|
307
|
+
```ts
|
|
308
|
+
import { StorageProviderError } from 'hls-streamer';
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
const playlist = await streamer.createM3U8();
|
|
312
|
+
} catch (err) {
|
|
313
|
+
if (err instanceof StorageProviderError) {
|
|
314
|
+
console.error(`Storage error for ${err.resourceId}:`, err.message);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
150
321
|
## Configuration Reference
|
|
151
322
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
|
155
|
-
|
|
|
156
|
-
| `
|
|
157
|
-
| `
|
|
158
|
-
| `
|
|
159
|
-
| `
|
|
323
|
+
Provide either `filePath` **or** `storageProvider` — not both.
|
|
324
|
+
|
|
325
|
+
| Option | Type | Default | Description |
|
|
326
|
+
| ------------------- | --------------------- | ------------ | ----------- |
|
|
327
|
+
| `filePath` | `string` | — | Path to a local media file. Supports: MP3, AAC, M4A, OGG, FLAC, WAV, MP4, MOV, M4V. |
|
|
328
|
+
| `storageProvider` | `IStorageProvider` | — | Remote storage provider (e.g. `S3Provider`). Mutually exclusive with `filePath`. |
|
|
329
|
+
| `segmentSizeKB` | `number` | `512` | Target segment size in kilobytes. |
|
|
330
|
+
| `fileName` | `string` | `"file"` | Base name for generated segment URLs. |
|
|
331
|
+
| `baseUrl` | `string` | `""` | URL prefix inserted before each segment path. |
|
|
332
|
+
| `enableFastStart` | `boolean` | `false` | Smaller first two segments for faster playback start. |
|
|
333
|
+
| `format` | `MediaFormat` | auto-detect | Optional override: `'mp3'`, `'aac'`, `'m4a'`, `'ogg'`, `'flac'`, `'wav'`, `'mp4'`, `'mov'`, `'m4v'`. |
|
|
160
334
|
|
|
161
335
|
### API Surface
|
|
162
336
|
|
|
@@ -165,7 +339,7 @@ For video files, an additional init segment URL is emitted as `EXT-X-MAP`:
|
|
|
165
339
|
- `getSegmentDuration(index: number): Promise<number>` – Duration in seconds for a specific segment.
|
|
166
340
|
- `getMediaType(): Promise<'audio' | 'video'>` – Returns `'video'` for MP4/MOV/M4V, `'audio'` for everything else.
|
|
167
341
|
|
|
168
|
-
Custom error classes: `FileNotFoundError`, `InvalidFileError`, `InvalidRangeError`, `InvalidParameterError`, `UnsupportedFormatError`.
|
|
342
|
+
Custom error classes: `FileNotFoundError`, `InvalidFileError`, `InvalidRangeError`, `InvalidParameterError`, `UnsupportedFormatError`, `StorageProviderError`.
|
|
169
343
|
|
|
170
344
|
### Supported Formats
|
|
171
345
|
|
|
@@ -227,6 +401,8 @@ Custom error classes: `FileNotFoundError`, `InvalidFileError`, `InvalidRangeErro
|
|
|
227
401
|
- **CDN friendliness** – Segment URLs are deterministic byte ranges, making them ideal for edge caching. Use `Cache-Control: public, max-age=86400`.
|
|
228
402
|
- **Serverless** – Zero-dependency design works in Lambda/Cloud Functions. `getFileBuffer` reads only the bytes needed, keeping memory usage low.
|
|
229
403
|
- **Content-Type** – Serve audio segments as `audio/mpeg` (or the appropriate codec MIME type) and video segments as `video/mp4`. Use `getMediaType()` to branch at runtime.
|
|
404
|
+
- **S3 client reuse** – Create one `S3Client` for the lifetime of your process and pass it to each `S3Provider`. This avoids per-request connection overhead and respects connection pool limits.
|
|
405
|
+
- **MinIO in Docker** – Set `endpoint` to your MinIO container URL and `forcePathStyle: true`. The bucket must exist and the credentials must have `s3:GetObject` and `s3:HeadObject` permissions.
|
|
230
406
|
- **Troubleshooting** – Inspect `FileLib.analyzeMediaFile()` to review parsing warnings and format-specific metadata.
|
|
231
407
|
|
|
232
408
|
## Development
|
|
@@ -257,6 +433,31 @@ Contributions are welcome! Please open an issue to discuss substantial changes b
|
|
|
257
433
|
|
|
258
434
|
## Release Notes
|
|
259
435
|
|
|
436
|
+
### Version 4.5.0
|
|
437
|
+
|
|
438
|
+
#### New Features
|
|
439
|
+
|
|
440
|
+
- **Remote storage support** – stream directly from S3, MinIO, or any S3-compatible service without downloading files locally. Pass a `storageProvider` to `HlsStreamerOptions` instead of `filePath`.
|
|
441
|
+
- **`S3Provider`** – built-in provider for AWS S3 and S3-compatible services (MinIO, Wasabi, Backblaze B2, etc.). Accepts a pre-configured `S3Client` or creates one from `clientConfig`. Uses HTTP byte-range requests for segments, avoiding full file downloads. `@aws-sdk/client-s3` is an **optional peer dependency** — only install it if you use `S3Provider`.
|
|
442
|
+
- **`IStorageProvider` interface** – implement this to connect any custom storage backend (GCS, Azure Blob, HTTP, etc.).
|
|
443
|
+
- **`StorageProviderError`** – new typed error thrown when a storage provider operation fails, carrying the `resourceId` of the failing resource.
|
|
444
|
+
- **`LocalFileProvider`** – the existing filesystem logic is now a first-class provider. Exported for use in custom wrappers or testing.
|
|
445
|
+
|
|
446
|
+
#### Migration
|
|
447
|
+
|
|
448
|
+
No changes needed for existing code. `filePath` continues to work exactly as before.
|
|
449
|
+
|
|
450
|
+
```ts
|
|
451
|
+
// v4.0 — unchanged, still works
|
|
452
|
+
new HlsStreamer({ filePath: '/local/audio.mp3' });
|
|
453
|
+
|
|
454
|
+
// v4.5 — new: remote storage
|
|
455
|
+
import { S3Provider } from 'hls-streamer';
|
|
456
|
+
new HlsStreamer({ storageProvider: new S3Provider({ bucket: 'b', key: 'audio.mp3', client: s3 }) });
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
---
|
|
460
|
+
|
|
260
461
|
### Version 4.0.0
|
|
261
462
|
|
|
262
463
|
Major release adding video support and completing the audio→media rename.
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import { MediaFormat } from '../Parsers/IMediaParser';
|
|
2
|
-
|
|
2
|
+
import { IStorageProvider } from './IStorageProvider';
|
|
3
|
+
export type { IStorageProvider };
|
|
4
|
+
type LocalFileSource = {
|
|
3
5
|
filePath: string;
|
|
6
|
+
storageProvider?: never;
|
|
7
|
+
};
|
|
8
|
+
type RemoteStorageSource = {
|
|
9
|
+
storageProvider: IStorageProvider;
|
|
10
|
+
filePath?: never;
|
|
11
|
+
};
|
|
12
|
+
type SharedOptions = {
|
|
4
13
|
segmentSizeKB?: number;
|
|
5
14
|
fileName?: string;
|
|
6
15
|
baseUrl?: string;
|
|
7
16
|
enableFastStart?: boolean;
|
|
8
17
|
format?: MediaFormat;
|
|
9
|
-
}
|
|
18
|
+
};
|
|
19
|
+
export type HlsStreamerOptions = (LocalFileSource | RemoteStorageSource) & SharedOptions;
|
|
10
20
|
export interface SegmentInfo {
|
|
11
21
|
start: number;
|
|
12
22
|
end: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HlsStreamer.d.ts","sourceRoot":"","sources":["../../src/Interfaces/HlsStreamer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"HlsStreamer.d.ts","sourceRoot":"","sources":["../../src/Interfaces/HlsStreamer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAEjC,KAAK,eAAe,GAAG;IAErB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,KAAK,CAAC;CACzB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IAEzB,eAAe,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB,CAAC;AAEF,KAAK,aAAa,GAAG;IAEnB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAMF,MAAM,MAAM,kBAAkB,GAAG,CAAC,eAAe,GAAG,mBAAmB,CAAC,GAAG,aAAa,CAAC;AAKzF,MAAM,WAAW,WAAW;IAE1B,KAAK,EAAE,MAAM,CAAC;IAEd,GAAG,EAAE,MAAM,CAAC;IAEZ,QAAQ,EAAE,MAAM,CAAC;CAClB;AAGD,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAGxG,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAKxG,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;CACjB;AAKD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface IStorageProvider {
|
|
2
|
+
readonly resourceId?: string;
|
|
3
|
+
getSize(): Promise<number>;
|
|
4
|
+
getRange(start: number, end: number): Promise<Buffer>;
|
|
5
|
+
getHeader(): Promise<Buffer>;
|
|
6
|
+
getBuffer(): Promise<Buffer>;
|
|
7
|
+
validateSync?(): void;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=IStorageProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IStorageProvider.d.ts","sourceRoot":"","sources":["../../src/Interfaces/IStorageProvider.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAE3B,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEtD,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAE7B,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAE7B,YAAY,CAAC,IAAI,IAAI,CAAC;CACvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IStorageProvider.js","sourceRoot":"","sources":["../../src/Interfaces/IStorageProvider.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { IStorageProvider } from '../Interfaces/IStorageProvider';
|
|
2
|
+
export declare class LocalFileProvider implements IStorageProvider {
|
|
3
|
+
private readonly filePath;
|
|
4
|
+
readonly resourceId: string;
|
|
5
|
+
constructor(filePath: string);
|
|
6
|
+
validateSync(): void;
|
|
7
|
+
getSize(): Promise<number>;
|
|
8
|
+
getRange(start: number, end: number): Promise<Buffer>;
|
|
9
|
+
getHeader(): Promise<Buffer>;
|
|
10
|
+
getBuffer(): Promise<Buffer>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=LocalFileProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocalFileProvider.d.ts","sourceRoot":"","sources":["../../src/Providers/LocalFileProvider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAGlE,qBAAa,iBAAkB,YAAW,gBAAgB;IAG5C,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAFrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEC,QAAQ,EAAE,MAAM;IAI7C,YAAY,IAAI,IAAI;IAUd,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAK1B,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAarD,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;IAI5B,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;CAGnC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { FileNotFoundError, InvalidFileError } from '../errors/HlsStreamerErrors';
|
|
3
|
+
export class LocalFileProvider {
|
|
4
|
+
constructor(filePath) {
|
|
5
|
+
Object.defineProperty(this, "filePath", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
configurable: true,
|
|
8
|
+
writable: true,
|
|
9
|
+
value: filePath
|
|
10
|
+
});
|
|
11
|
+
Object.defineProperty(this, "resourceId", {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
configurable: true,
|
|
14
|
+
writable: true,
|
|
15
|
+
value: void 0
|
|
16
|
+
});
|
|
17
|
+
this.resourceId = filePath;
|
|
18
|
+
}
|
|
19
|
+
validateSync() {
|
|
20
|
+
if (!fs.existsSync(this.filePath)) {
|
|
21
|
+
throw new FileNotFoundError(this.filePath);
|
|
22
|
+
}
|
|
23
|
+
const stat = fs.statSync(this.filePath);
|
|
24
|
+
if (!stat.isFile()) {
|
|
25
|
+
throw new InvalidFileError('Path is not a file');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async getSize() {
|
|
29
|
+
const stat = await fs.promises.stat(this.filePath);
|
|
30
|
+
return stat.size;
|
|
31
|
+
}
|
|
32
|
+
async getRange(start, end) {
|
|
33
|
+
const length = end - start;
|
|
34
|
+
if (length === 0)
|
|
35
|
+
return Buffer.alloc(0);
|
|
36
|
+
const fd = fs.openSync(this.filePath, 'r');
|
|
37
|
+
try {
|
|
38
|
+
const buffer = Buffer.alloc(length);
|
|
39
|
+
const bytesRead = fs.readSync(fd, buffer, 0, length, start);
|
|
40
|
+
return buffer.subarray(0, bytesRead);
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
fs.closeSync(fd);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async getHeader() {
|
|
47
|
+
return this.getRange(0, 64);
|
|
48
|
+
}
|
|
49
|
+
async getBuffer() {
|
|
50
|
+
return fs.promises.readFile(this.filePath);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=LocalFileProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocalFileProvider.js","sourceRoot":"","sources":["../../src/Providers/LocalFileProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAElF,MAAM,OAAO,iBAAiB;IAG5B,YAA6B,QAAgB;QAAjC;;;;mBAAiB,QAAQ;WAAQ;QAFpC;;;;;WAAmB;QAG1B,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC;IAC7B,CAAC;IAED,YAAY;QACV,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YACnB,MAAM,IAAI,gBAAgB,CAAC,oBAAoB,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAa,EAAE,GAAW;QACvC,MAAM,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC;QAC3B,IAAI,MAAM,KAAK,CAAC;YAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACzC,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAC3C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACpC,MAAM,SAAS,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAa,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACnE,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QACvC,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC;CACF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { IStorageProvider } from '../Interfaces/IStorageProvider';
|
|
2
|
+
export interface S3ProviderOptions {
|
|
3
|
+
bucket: string;
|
|
4
|
+
key: string;
|
|
5
|
+
client?: any;
|
|
6
|
+
clientConfig?: Record<string, any>;
|
|
7
|
+
_commands?: {
|
|
8
|
+
HeadObjectCommand: new (input: any) => any;
|
|
9
|
+
GetObjectCommand: new (input: any) => any;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export declare class S3Provider implements IStorageProvider {
|
|
13
|
+
readonly resourceId: string;
|
|
14
|
+
private readonly bucket;
|
|
15
|
+
private readonly key;
|
|
16
|
+
private readonly client;
|
|
17
|
+
private readonly HeadObjectCommand;
|
|
18
|
+
private readonly GetObjectCommand;
|
|
19
|
+
constructor(options: S3ProviderOptions);
|
|
20
|
+
getSize(): Promise<number>;
|
|
21
|
+
getRange(start: number, end: number): Promise<Buffer>;
|
|
22
|
+
getHeader(): Promise<Buffer>;
|
|
23
|
+
getBuffer(): Promise<Buffer>;
|
|
24
|
+
private streamToBuffer;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=S3Provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"S3Provider.d.ts","sourceRoot":"","sources":["../../src/Providers/S3Provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAGlE,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IAEZ,MAAM,CAAC,EAAE,GAAG,CAAC;IAEb,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAEnC,SAAS,CAAC,EAAE;QACV,iBAAiB,EAAE,KAAK,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC;QAC3C,gBAAgB,EAAE,KAAK,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC;KAC3C,CAAC;CACH;AAED,qBAAa,UAAW,YAAW,gBAAgB;IACjD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAM;IAC7B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA0B;IAC5D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA0B;gBAE/C,OAAO,EAAE,iBAAiB;IA8BhC,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAe1B,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAkBrD,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;IAI5B,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;YAYpB,cAAc;CAO7B"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { StorageProviderError } from '../errors/HlsStreamerErrors';
|
|
2
|
+
export class S3Provider {
|
|
3
|
+
constructor(options) {
|
|
4
|
+
Object.defineProperty(this, "resourceId", {
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true,
|
|
7
|
+
writable: true,
|
|
8
|
+
value: void 0
|
|
9
|
+
});
|
|
10
|
+
Object.defineProperty(this, "bucket", {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
writable: true,
|
|
14
|
+
value: void 0
|
|
15
|
+
});
|
|
16
|
+
Object.defineProperty(this, "key", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
configurable: true,
|
|
19
|
+
writable: true,
|
|
20
|
+
value: void 0
|
|
21
|
+
});
|
|
22
|
+
Object.defineProperty(this, "client", {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
writable: true,
|
|
26
|
+
value: void 0
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(this, "HeadObjectCommand", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
configurable: true,
|
|
31
|
+
writable: true,
|
|
32
|
+
value: void 0
|
|
33
|
+
});
|
|
34
|
+
Object.defineProperty(this, "GetObjectCommand", {
|
|
35
|
+
enumerable: true,
|
|
36
|
+
configurable: true,
|
|
37
|
+
writable: true,
|
|
38
|
+
value: void 0
|
|
39
|
+
});
|
|
40
|
+
this.bucket = options.bucket;
|
|
41
|
+
this.key = options.key;
|
|
42
|
+
this.resourceId = `s3://${options.bucket}/${options.key}`;
|
|
43
|
+
let sdk;
|
|
44
|
+
if (options._commands) {
|
|
45
|
+
sdk = options._commands;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
try {
|
|
49
|
+
sdk = require('@aws-sdk/client-s3');
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
throw new StorageProviderError('@aws-sdk/client-s3 is not installed. Run: npm install @aws-sdk/client-s3', this.resourceId);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
this.HeadObjectCommand = sdk.HeadObjectCommand;
|
|
56
|
+
this.GetObjectCommand = sdk.GetObjectCommand;
|
|
57
|
+
if (options.client) {
|
|
58
|
+
this.client = options.client;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
this.client = new sdk.S3Client(options.clientConfig ?? {});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async getSize() {
|
|
65
|
+
try {
|
|
66
|
+
const res = await this.client.send(new this.HeadObjectCommand({ Bucket: this.bucket, Key: this.key }));
|
|
67
|
+
if (res.ContentLength === undefined) {
|
|
68
|
+
throw new StorageProviderError('Could not determine object size', this.resourceId);
|
|
69
|
+
}
|
|
70
|
+
return res.ContentLength;
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
if (err instanceof StorageProviderError)
|
|
74
|
+
throw err;
|
|
75
|
+
throw new StorageProviderError(err.message, this.resourceId);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async getRange(start, end) {
|
|
79
|
+
if (start === end)
|
|
80
|
+
return Buffer.alloc(0);
|
|
81
|
+
try {
|
|
82
|
+
const res = await this.client.send(new this.GetObjectCommand({
|
|
83
|
+
Bucket: this.bucket,
|
|
84
|
+
Key: this.key,
|
|
85
|
+
Range: `bytes=${start}-${end - 1}`,
|
|
86
|
+
}));
|
|
87
|
+
return this.streamToBuffer(res.Body);
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
if (err instanceof StorageProviderError)
|
|
91
|
+
throw err;
|
|
92
|
+
throw new StorageProviderError(err.message, this.resourceId);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async getHeader() {
|
|
96
|
+
return this.getRange(0, 64);
|
|
97
|
+
}
|
|
98
|
+
async getBuffer() {
|
|
99
|
+
try {
|
|
100
|
+
const res = await this.client.send(new this.GetObjectCommand({ Bucket: this.bucket, Key: this.key }));
|
|
101
|
+
return this.streamToBuffer(res.Body);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
if (err instanceof StorageProviderError)
|
|
105
|
+
throw err;
|
|
106
|
+
throw new StorageProviderError(err.message, this.resourceId);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async streamToBuffer(stream) {
|
|
110
|
+
const chunks = [];
|
|
111
|
+
for await (const chunk of stream) {
|
|
112
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
113
|
+
}
|
|
114
|
+
return Buffer.concat(chunks);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=S3Provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"S3Provider.js","sourceRoot":"","sources":["../../src/Providers/S3Provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/Providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import { MediaFormat } from '../Parsers/IMediaParser';
|
|
2
|
-
|
|
2
|
+
import { IStorageProvider } from './IStorageProvider';
|
|
3
|
+
export type { IStorageProvider };
|
|
4
|
+
type LocalFileSource = {
|
|
3
5
|
filePath: string;
|
|
6
|
+
storageProvider?: never;
|
|
7
|
+
};
|
|
8
|
+
type RemoteStorageSource = {
|
|
9
|
+
storageProvider: IStorageProvider;
|
|
10
|
+
filePath?: never;
|
|
11
|
+
};
|
|
12
|
+
type SharedOptions = {
|
|
4
13
|
segmentSizeKB?: number;
|
|
5
14
|
fileName?: string;
|
|
6
15
|
baseUrl?: string;
|
|
7
16
|
enableFastStart?: boolean;
|
|
8
17
|
format?: MediaFormat;
|
|
9
|
-
}
|
|
18
|
+
};
|
|
19
|
+
export type HlsStreamerOptions = (LocalFileSource | RemoteStorageSource) & SharedOptions;
|
|
10
20
|
export interface SegmentInfo {
|
|
11
21
|
start: number;
|
|
12
22
|
end: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HlsStreamer.d.ts","sourceRoot":"","sources":["../../../src/Interfaces/HlsStreamer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"HlsStreamer.d.ts","sourceRoot":"","sources":["../../../src/Interfaces/HlsStreamer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAEjC,KAAK,eAAe,GAAG;IAErB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,KAAK,CAAC;CACzB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IAEzB,eAAe,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB,CAAC;AAEF,KAAK,aAAa,GAAG;IAEnB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAMF,MAAM,MAAM,kBAAkB,GAAG,CAAC,eAAe,GAAG,mBAAmB,CAAC,GAAG,aAAa,CAAC;AAKzF,MAAM,WAAW,WAAW;IAE1B,KAAK,EAAE,MAAM,CAAC;IAEd,GAAG,EAAE,MAAM,CAAC;IAEZ,QAAQ,EAAE,MAAM,CAAC;CAClB;AAGD,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAGxG,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAKxG,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;CACjB;AAKD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface IStorageProvider {
|
|
2
|
+
readonly resourceId?: string;
|
|
3
|
+
getSize(): Promise<number>;
|
|
4
|
+
getRange(start: number, end: number): Promise<Buffer>;
|
|
5
|
+
getHeader(): Promise<Buffer>;
|
|
6
|
+
getBuffer(): Promise<Buffer>;
|
|
7
|
+
validateSync?(): void;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=IStorageProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IStorageProvider.d.ts","sourceRoot":"","sources":["../../../src/Interfaces/IStorageProvider.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAE3B,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEtD,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAE7B,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAE7B,YAAY,CAAC,IAAI,IAAI,CAAC;CACvB"}
|