webcodecs-utils 0.1.3 → 0.1.4

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
@@ -11,15 +11,15 @@ npm install webcodecs-utils
11
11
  ## Quick Start
12
12
 
13
13
  ```typescript
14
- import { getBitrate, GPUDrawImage, extractChannels, MP4Demuxer } from 'webcodecs-utils';
14
+ import { getBitrate, GPUFrameRenderer, extractChannels, MP4Demuxer } from 'webcodecs-utils';
15
15
 
16
- // Calculate optimal bitrate
17
- const bitrate = getBitrate(1920, 1080, 30, 'good');
16
+ // Calculate optimal bitrate (defaults to 30fps)
17
+ const bitrate = getBitrate(1920, 1080);
18
18
 
19
19
  // Zero-copy video rendering with WebGPU
20
- const renderer = new GPUDrawImage(canvas);
20
+ const renderer = new GPUFrameRenderer(canvas);
21
21
  await renderer.init();
22
- renderer.drawImage(videoFrame, 0, 0);
22
+ renderer.drawImage(videoFrame);
23
23
 
24
24
  // Extract audio channels
25
25
  const decoder = new AudioDecoder({
@@ -45,14 +45,14 @@ const videoChunks = await demuxer.extractSegment('video', 0, 10);
45
45
  Calculate optimal bitrate for video encoding based on resolution, framerate, and quality.
46
46
 
47
47
  - 📄 [Source](./src/video/get-bitrate.ts)
48
- - 🎮 [Demo](./demos/bitrate-demo.html)
48
+ - 🎮 [Demo](./demos/get-bitrate.html)
49
49
 
50
50
  ```typescript
51
51
  function getBitrate(
52
52
  width: number,
53
53
  height: number,
54
- fps: number,
55
- quality?: 'low' | 'good' | 'high' | 'very-high'
54
+ fps?: number, // default: 30
55
+ quality?: 'low' | 'good' | 'high' | 'very-high' // default: 'good'
56
56
  ): number
57
57
  ```
58
58
 
@@ -60,7 +60,7 @@ function getBitrate(
60
60
  Generate proper codec strings (avc1, vp09, etc.) with correct profile/level for VideoEncoder configuration.
61
61
 
62
62
  - 📄 [Source](./src/video/get-codec-string.ts)
63
- - 🎮 [Demo](./demos/codec-string-demo.html)
63
+ - 🎮 [Demo](./demos/get-codec-string.html)
64
64
 
65
65
  ```typescript
66
66
  function getCodecString(
@@ -71,21 +71,23 @@ function getCodecString(
71
71
  ): string
72
72
  ```
73
73
 
74
- #### **GPUDrawImage**
74
+ #### **GPUFrameRenderer**
75
75
  Zero-copy video frame rendering using WebGPU importExternalTexture, with fallback to ImageBitmapRenderer.
76
76
 
77
- - 📄 [Source](./src/video/gpu-draw-image.ts)
78
- - 🎮 [Demo](./demos/gpu-renderer-demo.html)
77
+ - 📄 [Source](./src/video/gpu-renderer.ts)
78
+ - 🎮 [Demo](./demos/gpu-renderer.html)
79
79
 
80
80
  ```typescript
81
- class GPUDrawImage {
81
+ class GPUFrameRenderer {
82
82
  constructor(canvas: HTMLCanvasElement | OffscreenCanvas, options?: {
83
83
  filterMode?: 'linear' | 'bicubic'
84
84
  })
85
85
 
86
86
  async init(): Promise<void>
87
- drawImage(videoFrame: VideoFrame, dx?: number, dy?: number): void
87
+ drawImage(videoFrame: VideoFrame): void
88
88
  getMode(): 'webgpu' | 'bitmap' | null
89
+ getFilterMode(): 'linear' | 'bicubic'
90
+ setFilterMode(mode: 'linear' | 'bicubic'): void
89
91
  destroy(): void
90
92
  }
91
93
  ```
@@ -98,7 +100,7 @@ Extract and de-interleave audio channels from AudioData into Float32Array[].
98
100
  Handles both planar (f32-planar) and interleaved (f32) audio formats automatically. Returns an array of Float32Array buffers, one per channel (e.g., [left, right] for stereo).
99
101
 
100
102
  - 📄 [Source](./src/audio/extract-channels.ts)
101
- - 🎮 [Demo](./demos/audio-channels-demo.html)
103
+ - 🎮 [Demo](./demos/extract-channels.html)
102
104
 
103
105
  ```typescript
104
106
  function extractChannels(audioData: AudioData): Float32Array[]
@@ -119,8 +121,8 @@ for (let i = 0; i < leftChannel.length; i++) {
119
121
  #### **MP3Encoder**
120
122
  Encode AudioData to MP3 format using LameJS.
121
123
 
122
- - 📄 [Source](./src/audio/mp3-encoder.ts)
123
- - 🎮 [Demo](./demos/mp3-encoder-demo.html)
124
+ - 📄 [Source](./src/audio/mp3.ts)
125
+ - 🎮 [Demo](./demos/mp3-encoder.html)
124
126
 
125
127
  ```typescript
126
128
  class MP3Encoder {
@@ -132,16 +134,38 @@ class MP3Encoder {
132
134
 
133
135
  processBatch(audioData: AudioData): Uint8Array
134
136
  finish(): Blob
137
+ getEncodedSize(): number
135
138
  }
136
139
  ```
137
140
 
138
- ### Demux
141
+ #### **MP3Decoder**
142
+ Decode MP3 files to raw PCM samples or AudioData objects.
143
+
144
+ - 📄 [Source](./src/audio/mp3.ts)
145
+ - 🎮 [Demo](./demos/mp3-decoder.html)
146
+
147
+ ```typescript
148
+ class MP3Decoder {
149
+ constructor()
150
+
151
+ async initialize(): Promise<void>
152
+ async toSamples(mp3Buffer: ArrayBuffer): Promise<{
153
+ channels: Float32Array[],
154
+ sampleRate: number,
155
+ numberOfChannels: number
156
+ }>
157
+ async toAudioData(mp3Buffer: ArrayBuffer): Promise<AudioData[]>
158
+ async destroy(): Promise<void>
159
+ }
160
+ ```
161
+
162
+ ### Demux/Mux
139
163
 
140
164
  #### **MP4Demuxer**
141
165
  Parse MP4 files and extract EncodedVideoChunk/EncodedAudioChunk objects using MP4Box.
142
166
 
143
167
  - 📄 [Source](./src/demux/mp4-demuxer.ts)
144
- - 🎮 [Demo](./demos/mp4-demuxer-demo.html)
168
+ - 🎮 [Demo](./demos/mp4-demuxer.html)
145
169
 
146
170
  ```typescript
147
171
  class MP4Demuxer {
@@ -151,11 +175,14 @@ class MP4Demuxer {
151
175
  getTracks(): TrackData
152
176
  getVideoTrack(): VideoTrackData | undefined
153
177
  getAudioTrack(): AudioTrackData | undefined
178
+ getVideoDecoderConfig(): VideoDecoderConfig | undefined
179
+ getAudioDecoderConfig(): AudioDecoderConfig | undefined
154
180
  async extractSegment(
155
181
  trackType: 'audio' | 'video',
156
182
  startTime: number,
157
183
  endTime: number
158
184
  ): Promise<EncodedVideoChunk[] | EncodedAudioChunk[]>
185
+ getInfo(): MP4Info
159
186
  }
160
187
  ```
161
188
 
@@ -174,7 +201,7 @@ const videoChunks = await demuxer.extractSegment('video', 0, 10);
174
201
 
175
202
  These utilities require:
176
203
  - **WebCodecs API** - Chrome 94+, Edge 94+, Safari 17.4+ (some features)
177
- - **WebGPU** (optional) - Chrome 113+, Edge 113+, Safari 18+ (for GPUDrawImage)
204
+ - **WebGPU** (optional) - Chrome 113+, Edge 113+, Safari 18+ (for GPUFrameRenderer)
178
205
 
179
206
  All utilities include compatibility checks and graceful degradation where applicable.
180
207
 
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Fn=require("lamejs"),zi=require("mp4box");function Jn(e,t,i="good"){const n=e*t,d={low:.05,good:.08,high:.1,"very-high":.15},o=d[i]||d.good;return n*30*o}function En(e,t,i,n){const d=[{maxMacroblocks:99,maxBitrate:64e3,level:10},{maxMacroblocks:396,maxBitrate:192e3,level:11},{maxMacroblocks:396,maxBitrate:384e3,level:12},{maxMacroblocks:396,maxBitrate:768e3,level:13},{maxMacroblocks:396,maxBitrate:2e6,level:20},{maxMacroblocks:792,maxBitrate:4e6,level:21},{maxMacroblocks:1620,maxBitrate:4e6,level:22},{maxMacroblocks:1620,maxBitrate:1e7,level:30},{maxMacroblocks:3600,maxBitrate:14e6,level:31},{maxMacroblocks:5120,maxBitrate:2e7,level:32},{maxMacroblocks:8192,maxBitrate:2e7,level:40},{maxMacroblocks:8192,maxBitrate:5e7,level:41},{maxMacroblocks:8704,maxBitrate:5e7,level:42},{maxMacroblocks:22080,maxBitrate:135e6,level:50},{maxMacroblocks:36864,maxBitrate:24e7,level:51},{maxMacroblocks:36864,maxBitrate:24e7,level:52},{maxMacroblocks:139264,maxBitrate:24e7,level:60},{maxMacroblocks:139264,maxBitrate:48e7,level:61},{maxMacroblocks:139264,maxBitrate:8e8,level:62}],o=[{maxPictureSize:36864,maxBitrate:128e3,tier:"L",level:30},{maxPictureSize:122880,maxBitrate:15e5,tier:"L",level:60},{maxPictureSize:245760,maxBitrate:3e6,tier:"L",level:63},{maxPictureSize:552960,maxBitrate:6e6,tier:"L",level:90},{maxPictureSize:983040,maxBitrate:1e7,tier:"L",level:93},{maxPictureSize:2228224,maxBitrate:12e6,tier:"L",level:120},{maxPictureSize:2228224,maxBitrate:3e7,tier:"H",level:120},{maxPictureSize:2228224,maxBitrate:2e7,tier:"L",level:123},{maxPictureSize:2228224,maxBitrate:5e7,tier:"H",level:123},{maxPictureSize:8912896,maxBitrate:25e6,tier:"L",level:150},{maxPictureSize:8912896,maxBitrate:1e8,tier:"H",level:150},{maxPictureSize:8912896,maxBitrate:4e7,tier:"L",level:153},{maxPictureSize:8912896,maxBitrate:16e7,tier:"H",level:153},{maxPictureSize:8912896,maxBitrate:6e7,tier:"L",level:156},{maxPictureSize:8912896,maxBitrate:24e7,tier:"H",level:156},{maxPictureSize:35651584,maxBitrate:6e7,tier:"L",level:180},{maxPictureSize:35651584,maxBitrate:24e7,tier:"H",level:180},{maxPictureSize:35651584,maxBitrate:12e7,tier:"L",level:183},{maxPictureSize:35651584,maxBitrate:48e7,tier:"H",level:183},{maxPictureSize:35651584,maxBitrate:24e7,tier:"L",level:186},{maxPictureSize:35651584,maxBitrate:8e8,tier:"H",level:186}],u=[{maxPictureSize:36864,maxBitrate:2e5,level:10},{maxPictureSize:73728,maxBitrate:8e5,level:11},{maxPictureSize:122880,maxBitrate:18e5,level:20},{maxPictureSize:245760,maxBitrate:36e5,level:21},{maxPictureSize:552960,maxBitrate:72e5,level:30},{maxPictureSize:983040,maxBitrate:12e6,level:31},{maxPictureSize:2228224,maxBitrate:18e6,level:40},{maxPictureSize:2228224,maxBitrate:3e7,level:41},{maxPictureSize:8912896,maxBitrate:6e7,level:50},{maxPictureSize:8912896,maxBitrate:12e7,level:51},{maxPictureSize:8912896,maxBitrate:18e7,level:52},{maxPictureSize:35651584,maxBitrate:18e7,level:60},{maxPictureSize:35651584,maxBitrate:24e7,level:61},{maxPictureSize:35651584,maxBitrate:48e7,level:62}],h=[{maxPictureSize:147456,maxBitrate:15e5,tier:"M",level:0},{maxPictureSize:278784,maxBitrate:3e6,tier:"M",level:1},{maxPictureSize:665856,maxBitrate:6e6,tier:"M",level:4},{maxPictureSize:1065024,maxBitrate:1e7,tier:"M",level:5},{maxPictureSize:2359296,maxBitrate:12e6,tier:"M",level:8},{maxPictureSize:2359296,maxBitrate:3e7,tier:"H",level:8},{maxPictureSize:2359296,maxBitrate:2e7,tier:"M",level:9},{maxPictureSize:2359296,maxBitrate:5e7,tier:"H",level:9},{maxPictureSize:8912896,maxBitrate:3e7,tier:"M",level:12},{maxPictureSize:8912896,maxBitrate:1e8,tier:"H",level:12},{maxPictureSize:8912896,maxBitrate:4e7,tier:"M",level:13},{maxPictureSize:8912896,maxBitrate:16e7,tier:"H",level:13},{maxPictureSize:8912896,maxBitrate:6e7,tier:"M",level:14},{maxPictureSize:8912896,maxBitrate:24e7,tier:"H",level:14},{maxPictureSize:35651584,maxBitrate:6e7,tier:"M",level:15},{maxPictureSize:35651584,maxBitrate:24e7,tier:"H",level:15},{maxPictureSize:35651584,maxBitrate:6e7,tier:"M",level:16},{maxPictureSize:35651584,maxBitrate:24e7,tier:"H",level:16},{maxPictureSize:35651584,maxBitrate:1e8,tier:"M",level:17},{maxPictureSize:35651584,maxBitrate:48e7,tier:"H",level:17},{maxPictureSize:35651584,maxBitrate:16e7,tier:"M",level:18},{maxPictureSize:35651584,maxBitrate:8e8,tier:"H",level:18},{maxPictureSize:35651584,maxBitrate:16e7,tier:"M",level:19},{maxPictureSize:35651584,maxBitrate:8e8,tier:"H",level:19}];function S(W){return W?W[W.length-1]:void 0}if(e==="avc"){const I=Math.ceil(t/16)*Math.ceil(i/16),Z=d.find(P=>I<=P.maxMacroblocks&&n<=P.maxBitrate)??S(d),j=Z?Z.level:0,w="64".padStart(2,"0"),A="00",J=j.toString(16).padStart(2,"0");return`avc1.${w}${A}${J}`}else if(e==="hevc"){const W="",Z="6",j=t*i,w=o.find(J=>j<=J.maxPictureSize&&n<=J.maxBitrate)??S(o);return`hev1.${W}1.${Z}.${w.tier}${w.level}.B0`}else{if(e==="vp8")return"vp8";if(e==="vp9"){const W="00",I=t*i,Z=u.find(w=>I<=w.maxPictureSize&&n<=w.maxBitrate)??S(u);return`vp09.${W}.${Z.level.toString().padStart(2,"0")}.08`}else if(e==="av1"){const I=t*i,Z=h.find(A=>I<=A.maxPictureSize&&n<=A.maxBitrate)??S(h);return`av01.0.${Z.level.toString().padStart(2,"0")}${Z.tier}.08`}}throw new TypeError(`Unhandled codec '${e}'.`)}class Nn{constructor(t,i={}){this.canvas=t,this.mode="webgpu",this.filterMode=i.filterMode||"linear",this.device=null,this.context=null,this.linearPipeline=null,this.bicubicPipeline=null,this.sampler=null,this.uniformBuffer=null,this.bitmapCtx=null}async init(){if(navigator.gpu)try{await this.initWebGPU(),this.mode="webgpu",console.log("GPUDrawImage: Using WebGPU (zero-copy)");return}catch(t){console.warn("GPUDrawImage: WebGPU initialization failed, falling back to ImageBitmap",t)}this.initBitmapRenderer(),this.mode="bitmap",console.log("GPUDrawImage: Using ImageBitmapRenderer (fallback)")}async initWebGPU(){const t=await navigator.gpu.requestAdapter();if(!t||(this.device=await t.requestDevice(),!this.device)||(this.context=this.canvas.getContext("webgpu"),!this.context))return!1;const i=navigator.gpu.getPreferredCanvasFormat();this.context.configure({device:this.device,format:i,alphaMode:"opaque"}),this.sampler=this.device.createSampler({magFilter:"linear",minFilter:"linear"}),this.uniformBuffer=this.device.createBuffer({size:8,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});const n=`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Fn=require("lamejs"),zi=require("mp4box");function Jn(e,t,i=30,n="good"){const d=e*t,o={low:.05,good:.08,high:.1,"very-high":.15},u=o[n]||o.good;return d*i*u}function En(e,t,i,n){const d=[{maxMacroblocks:99,maxBitrate:64e3,level:10},{maxMacroblocks:396,maxBitrate:192e3,level:11},{maxMacroblocks:396,maxBitrate:384e3,level:12},{maxMacroblocks:396,maxBitrate:768e3,level:13},{maxMacroblocks:396,maxBitrate:2e6,level:20},{maxMacroblocks:792,maxBitrate:4e6,level:21},{maxMacroblocks:1620,maxBitrate:4e6,level:22},{maxMacroblocks:1620,maxBitrate:1e7,level:30},{maxMacroblocks:3600,maxBitrate:14e6,level:31},{maxMacroblocks:5120,maxBitrate:2e7,level:32},{maxMacroblocks:8192,maxBitrate:2e7,level:40},{maxMacroblocks:8192,maxBitrate:5e7,level:41},{maxMacroblocks:8704,maxBitrate:5e7,level:42},{maxMacroblocks:22080,maxBitrate:135e6,level:50},{maxMacroblocks:36864,maxBitrate:24e7,level:51},{maxMacroblocks:36864,maxBitrate:24e7,level:52},{maxMacroblocks:139264,maxBitrate:24e7,level:60},{maxMacroblocks:139264,maxBitrate:48e7,level:61},{maxMacroblocks:139264,maxBitrate:8e8,level:62}],o=[{maxPictureSize:36864,maxBitrate:128e3,tier:"L",level:30},{maxPictureSize:122880,maxBitrate:15e5,tier:"L",level:60},{maxPictureSize:245760,maxBitrate:3e6,tier:"L",level:63},{maxPictureSize:552960,maxBitrate:6e6,tier:"L",level:90},{maxPictureSize:983040,maxBitrate:1e7,tier:"L",level:93},{maxPictureSize:2228224,maxBitrate:12e6,tier:"L",level:120},{maxPictureSize:2228224,maxBitrate:3e7,tier:"H",level:120},{maxPictureSize:2228224,maxBitrate:2e7,tier:"L",level:123},{maxPictureSize:2228224,maxBitrate:5e7,tier:"H",level:123},{maxPictureSize:8912896,maxBitrate:25e6,tier:"L",level:150},{maxPictureSize:8912896,maxBitrate:1e8,tier:"H",level:150},{maxPictureSize:8912896,maxBitrate:4e7,tier:"L",level:153},{maxPictureSize:8912896,maxBitrate:16e7,tier:"H",level:153},{maxPictureSize:8912896,maxBitrate:6e7,tier:"L",level:156},{maxPictureSize:8912896,maxBitrate:24e7,tier:"H",level:156},{maxPictureSize:35651584,maxBitrate:6e7,tier:"L",level:180},{maxPictureSize:35651584,maxBitrate:24e7,tier:"H",level:180},{maxPictureSize:35651584,maxBitrate:12e7,tier:"L",level:183},{maxPictureSize:35651584,maxBitrate:48e7,tier:"H",level:183},{maxPictureSize:35651584,maxBitrate:24e7,tier:"L",level:186},{maxPictureSize:35651584,maxBitrate:8e8,tier:"H",level:186}],u=[{maxPictureSize:36864,maxBitrate:2e5,level:10},{maxPictureSize:73728,maxBitrate:8e5,level:11},{maxPictureSize:122880,maxBitrate:18e5,level:20},{maxPictureSize:245760,maxBitrate:36e5,level:21},{maxPictureSize:552960,maxBitrate:72e5,level:30},{maxPictureSize:983040,maxBitrate:12e6,level:31},{maxPictureSize:2228224,maxBitrate:18e6,level:40},{maxPictureSize:2228224,maxBitrate:3e7,level:41},{maxPictureSize:8912896,maxBitrate:6e7,level:50},{maxPictureSize:8912896,maxBitrate:12e7,level:51},{maxPictureSize:8912896,maxBitrate:18e7,level:52},{maxPictureSize:35651584,maxBitrate:18e7,level:60},{maxPictureSize:35651584,maxBitrate:24e7,level:61},{maxPictureSize:35651584,maxBitrate:48e7,level:62}],h=[{maxPictureSize:147456,maxBitrate:15e5,tier:"M",level:0},{maxPictureSize:278784,maxBitrate:3e6,tier:"M",level:1},{maxPictureSize:665856,maxBitrate:6e6,tier:"M",level:4},{maxPictureSize:1065024,maxBitrate:1e7,tier:"M",level:5},{maxPictureSize:2359296,maxBitrate:12e6,tier:"M",level:8},{maxPictureSize:2359296,maxBitrate:3e7,tier:"H",level:8},{maxPictureSize:2359296,maxBitrate:2e7,tier:"M",level:9},{maxPictureSize:2359296,maxBitrate:5e7,tier:"H",level:9},{maxPictureSize:8912896,maxBitrate:3e7,tier:"M",level:12},{maxPictureSize:8912896,maxBitrate:1e8,tier:"H",level:12},{maxPictureSize:8912896,maxBitrate:4e7,tier:"M",level:13},{maxPictureSize:8912896,maxBitrate:16e7,tier:"H",level:13},{maxPictureSize:8912896,maxBitrate:6e7,tier:"M",level:14},{maxPictureSize:8912896,maxBitrate:24e7,tier:"H",level:14},{maxPictureSize:35651584,maxBitrate:6e7,tier:"M",level:15},{maxPictureSize:35651584,maxBitrate:24e7,tier:"H",level:15},{maxPictureSize:35651584,maxBitrate:6e7,tier:"M",level:16},{maxPictureSize:35651584,maxBitrate:24e7,tier:"H",level:16},{maxPictureSize:35651584,maxBitrate:1e8,tier:"M",level:17},{maxPictureSize:35651584,maxBitrate:48e7,tier:"H",level:17},{maxPictureSize:35651584,maxBitrate:16e7,tier:"M",level:18},{maxPictureSize:35651584,maxBitrate:8e8,tier:"H",level:18},{maxPictureSize:35651584,maxBitrate:16e7,tier:"M",level:19},{maxPictureSize:35651584,maxBitrate:8e8,tier:"H",level:19}];function S(W){return W?W[W.length-1]:void 0}if(e==="avc"){const I=Math.ceil(t/16)*Math.ceil(i/16),Z=d.find(P=>I<=P.maxMacroblocks&&n<=P.maxBitrate)??S(d),j=Z?Z.level:0,w="64".padStart(2,"0"),A="00",J=j.toString(16).padStart(2,"0");return`avc1.${w}${A}${J}`}else if(e==="hevc"){const W="",Z="6",j=t*i,w=o.find(J=>j<=J.maxPictureSize&&n<=J.maxBitrate)??S(o);return`hev1.${W}1.${Z}.${w.tier}${w.level}.B0`}else{if(e==="vp8")return"vp8";if(e==="vp9"){const W="00",I=t*i,Z=u.find(w=>I<=w.maxPictureSize&&n<=w.maxBitrate)??S(u);return`vp09.${W}.${Z.level.toString().padStart(2,"0")}.08`}else if(e==="av1"){const I=t*i,Z=h.find(A=>I<=A.maxPictureSize&&n<=A.maxBitrate)??S(h);return`av01.0.${Z.level.toString().padStart(2,"0")}${Z.tier}.08`}}throw new TypeError(`Unhandled codec '${e}'.`)}class Nn{constructor(t,i={}){this.canvas=t,this.mode="webgpu",this.filterMode=i.filterMode||"linear",this.device=null,this.context=null,this.linearPipeline=null,this.bicubicPipeline=null,this.sampler=null,this.uniformBuffer=null,this.bitmapCtx=null}async init(){if(navigator.gpu)try{await this.initWebGPU(),this.mode="webgpu",console.log("GPUDrawImage: Using WebGPU (zero-copy)");return}catch(t){console.warn("GPUDrawImage: WebGPU initialization failed, falling back to ImageBitmap",t)}this.initBitmapRenderer(),this.mode="bitmap",console.log("GPUDrawImage: Using ImageBitmapRenderer (fallback)")}async initWebGPU(){const t=await navigator.gpu.requestAdapter();if(!t||(this.device=await t.requestDevice(),!this.device)||(this.context=this.canvas.getContext("webgpu"),!this.context))return!1;const i=navigator.gpu.getPreferredCanvasFormat();this.context.configure({device:this.device,format:i,alphaMode:"opaque"}),this.sampler=this.device.createSampler({magFilter:"linear",minFilter:"linear"}),this.uniformBuffer=this.device.createBuffer({size:8,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});const n=`
2
2
  struct VertexOutput {
3
3
  @builtin(position) position: vec4f,
4
4
  @location(0) texCoord: vec2f,
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import gn from "lamejs";
2
2
  import Fn, { DataStream as bs } from "mp4box";
3
- function G1(e, t, i = "good") {
4
- const n = e * t, d = {
3
+ function G1(e, t, i = 30, n = "good") {
4
+ const d = e * t, o = {
5
5
  low: 0.05,
6
6
  good: 0.08,
7
7
  high: 0.1,
8
8
  "very-high": 0.15
9
- }, o = d[i] || d.good;
10
- return n * 30 * o;
9
+ }, u = o[n] || o.good;
10
+ return d * i * u;
11
11
  }
12
12
  function S1(e, t, i, n) {
13
13
  const d = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webcodecs-utils",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Utility functions for working with WebCodecs API",
5
5
  "homepage": "https://webcodecsfundamentals.org",
6
6
  "repository": {