@napi-rs/webcodecs 1.2.0 → 1.3.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 +105 -18
- package/index.d.ts +271 -215
- package/index.js +82 -237
- package/package.json +42 -33
package/README.md
CHANGED
|
@@ -7,7 +7,8 @@ WebCodecs API implementation for Node.js using FFmpeg, built with [NAPI-RS](http
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- **W3C WebCodecs API compliant** - Full implementation of the WebCodecs specification with native `DOMException` errors
|
|
10
|
-
- **Video encoding/decoding** - H.264, H.265, VP8, VP9, AV1
|
|
10
|
+
- **Video encoding/decoding** - H.264, H.265 (with Alpha), VP8, VP9 (with Alpha), AV1
|
|
11
|
+
- **Encoding Alpha channel** - VP9 and HEVC alpha encoding/decoding with transparency support (See [canvas-to-video.js](example/canvas-to-video.js) example and [video.html](example/video.html))
|
|
11
12
|
- **Audio encoding/decoding** - AAC, Opus, MP3, FLAC, Vorbis, PCM variants
|
|
12
13
|
- **Container muxing/demuxing** - MP4, WebM, MKV containers with seeking support
|
|
13
14
|
- **Image decoding** - JPEG, PNG, WebP, GIF, BMP, AVIF, JPEG XL
|
|
@@ -339,16 +340,28 @@ frame.close()
|
|
|
339
340
|
|
|
340
341
|
### Video
|
|
341
342
|
|
|
342
|
-
| Codec | Codec String | Encoding | Decoding |
|
|
343
|
-
| ----- | ----------------------- | -------- | -------- |
|
|
344
|
-
| H.264 | `avc1.*` | ✅ | ✅ |
|
|
345
|
-
| H.265 | `hev1.*`, `hvc1.*` | ✅ | ✅ |
|
|
346
|
-
| VP8 | `vp8` | ✅ | ✅ |
|
|
347
|
-
| VP9 | `vp09.*`, `vp9` | ✅ | ✅ |
|
|
348
|
-
| AV1 | `av01.*`, `av01`, `av1` | ✅ | ✅ |
|
|
343
|
+
| Codec | Codec String | Encoding | Encoding Alpha | Decoding | Decoding Alpha |
|
|
344
|
+
| ----- | ----------------------- | -------- | -------------- | -------- | -------------- |
|
|
345
|
+
| H.264 | `avc1.*` | ✅ | 🙅🏻♀️ | ✅ | 🙅🏻♀️ |
|
|
346
|
+
| H.265 | `hev1.*`, `hvc1.*` | ✅ | ✅¹ | ✅ | ✅ |
|
|
347
|
+
| VP8 | `vp8` | ✅ | 🙅🏻♀️ | ✅ | 🙅🏻♀️ |
|
|
348
|
+
| VP9 | `vp09.*`, `vp9` | ✅ | ✅ | ✅ | ✅ |
|
|
349
|
+
| AV1 | `av01.*`, `av01`, `av1` | ✅ | 🙅🏻♀️ | ✅ | 🙅🏻♀️ |
|
|
349
350
|
|
|
350
351
|
**Note:** Short form codec strings (`vp9`, `av01`, `av1`) are accepted for compatibility with browser implementations.
|
|
351
352
|
|
|
353
|
+
¹ **HEVC Alpha Encoding Limitations:**
|
|
354
|
+
|
|
355
|
+
- Requires software encoder (libx265) - set `hardwareAcceleration: 'prefer-software'`
|
|
356
|
+
- Hardware encoders (VideoToolbox, NVENC, VAAPI, QSV) do not support alpha
|
|
357
|
+
- Only YUVA420P (8-bit) and YUVA420P10 (10-bit Main 10 profile) pixel formats supported
|
|
358
|
+
|
|
359
|
+
**Legend:**
|
|
360
|
+
|
|
361
|
+
- ✅ Feature supported
|
|
362
|
+
- 🙅🏻♀️ Feature not supported by codec format
|
|
363
|
+
- ❓ Feature supported by codec format but not yet implemented
|
|
364
|
+
|
|
352
365
|
### Audio
|
|
353
366
|
|
|
354
367
|
| Codec | Codec String | Encoding | Decoding |
|
|
@@ -362,15 +375,15 @@ frame.close()
|
|
|
362
375
|
|
|
363
376
|
### Image
|
|
364
377
|
|
|
365
|
-
| Format | MIME Type | Decoding |
|
|
366
|
-
| ------- | ------------ | -------- |
|
|
367
|
-
| JPEG | `image/jpeg` | ✅ |
|
|
368
|
-
| PNG | `image/png` | ✅ |
|
|
369
|
-
| WebP | `image/webp` | ✅ |
|
|
370
|
-
| GIF | `image/gif` | ✅ |
|
|
371
|
-
| BMP | `image/bmp` | ✅ |
|
|
372
|
-
| AVIF | `image/avif` | ✅ |
|
|
373
|
-
| JPEG XL | `image/jxl` | ✅ |
|
|
378
|
+
| Format | MIME Type | Decoding |
|
|
379
|
+
| ------- | ------------ | -------- |
|
|
380
|
+
| JPEG | `image/jpeg` | ✅ |
|
|
381
|
+
| PNG | `image/png` | ✅ |
|
|
382
|
+
| WebP | `image/webp` | ✅ |
|
|
383
|
+
| GIF | `image/gif` | ✅ |
|
|
384
|
+
| BMP | `image/bmp` | ✅ |
|
|
385
|
+
| AVIF | `image/avif` | ✅ |
|
|
386
|
+
| JPEG XL | `image/jxl` | ✅ |
|
|
374
387
|
|
|
375
388
|
### Containers
|
|
376
389
|
|
|
@@ -441,14 +454,63 @@ encoder.configure({
|
|
|
441
454
|
hardwareAcceleration: 'prefer-hardware', // 'no-preference' | 'prefer-hardware' | 'prefer-software'
|
|
442
455
|
// Latency mode affects encoder tuning
|
|
443
456
|
latencyMode: 'realtime', // 'quality' | 'realtime'
|
|
457
|
+
// Alpha channel preservation (VP9 and HEVC only)
|
|
458
|
+
alpha: 'discard', // 'keep' | 'discard' (default: 'discard')
|
|
444
459
|
})
|
|
445
460
|
```
|
|
446
461
|
|
|
447
462
|
- `latencyMode: 'realtime'` - Enables low-latency encoder options (smaller GOP, no B-frames, fast presets)
|
|
448
463
|
- `latencyMode: 'quality'` - Enables quality-focused options (larger GOP, B-frames, lookahead)
|
|
464
|
+
- `alpha: 'keep'` - Preserves alpha channel (VP9 and HEVC only). For HEVC, requires `hardwareAcceleration: 'prefer-software'`
|
|
449
465
|
|
|
450
466
|
The encoder automatically applies optimal settings for each hardware encoder based on the latency mode.
|
|
451
467
|
|
|
468
|
+
### Alpha Channel Encoding
|
|
469
|
+
|
|
470
|
+
Encode video with transparency using VP9 or HEVC:
|
|
471
|
+
|
|
472
|
+
```typescript
|
|
473
|
+
import { VideoEncoder, VideoFrame } from '@napi-rs/webcodecs'
|
|
474
|
+
|
|
475
|
+
const encoder = new VideoEncoder({
|
|
476
|
+
output: (chunk, metadata) => {
|
|
477
|
+
console.log(`Alpha chunk: ${chunk.byteLength} bytes`)
|
|
478
|
+
},
|
|
479
|
+
error: (e) => console.error(e),
|
|
480
|
+
})
|
|
481
|
+
|
|
482
|
+
// VP9 alpha - works with hardware or software
|
|
483
|
+
encoder.configure({
|
|
484
|
+
codec: 'vp09.00.10.08',
|
|
485
|
+
width: 1920,
|
|
486
|
+
height: 1080,
|
|
487
|
+
alpha: 'keep',
|
|
488
|
+
})
|
|
489
|
+
|
|
490
|
+
// HEVC alpha - requires software encoder
|
|
491
|
+
encoder.configure({
|
|
492
|
+
codec: 'hev1.1.6.L93.B0',
|
|
493
|
+
width: 1920,
|
|
494
|
+
height: 1080,
|
|
495
|
+
alpha: 'keep',
|
|
496
|
+
hardwareAcceleration: 'prefer-software', // Required for HEVC alpha
|
|
497
|
+
})
|
|
498
|
+
|
|
499
|
+
// Create frame with alpha channel (I420A format)
|
|
500
|
+
const width = 1920
|
|
501
|
+
const height = 1080
|
|
502
|
+
const frameData = new Uint8Array(width * height * 1.5 + width * height) // Y + U + V + A
|
|
503
|
+
const frame = new VideoFrame(frameData, {
|
|
504
|
+
format: 'I420A',
|
|
505
|
+
codedWidth: width,
|
|
506
|
+
codedHeight: height,
|
|
507
|
+
timestamp: 0,
|
|
508
|
+
})
|
|
509
|
+
|
|
510
|
+
encoder.encode(frame)
|
|
511
|
+
frame.close()
|
|
512
|
+
```
|
|
513
|
+
|
|
452
514
|
## Limitations
|
|
453
515
|
|
|
454
516
|
### Scalable Video Coding (SVC)
|
|
@@ -533,6 +595,31 @@ ImageDecoder supports all W3C spec options:
|
|
|
533
595
|
|
|
534
596
|
- **ImageDecoder GIF animation**: FFmpeg may return only the first frame. Use `VideoDecoder` with GIF codec for full animation.
|
|
535
597
|
|
|
598
|
+
### Per-Frame Quantizer Control
|
|
599
|
+
|
|
600
|
+
Per-frame quantizer control is available for VP9 and AV1 when using `bitrateMode: 'quantizer'`:
|
|
601
|
+
|
|
602
|
+
```typescript
|
|
603
|
+
encoder.configure({
|
|
604
|
+
codec: 'vp09.00.10.08',
|
|
605
|
+
width: 1920,
|
|
606
|
+
height: 1080,
|
|
607
|
+
bitrateMode: 'quantizer',
|
|
608
|
+
})
|
|
609
|
+
|
|
610
|
+
// Per-frame QP control (0-255 range per W3C WebCodecs spec)
|
|
611
|
+
encoder.encode(frame, { vp9: { quantizer: 128 } })
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
| Codec | Per-Frame QP | Notes |
|
|
615
|
+
| ----- | ------------ | ------------------------------------------------------------ |
|
|
616
|
+
| VP9 | ✅ Works | Uses FFmpeg's dynamic qmax update mechanism |
|
|
617
|
+
| AV1 | ❌ No effect | FFmpeg's libaom wrapper doesn't support dynamic qmax updates |
|
|
618
|
+
| H.264 | ✅ Works | Uses FFmpeg's frame quality mechanism (0-51 range) |
|
|
619
|
+
| H.265 | ✅ Works | Uses FFmpeg's frame quality mechanism (0-51 range) |
|
|
620
|
+
|
|
621
|
+
**Note:** The 0-255 quantizer range for VP9/AV1 aligns with [Chromium's WebCodecs implementation](https://chromium-review.googlesource.com/c/chromium/src/+/7204065). Internally, values are converted to the 0-63 encoder range using `q_index / 4`.
|
|
622
|
+
|
|
536
623
|
## Logging
|
|
537
624
|
|
|
538
625
|
This library uses Rust's `tracing` crate for structured logging. Enable logging via the `WEBCODECS_LOG` environment variable:
|
|
@@ -618,4 +705,4 @@ cargo clippy
|
|
|
618
705
|
|
|
619
706
|
## License
|
|
620
707
|
|
|
621
|
-
MIT
|
|
708
|
+
MIT
|