@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.
Files changed (4) hide show
  1. package/README.md +105 -18
  2. package/index.d.ts +271 -215
  3. package/index.js +82 -237
  4. 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 | Notes |
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` | ✅ | Not available on Windows arm64 |
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