@vidtreo/recorder 0.0.1 → 0.8.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @vidtreo/recorder
2
2
 
3
- Video transcoding package using mediabunny. Transcodes videos to MP4 format with configurable settings, optimized for Bun runtime.
3
+ Vidtreo SDK for browser-based video recording and transcoding. Similar to Ziggeo and Addpipe, Vidtreo provides enterprise-grade video processing capabilities for web applications. Features include camera and screen recording, real-time MP4 transcoding, audio level analysis, mute/pause controls, source switching, device selection, and automatic backend uploads.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,222 +8,709 @@ Video transcoding package using mediabunny. Transcodes videos to MP4 format with
8
8
  npm install @vidtreo/recorder
9
9
  ```
10
10
 
11
- ## Usage
11
+ ## Quick Start
12
12
 
13
- ### Basic Usage
13
+ ```typescript
14
+ import { VidtreoRecorder } from '@vidtreo/recorder';
15
+
16
+ const recorder = new VidtreoRecorder({
17
+ apiKey: 'your-api-key',
18
+ apiUrl: 'https://your-worker.workers.dev',
19
+ enableSourceSwitching: true,
20
+ maxRecordingTime: 300000,
21
+ onUploadComplete: (result) => {
22
+ console.log('Recording ID:', result.recordingId);
23
+ console.log('Video URL:', result.uploadUrl);
24
+ },
25
+ });
26
+
27
+ await recorder.startPreview('camera');
28
+ await recorder.startRecording({}, 'camera');
29
+ const result = await recorder.stopRecording();
30
+ recorder.cleanup();
31
+ ```
32
+
33
+ ## API Reference
34
+
35
+ ### VidtreoRecorder
36
+
37
+ The main class for recording video from camera or screen sources.
38
+
39
+ #### Constructor
14
40
 
15
41
  ```typescript
16
- import { transcodeVideo } from '@vidtreo/recorder';
42
+ new VidtreoRecorder(config: VidtreoRecorderConfig)
43
+ ```
17
44
 
18
- // Transcode from a Blob
19
- const videoBlob = new Blob([videoData], { type: 'video/mp4' });
20
- const result = await transcodeVideo(videoBlob);
21
- console.log(result.buffer); // ArrayBuffer with transcoded video
22
- console.log(result.blob); // Blob with transcoded video
45
+ Creates a new recorder instance with the specified configuration.
46
+
47
+ **Parameters:**
48
+
49
+ - `config.apiKey` (required): Your API key for backend authentication
50
+ - `config.apiUrl` (required): Your backend API URL endpoint
51
+ - `config.enableSourceSwitching` (optional): Enable switching between camera and screen during recording. Default: `false`
52
+ - `config.enableMute` (optional): Enable mute/unmute functionality. When disabled, `muteAudio()`, `unmuteAudio()`, and `toggleMute()` will throw errors. Default: `true`
53
+ - `config.enablePause` (optional): Enable pause/resume functionality. When disabled, `pauseRecording()` and `resumeRecording()` will throw errors. Default: `true`
54
+ - `config.enableDeviceChange` (optional): Enable device selection functionality. When disabled, `getAvailableDevices()` will throw an error. Default: `true`
55
+ - `config.maxRecordingTime` (optional): Maximum recording duration in milliseconds. When the maximum time is reached, recording automatically stops. If not set, recording can continue indefinitely until manually stopped. Examples: `300000` (5 minutes), `600000` (10 minutes), `1800000` (30 minutes)
56
+ - `config.countdownDuration` (optional): Countdown duration in milliseconds before recording starts. Default: `0` (no countdown)
57
+ - `config.userMetadata` (optional): Custom metadata object to include with uploads
58
+ - `config.onUploadComplete` (optional): Callback invoked when upload completes successfully
59
+ - `config.onUploadProgress` (optional): Callback invoked during upload with progress value (0-1)
60
+ - `config.onUploadError` (optional): Callback invoked when upload fails
61
+ - `config.onRecordingStart` (optional): Callback invoked when recording starts
62
+ - `config.onRecordingStop` (optional): Callback invoked when recording stops
63
+ - `config.onError` (optional): Callback invoked when a stream error occurs
64
+
65
+ **Throws:** `Error` if `apiKey` or `apiUrl` are missing
66
+
67
+ #### Methods
68
+
69
+ ##### `initialize(): Promise<void>`
70
+
71
+ Initializes the recorder with the provided configuration. Called automatically when needed, but can be called explicitly for early initialization.
72
+
73
+ **Returns:** `Promise<void>`
74
+
75
+ ##### `startPreview(sourceType?: SourceType): Promise<MediaStream>`
76
+
77
+ Starts a preview stream from the specified source without recording.
78
+
79
+ **Parameters:**
80
+
81
+ - `sourceType` (optional): Source type to preview. Either `'camera'` or `'screen'`. Default: `'camera'`
82
+
83
+ **Returns:** `Promise<MediaStream>` - The preview media stream
84
+
85
+ **Throws:** `Error` if stream initialization fails
86
+
87
+ ##### `startRecording(options?: RecordingStartOptions, sourceType?: SourceType): Promise<void>`
88
+
89
+ Starts recording from the specified source. If no preview is active, automatically starts one.
90
+
91
+ **Parameters:**
92
+
93
+ - `options` (optional): Recording options object
94
+ - `options.video`: Video constraints (boolean or `CameraConstraints` object)
95
+ - `options.audio`: Audio constraints (boolean or `MediaTrackConstraints` object)
96
+ - `sourceType` (optional): Source type to record from. Either `'camera'` or `'screen'`. Default: `'camera'`
97
+
98
+ **Returns:** `Promise<void>`
99
+
100
+ **Throws:** `Error` if recording cannot be started
101
+
102
+ ##### `stopRecording(): Promise<RecordingStopResult>`
103
+
104
+ Stops the current recording, transcodes the video, and uploads it to the backend.
105
+
106
+ **Returns:** `Promise<RecordingStopResult>` - Object containing:
107
+ - `recordingId`: Unique identifier for the uploaded recording
108
+ - `uploadUrl`: URL where the video can be accessed
109
+ - `blob`: The recorded video as a Blob
110
+
111
+ **Throws:** `Error` if recording is not active or upload fails
112
+
113
+ ##### `switchSource(sourceType: SourceType): Promise<void>`
114
+
115
+ Switches the recording source between camera and screen during an active recording.
116
+
117
+ **Parameters:**
118
+
119
+ - `sourceType`: Target source type. Either `'camera'` or `'screen'`
120
+
121
+ **Returns:** `Promise<void>`
122
+
123
+ **Throws:** `Error` if source switching is not enabled or if not currently recording
124
+
125
+ ##### `getAvailableDevices(): Promise<AvailableDevices>`
126
+
127
+ Retrieves the list of available camera and microphone devices.
128
+
129
+ **Returns:** `Promise<AvailableDevices>` - Object containing:
130
+ - `video`: Array of available video input devices
131
+ - `audio`: Array of available audio input devices
132
+
133
+ **Throws:** `Error` if device change functionality is disabled (`enableDeviceChange === false`)
134
+
135
+ ##### `muteAudio(): void`
136
+
137
+ Mutes the audio track during recording.
138
+
139
+ **Throws:** `Error` if mute functionality is disabled (`enableMute === false`)
140
+
141
+ ##### `unmuteAudio(): void`
142
+
143
+ Unmutes the audio track during recording.
23
144
 
24
- // Transcode from a File
25
- const fileInput = document.querySelector('input[type="file"]');
26
- const file = fileInput.files[0];
27
- const result = await transcodeVideo(file);
145
+ **Throws:** `Error` if mute functionality is disabled (`enableMute === false`)
28
146
 
29
- // Transcode from a file path (Bun only)
30
- const result = await transcodeVideo('/path/to/video.mp4');
147
+ ##### `toggleMute(): void`
148
+
149
+ Toggles the mute state of the audio track.
150
+
151
+ **Throws:** `Error` if mute functionality is disabled (`enableMute === false`)
152
+
153
+ ##### `isMuted(): boolean`
154
+
155
+ Returns the current mute state.
156
+
157
+ **Returns:** `true` if audio is muted, `false` otherwise
158
+
159
+ ##### `pauseRecording(): void`
160
+
161
+ Pauses the current recording. Video frames are not captured while paused.
162
+
163
+ **Throws:** `Error` if pause functionality is disabled (`enablePause === false`)
164
+
165
+ ##### `resumeRecording(): void`
166
+
167
+ Resumes a paused recording.
168
+
169
+ **Throws:** `Error` if pause functionality is disabled (`enablePause === false`)
170
+
171
+ ##### `isPaused(): boolean`
172
+
173
+ Returns the current pause state.
174
+
175
+ **Returns:** `true` if recording is paused, `false` otherwise
176
+
177
+ ##### `getRecordingState(): RecordingState`
178
+
179
+ Returns the current recording state.
180
+
181
+ **Returns:** One of:
182
+ - `'idle'`: Not recording
183
+ - `'countdown'`: Countdown in progress before recording
184
+ - `'recording'`: Actively recording
185
+
186
+ ##### `getStream(): MediaStream | null`
187
+
188
+ Returns the current media stream, or `null` if no stream is active.
189
+
190
+ **Returns:** `MediaStream | null`
191
+
192
+ ##### `cleanup(): void`
193
+
194
+ Cleans up all resources, stops active streams, and cancels any pending operations. Should be called when the recorder is no longer needed.
195
+
196
+ ## Type Definitions
197
+
198
+ ### VidtreoRecorderConfig
199
+
200
+ ```typescript
201
+ interface VidtreoRecorderConfig {
202
+ apiKey: string;
203
+ apiUrl: string;
204
+ enableSourceSwitching?: boolean;
205
+ enableMute?: boolean;
206
+ enablePause?: boolean;
207
+ enableDeviceChange?: boolean;
208
+ maxRecordingTime?: number;
209
+ countdownDuration?: number;
210
+ userMetadata?: Record<string, unknown>;
211
+ onUploadComplete?: (result: {
212
+ recordingId: string;
213
+ uploadUrl: string;
214
+ }) => void;
215
+ onUploadProgress?: (progress: number) => void;
216
+ onUploadError?: (error: Error) => void;
217
+ onRecordingStart?: () => void;
218
+ onRecordingStop?: () => void;
219
+ onError?: (error: Error) => void;
220
+ }
31
221
  ```
32
222
 
33
- ### Custom Configuration
223
+ **Note:** For web component usage, see the [@vidtreo/recorder-wc](../recorder-wc/README.md) package. Use the `max-recording-time` attribute instead of `maxRecordingTime`. The attribute accepts a numeric value in milliseconds as a string (e.g., `max-recording-time="300000"` for 5 minutes).
224
+
225
+ ### RecordingStartOptions
34
226
 
35
227
  ```typescript
36
- import { transcodeVideo, DEFAULT_TRANSCODE_CONFIG } from '@vidtreo/recorder';
228
+ interface RecordingStartOptions {
229
+ video?: boolean | CameraConstraints;
230
+ audio?: boolean | MediaTrackConstraints;
231
+ }
232
+ ```
37
233
 
38
- // Use custom configuration
39
- const result = await transcodeVideo(videoBlob, {
40
- width: 1920,
41
- height: 1080,
42
- fps: 60,
43
- bitrate: 2000000, // 2Mbps
44
- packetCount: 2000,
45
- });
234
+ ### RecordingStopResult
46
235
 
47
- // Partial configuration (merges with defaults)
48
- const result = await transcodeVideo(videoBlob, {
49
- width: 640,
50
- height: 480,
51
- });
236
+ ```typescript
237
+ interface RecordingStopResult {
238
+ recordingId: string;
239
+ uploadUrl: string;
240
+ blob: Blob;
241
+ }
52
242
  ```
53
243
 
54
- ## Configuration
244
+ ### SourceType
245
+
246
+ ```typescript
247
+ type SourceType = 'camera' | 'screen';
248
+ ```
55
249
 
56
- The default configuration is:
250
+ ### RecordingState
57
251
 
58
252
  ```typescript
59
- {
60
- format: 'mp4', // Always MP4 output
61
- fps: 30, // 30 frames per second
62
- width: 1280, // 1280 pixels
63
- height: 720, // 720 pixels
64
- bitrate: 500000, // 500kbps
65
- audioCodec: 'aac', // AAC audio codec
66
- preset: 'medium', // Medium quality preset
67
- packetCount: 1200, // Maximum packet count for video track
253
+ type RecordingState = 'idle' | 'countdown' | 'recording';
254
+ ```
255
+
256
+ ### AvailableDevices
257
+
258
+ ```typescript
259
+ interface AvailableDevices {
260
+ video: MediaDeviceInfo[];
261
+ audio: MediaDeviceInfo[];
68
262
  }
69
263
  ```
70
264
 
71
- ### Configuration Options
265
+ ### CameraConstraints
72
266
 
73
- - `format`: Output format (always `'mp4'`)
74
- - `fps`: Target frame rate in frames per second
75
- - `width`: Target video width in pixels
76
- - `height`: Target video height in pixels
77
- - `bitrate`: Target video bitrate in bits per second
78
- - `audioCodec`: Audio codec to use (always `'aac'`)
79
- - `preset`: Quality preset (always `'medium'`)
80
- - `packetCount`: Maximum packet count for video track metadata (optimization hint)
267
+ ```typescript
268
+ interface CameraConstraints {
269
+ width?: number | { ideal?: number; min?: number; max?: number };
270
+ height?: number | { ideal?: number; min?: number; max?: number };
271
+ frameRate?: number | { ideal?: number; min?: number; max?: number };
272
+ }
273
+ ```
81
274
 
82
- ## API Reference
275
+ ## Usage Examples
83
276
 
84
- ### `transcodeVideo(input, config?)`
277
+ ### Basic Recording Workflow
85
278
 
86
- Transcodes a video file to MP4 format.
279
+ ```typescript
280
+ import { VidtreoRecorder } from '@vidtreo/recorder';
281
+
282
+ const recorder = new VidtreoRecorder({
283
+ apiKey: 'your-api-key',
284
+ apiUrl: 'https://api.example.com',
285
+ onUploadComplete: (result) => {
286
+ console.log('Uploaded:', result.uploadUrl);
287
+ },
288
+ });
87
289
 
88
- **Parameters:**
89
- - `input`: `Blob | File | string` - Input video source (Blob, File, or file path string)
90
- - `config`: `Partial<TranscodeConfig>` - Optional configuration object (merges with defaults)
290
+ try {
291
+ await recorder.startPreview('camera');
292
+ await recorder.startRecording({}, 'camera');
293
+
294
+ setTimeout(async () => {
295
+ const result = await recorder.stopRecording();
296
+ console.log('Recording ID:', result.recordingId);
297
+ recorder.cleanup();
298
+ }, 10000);
299
+ } catch (error) {
300
+ console.error('Recording failed:', error);
301
+ recorder.cleanup();
302
+ }
303
+ ```
91
304
 
92
- **Returns:** `Promise<TranscodeResult>`
305
+ ### Recording with Maximum Time Limit
306
+
307
+ ```typescript
308
+ const recorder = new VidtreoRecorder({
309
+ apiKey: 'your-api-key',
310
+ apiUrl: 'https://api.example.com',
311
+ maxRecordingTime: 300000,
312
+ onRecordingStop: () => {
313
+ console.log('Recording stopped automatically after 5 minutes');
314
+ },
315
+ });
93
316
 
94
- **Throws:** `Error` if transcoding fails or input is invalid
317
+ await recorder.startRecording({}, 'camera');
318
+ ```
95
319
 
96
- ### `TranscodeResult`
320
+ ### Recording with Source Switching
97
321
 
98
322
  ```typescript
99
- interface TranscodeResult {
100
- buffer: ArrayBuffer; // Transcoded video as ArrayBuffer
101
- blob: Blob; // Transcoded video as Blob
102
- }
323
+ const recorder = new VidtreoRecorder({
324
+ apiKey: 'your-api-key',
325
+ apiUrl: 'https://api.example.com',
326
+ enableSourceSwitching: true,
327
+ maxRecordingTime: 600000,
328
+ });
329
+
330
+ await recorder.startRecording({}, 'camera');
331
+
332
+ setTimeout(async () => {
333
+ await recorder.switchSource('screen');
334
+ }, 5000);
335
+
336
+ setTimeout(async () => {
337
+ await recorder.switchSource('camera');
338
+ }, 10000);
339
+
340
+ setTimeout(async () => {
341
+ const result = await recorder.stopRecording();
342
+ recorder.cleanup();
343
+ }, 15000);
103
344
  ```
104
345
 
105
- ### `DEFAULT_TRANSCODE_CONFIG`
346
+ **Note:** When `maxRecordingTime` is set, the recording will automatically stop when the time limit is reached, even if the timeout callbacks are still pending. The `onRecordingStop` callback will be invoked when the maximum time is reached.
106
347
 
107
- Default configuration object. Can be imported and used as a base for custom configurations.
348
+ ### Recording with Mute Control
108
349
 
109
- ## Supported Input Formats
350
+ ```typescript
351
+ const recorder = new VidtreoRecorder({
352
+ apiKey: 'your-api-key',
353
+ apiUrl: 'https://api.example.com',
354
+ });
110
355
 
111
- The package supports all formats supported by mediabunny:
112
- - MP4 (.mp4, .m4v)
113
- - WebM (.webm)
114
- - QuickTime (.mov)
115
- - Matroska (.mkv)
116
- - OGG (.ogv)
117
- - And more...
356
+ await recorder.startRecording({}, 'camera');
118
357
 
119
- ## Bun Optimizations
358
+ recorder.muteAudio();
359
+ setTimeout(() => recorder.unmuteAudio(), 5000);
360
+ setTimeout(() => recorder.toggleMute(), 10000);
361
+
362
+ setTimeout(async () => {
363
+ await recorder.stopRecording();
364
+ recorder.cleanup();
365
+ }, 15000);
366
+ ```
120
367
 
121
- This package leverages Bun's native capabilities:
122
- - Uses `Bun.file()` for efficient file reading when file paths are provided
123
- - Optimized for Bun's runtime and test runner
124
- - Native ArrayBuffer handling
368
+ ### Recording with Pause and Resume
369
+
370
+ ```typescript
371
+ const recorder = new VidtreoRecorder({
372
+ apiKey: 'your-api-key',
373
+ apiUrl: 'https://api.example.com',
374
+ });
125
375
 
126
- ## Examples
376
+ await recorder.startRecording({}, 'camera');
127
377
 
128
- ### Transcode and Save to File (Bun)
378
+ setTimeout(() => recorder.pauseRecording(), 3000);
379
+ setTimeout(() => recorder.resumeRecording(), 6000);
380
+
381
+ setTimeout(async () => {
382
+ await recorder.stopRecording();
383
+ recorder.cleanup();
384
+ }, 10000);
385
+ ```
386
+
387
+ ### Recording with Upload Progress
129
388
 
130
389
  ```typescript
131
- import { transcodeVideo } from '@vidtreo/recorder';
132
- import { writeFile } from 'fs/promises';
390
+ const recorder = new VidtreoRecorder({
391
+ apiKey: 'your-api-key',
392
+ apiUrl: 'https://api.example.com',
393
+ onUploadProgress: (progress) => {
394
+ const percentage = Math.round(progress * 100);
395
+ console.log(`Upload: ${percentage}%`);
396
+ },
397
+ onUploadComplete: (result) => {
398
+ console.log('Upload complete:', result.uploadUrl);
399
+ },
400
+ onUploadError: (error) => {
401
+ console.error('Upload failed:', error.message);
402
+ },
403
+ });
133
404
 
134
- const result = await transcodeVideo('/path/to/input.mp4');
135
- await Bun.write('/path/to/output.mp4', result.buffer);
405
+ await recorder.startRecording({}, 'camera');
406
+ setTimeout(async () => {
407
+ await recorder.stopRecording();
408
+ recorder.cleanup();
409
+ }, 5000);
136
410
  ```
137
411
 
138
- ### Transcode with Progress Tracking
412
+ ### Recording with Custom Metadata
139
413
 
140
414
  ```typescript
141
- import { transcodeVideo } from '@vidtreo/recorder';
415
+ const recorder = new VidtreoRecorder({
416
+ apiKey: 'your-api-key',
417
+ apiUrl: 'https://api.example.com',
418
+ userMetadata: {
419
+ userId: 'user-123',
420
+ sessionId: 'session-456',
421
+ projectId: 'project-789',
422
+ },
423
+ });
142
424
 
143
- console.log('Starting transcoding...');
144
- const result = await transcodeVideo(videoBlob);
145
- console.log('Transcoding complete!');
146
- console.log(`Output size: ${result.buffer.byteLength} bytes`);
425
+ await recorder.startRecording({}, 'camera');
426
+ setTimeout(async () => {
427
+ await recorder.stopRecording();
428
+ recorder.cleanup();
429
+ }, 5000);
147
430
  ```
148
431
 
149
- ## Web Component
432
+ ### Recording with Countdown
150
433
 
151
- This package also includes a standalone web component (`<vidtreo-recorder>`) that can be used in any HTML page without requiring a build step or framework.
434
+ ```typescript
435
+ const recorder = new VidtreoRecorder({
436
+ apiKey: 'your-api-key',
437
+ apiUrl: 'https://api.example.com',
438
+ countdownDuration: 3000,
439
+ });
152
440
 
153
- ### Building the Web Component
441
+ await recorder.startPreview('camera');
442
+ await recorder.startRecording({}, 'camera');
443
+ setTimeout(async () => {
444
+ await recorder.stopRecording();
445
+ recorder.cleanup();
446
+ }, 10000);
447
+ ```
154
448
 
155
- To build the web component, run:
449
+ ### Device Selection
156
450
 
157
- ```bash
158
- bun run build:wc
451
+ ```typescript
452
+ const recorder = new VidtreoRecorder({
453
+ apiKey: 'your-api-key',
454
+ apiUrl: 'https://api.example.com',
455
+ });
456
+
457
+ const devices = await recorder.getAvailableDevices();
458
+ console.log('Cameras:', devices.video.map(d => d.label));
459
+ console.log('Microphones:', devices.audio.map(d => d.label));
460
+
461
+ await recorder.startRecording({}, 'camera');
462
+ setTimeout(async () => {
463
+ await recorder.stopRecording();
464
+ recorder.cleanup();
465
+ }, 5000);
466
+ ```
467
+
468
+ ### Recording State Monitoring
469
+
470
+ ```typescript
471
+ const recorder = new VidtreoRecorder({
472
+ apiKey: 'your-api-key',
473
+ apiUrl: 'https://api.example.com',
474
+ onRecordingStart: () => {
475
+ console.log('Recording started');
476
+ },
477
+ onRecordingStop: () => {
478
+ console.log('Recording stopped');
479
+ },
480
+ });
481
+
482
+ await recorder.startRecording({}, 'camera');
483
+
484
+ const checkState = setInterval(() => {
485
+ const state = recorder.getRecordingState();
486
+ const isPaused = recorder.isPaused();
487
+ const isMuted = recorder.isMuted();
488
+ console.log(`State: ${state}, Paused: ${isPaused}, Muted: ${isMuted}`);
489
+ }, 1000);
490
+
491
+ setTimeout(async () => {
492
+ clearInterval(checkState);
493
+ await recorder.stopRecording();
494
+ recorder.cleanup();
495
+ }, 10000);
159
496
  ```
160
497
 
161
- This will create two files in `dist/wc/`:
162
- - `vidtreo-recorder.js` - The web component JavaScript bundle
163
- - `vidtreo-recorder.css` - The Tailwind CSS stylesheet
498
+ ### Screen Recording
164
499
 
165
- ### Web Component Usage
500
+ ```typescript
501
+ const recorder = new VidtreoRecorder({
502
+ apiKey: 'your-api-key',
503
+ apiUrl: 'https://api.example.com',
504
+ enableSourceSwitching: true,
505
+ });
166
506
 
167
- #### Basic Usage
507
+ await recorder.startPreview('screen');
508
+ await recorder.startRecording({}, 'screen');
509
+ setTimeout(async () => {
510
+ await recorder.stopRecording();
511
+ recorder.cleanup();
512
+ }, 30000);
513
+ ```
168
514
 
169
- Include both the CSS and JS files in your HTML:
515
+ ### Error Handling
170
516
 
171
- ```html
172
- <!DOCTYPE html>
173
- <html lang="en">
174
- <head>
175
- <meta charset="UTF-8">
176
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
177
- <title>My App</title>
178
- <!-- Include the CSS file -->
179
- <link rel="stylesheet" href="./dist/wc/vidtreo-recorder.css">
180
- </head>
181
- <body>
182
- <!-- Use the web component -->
183
- <vidtreo-recorder></vidtreo-recorder>
517
+ ```typescript
518
+ const recorder = new VidtreoRecorder({
519
+ apiKey: 'your-api-key',
520
+ apiUrl: 'https://api.example.com',
521
+ onError: (error) => {
522
+ console.error('Stream error:', error.message);
523
+ },
524
+ onUploadError: (error) => {
525
+ console.error('Upload error:', error.message);
526
+ },
527
+ });
184
528
 
185
- <!-- Include the JS file -->
186
- <script src="./dist/wc/vidtreo-recorder.js"></script>
187
- </body>
188
- </html>
529
+ try {
530
+ await recorder.startRecording({}, 'camera');
531
+ const result = await recorder.stopRecording();
532
+ console.log('Success:', result.uploadUrl);
533
+ } catch (error) {
534
+ console.error('Recording error:', error);
535
+ } finally {
536
+ recorder.cleanup();
537
+ }
189
538
  ```
190
539
 
191
- #### CDN Usage
540
+ ### Recording with Disabled Features
541
+
542
+ ```typescript
543
+ const recorder = new VidtreoRecorder({
544
+ apiKey: 'your-api-key',
545
+ apiUrl: 'https://api.example.com',
546
+ enableMute: false,
547
+ enablePause: false,
548
+ enableSourceSwitching: false,
549
+ enableDeviceChange: false,
550
+ });
192
551
 
193
- After uploading the files to your CDN, reference them:
552
+ await recorder.startRecording({}, 'camera');
194
553
 
195
- ```html
196
- <link rel="stylesheet" href="https://your-cdn.com/vidtreo-recorder.css">
197
- <script src="https://your-cdn.com/vidtreo-recorder.js"></script>
554
+ try {
555
+ recorder.muteAudio();
556
+ } catch (error) {
557
+ console.error('Mute is disabled:', error.message);
558
+ }
198
559
 
199
- <vidtreo-recorder></vidtreo-recorder>
560
+ try {
561
+ recorder.pauseRecording();
562
+ } catch (error) {
563
+ console.error('Pause is disabled:', error.message);
564
+ }
565
+
566
+ setTimeout(async () => {
567
+ await recorder.stopRecording();
568
+ recorder.cleanup();
569
+ }, 10000);
200
570
  ```
201
571
 
202
- ### Web Component Features
572
+ ## Web Component Usage
203
573
 
204
- - Drag and drop video file upload
205
- - Click to upload video files
206
- - Real-time transcoding progress
207
- - Download transcoded MP4 files
208
- - Play transcoded videos in a new window
209
- - Error handling and validation
574
+ The web component is available in a separate package: [@vidtreo/recorder-wc](../recorder-wc/README.md)
210
575
 
211
- ### Web Component Development
576
+ For web component installation, usage, and examples, please refer to the [@vidtreo/recorder-wc documentation](../recorder-wc/README.md).
212
577
 
213
- To develop the web component with hot reload:
578
+ ## Advanced Usage
214
579
 
215
- ```bash
216
- bun run dev:wc
580
+ ### Low-Level APIs
581
+
582
+ For advanced use cases, the package exports lower-level APIs that provide more granular control:
583
+
584
+ #### Transcoding
585
+
586
+ ```typescript
587
+ import { transcodeVideo, DEFAULT_TRANSCODE_CONFIG } from '@vidtreo/recorder';
588
+
589
+ const videoBlob = new Blob([videoData], { type: 'video/mp4' });
590
+ const result = await transcodeVideo(videoBlob, {
591
+ width: 1920,
592
+ height: 1080,
593
+ fps: 60,
594
+ bitrate: 2000000,
595
+ });
596
+
597
+ console.log('Transcoded size:', result.buffer.byteLength);
598
+ ```
599
+
600
+ #### RecorderController
601
+
602
+ For fine-grained control over the recording process:
603
+
604
+ ```typescript
605
+ import { RecorderController } from '@vidtreo/recorder';
606
+
607
+ const controller = new RecorderController({
608
+ recording: {
609
+ onStateChange: (state) => console.log('State:', state),
610
+ },
611
+ });
612
+
613
+ await controller.initialize({
614
+ apiKey: 'your-api-key',
615
+ backendUrl: 'https://api.example.com',
616
+ });
617
+ ```
618
+
619
+ #### Stream Management
620
+
621
+ ```typescript
622
+ import { CameraStreamManager } from '@vidtreo/recorder';
623
+
624
+ const streamManager = new CameraStreamManager();
625
+ await streamManager.startStream();
626
+ const stream = streamManager.getStream();
217
627
  ```
218
628
 
219
- ### Web Component File Structure
629
+ ## Configuration
630
+
631
+ Video transcoding configuration is managed through your backend API. The recorder fetches configuration using the provided `apiKey` and `apiUrl`. Default transcoding settings include:
632
+
633
+ - Format: MP4
634
+ - Frame rate: 30 fps
635
+ - Resolution: 1280x720
636
+ - Bitrate: 500 kbps
637
+ - Audio codec: AAC
638
+ - Preset: Medium quality
639
+
640
+ These defaults are used when backend configuration is unavailable or during initialization.
641
+
642
+ ## Browser Compatibility
643
+
644
+ This package requires modern browser APIs for full functionality. The most critical requirement is support for the **WebCodecs API**, which enables real-time MP4 transcoding.
645
+
646
+ ### Full Support (All Features)
647
+
648
+ The following browsers support all features including real-time MP4 transcoding:
649
+
650
+ - **Chrome 94+** - Full support for all features
651
+ - **Edge (Chromium) 94+** - Full support, same as Chrome
652
+ - **Opera 80+** - Full support, Chromium-based
653
+ - **Brave 1.30+** - Full support, Chromium-based
654
+ - **Vivaldi 5.0+** - Full support, Chromium-based
655
+ - **Firefox 130+** - Full WebCodecs support
656
+ - **Safari (macOS/iOS) 26.0+** - Full WebCodecs support
657
+
658
+ ### Partial Support (Core Features Only)
220
659
 
221
- - `src/components/vidtreo-recorder.wc.ts` - Web component source code
222
- - `src/styles/tailwind.css` - Tailwind CSS source
223
- - `vite.wc.config.ts` - Vite configuration for web component build
224
- - `dist/wc/` - Build output directory
660
+ The following browsers support core recording features but may have limitations:
661
+
662
+ - **Firefox 76-129** - AudioWorklet supported, but WebCodecs not available. Real-time MP4 transcoding unavailable; falls back to MediaRecorder (WebM format)
663
+ - **Safari (macOS/iOS) 16.4-25.x** - Partial WebCodecs support; some codecs may not be available
664
+
665
+ ### Required Browser APIs
666
+
667
+ - **WebCodecs API** - Required for real-time MP4 transcoding (via mediabunny)
668
+ - **OffscreenCanvas** - Required for video frame processing
669
+ - **AudioWorklet** - Required for audio processing and level analysis
670
+ - **MediaRecorder API** - Used as fallback recording method
671
+ - **Screen Capture API** (`getDisplayMedia`) - Required for screen recording
672
+ - **MediaDevices API** (`getUserMedia`) - Required for camera/microphone access
673
+ - **IndexedDB** - Required for persistent upload queue
674
+ - **Storage API** - Required for storage quota management
675
+
676
+ ### Feature Support by Browser
677
+
678
+ | Feature | Chrome 94+ | Edge 94+ | Firefox 130+ | Safari 26.0+ | Firefox 76-129 | Safari 16.4-25.x |
679
+ |---------|------------|---------|--------------|--------------|---------------|------------------|
680
+ | Camera Recording | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
681
+ | Screen Recording | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
682
+ | Real-time MP4 Transcoding | ✅ | ✅ | ✅ | ✅ | ❌ (WebM) | ⚠️ (Partial) |
683
+ | Audio Level Analysis | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
684
+ | Source Switching | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
685
+ | Device Switching | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
686
+ | Persistent Upload Queue | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
687
+
688
+ ### Unsupported Browsers
689
+
690
+ - Internet Explorer (all versions)
691
+ - Firefox < 76 (missing AudioWorklet)
692
+ - Safari < 14.1 (missing AudioWorklet)
693
+ - Safari < 16.4 (missing OffscreenCanvas and WebCodecs)
694
+ - Edge Legacy (pre-Chromium)
695
+ - Chrome < 94 (missing WebCodecs)
696
+
697
+ ### Mobile Browser Support
698
+
699
+ - **Chrome Android 94+** - Full support
700
+ - **Samsung Internet 18.0+** - Full support
701
+ - **Firefox Android 130+** - Full support
702
+ - **Safari iOS 16.4+** - Partial support (WebCodecs partial)
703
+ - **Safari iOS 26.0+** - Full support
704
+
705
+ ### Important Notes
706
+
707
+ 1. **HTTPS Required**: Media capture APIs require HTTPS (or localhost) in most browsers
708
+ 2. **User Permissions**: Camera, microphone, and screen capture require explicit user permission
709
+ 3. **Automatic Fallback**: The package automatically falls back to MediaRecorder when WebCodecs is unavailable (produces WebM instead of MP4)
710
+ 4. **Feature Detection**: The package includes feature detection and gracefully degrades functionality when APIs are unavailable
711
+
712
+ For detailed browser compatibility information, API requirements, and known limitations, see [BROWSER_COMPATIBILITY.md](./BROWSER_COMPATIBILITY.md).
225
713
 
226
714
  ## License
227
715
 
228
716
  MIT
229
-