webcodecs-node 0.5.0 → 0.5.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.
Files changed (185) hide show
  1. package/package.json +1 -1
  2. package/dist/AudioData.d.ts +0 -6
  3. package/dist/AudioData.d.ts.map +0 -1
  4. package/dist/AudioData.js +0 -6
  5. package/dist/AudioData.js.map +0 -1
  6. package/dist/AudioDecoder.d.ts +0 -6
  7. package/dist/AudioDecoder.d.ts.map +0 -1
  8. package/dist/AudioDecoder.js +0 -6
  9. package/dist/AudioDecoder.js.map +0 -1
  10. package/dist/AudioEncoder.d.ts +0 -6
  11. package/dist/AudioEncoder.d.ts.map +0 -1
  12. package/dist/AudioEncoder.js +0 -6
  13. package/dist/AudioEncoder.js.map +0 -1
  14. package/dist/EncodedAudioChunk.d.ts +0 -6
  15. package/dist/EncodedAudioChunk.d.ts.map +0 -1
  16. package/dist/EncodedAudioChunk.js +0 -6
  17. package/dist/EncodedAudioChunk.js.map +0 -1
  18. package/dist/EncodedVideoChunk.d.ts +0 -6
  19. package/dist/EncodedVideoChunk.d.ts.map +0 -1
  20. package/dist/EncodedVideoChunk.js +0 -6
  21. package/dist/EncodedVideoChunk.js.map +0 -1
  22. package/dist/FFmpegProcess.d.ts +0 -6
  23. package/dist/FFmpegProcess.d.ts.map +0 -1
  24. package/dist/FFmpegProcess.js +0 -6
  25. package/dist/FFmpegProcess.js.map +0 -1
  26. package/dist/HardwareAcceleration.d.ts +0 -6
  27. package/dist/HardwareAcceleration.d.ts.map +0 -1
  28. package/dist/HardwareAcceleration.js +0 -6
  29. package/dist/HardwareAcceleration.js.map +0 -1
  30. package/dist/ImageDecoder.d.ts +0 -6
  31. package/dist/ImageDecoder.d.ts.map +0 -1
  32. package/dist/ImageDecoder.js +0 -6
  33. package/dist/ImageDecoder.js.map +0 -1
  34. package/dist/Logger.d.ts +0 -6
  35. package/dist/Logger.d.ts.map +0 -1
  36. package/dist/Logger.js +0 -6
  37. package/dist/Logger.js.map +0 -1
  38. package/dist/MediaCapabilities.d.ts +0 -9
  39. package/dist/MediaCapabilities.d.ts.map +0 -1
  40. package/dist/MediaCapabilities.js +0 -8
  41. package/dist/MediaCapabilities.js.map +0 -1
  42. package/dist/VideoDecoder.d.ts +0 -6
  43. package/dist/VideoDecoder.d.ts.map +0 -1
  44. package/dist/VideoDecoder.js +0 -6
  45. package/dist/VideoDecoder.js.map +0 -1
  46. package/dist/VideoEncoder.d.ts +0 -6
  47. package/dist/VideoEncoder.d.ts.map +0 -1
  48. package/dist/VideoEncoder.js +0 -6
  49. package/dist/VideoEncoder.js.map +0 -1
  50. package/dist/VideoFrame.d.ts +0 -10
  51. package/dist/VideoFrame.d.ts.map +0 -1
  52. package/dist/VideoFrame.js +0 -9
  53. package/dist/VideoFrame.js.map +0 -1
  54. package/dist/__tests__/AudioData.test.d.ts +0 -5
  55. package/dist/__tests__/AudioData.test.d.ts.map +0 -1
  56. package/dist/__tests__/AudioData.test.js +0 -180
  57. package/dist/__tests__/AudioData.test.js.map +0 -1
  58. package/dist/__tests__/AudioDecoder.test.d.ts +0 -5
  59. package/dist/__tests__/AudioDecoder.test.d.ts.map +0 -1
  60. package/dist/__tests__/AudioDecoder.test.js +0 -733
  61. package/dist/__tests__/AudioDecoder.test.js.map +0 -1
  62. package/dist/__tests__/AudioEncoder.test.d.ts +0 -5
  63. package/dist/__tests__/AudioEncoder.test.d.ts.map +0 -1
  64. package/dist/__tests__/AudioEncoder.test.js +0 -247
  65. package/dist/__tests__/AudioEncoder.test.js.map +0 -1
  66. package/dist/__tests__/EncodedChunks.test.d.ts +0 -5
  67. package/dist/__tests__/EncodedChunks.test.d.ts.map +0 -1
  68. package/dist/__tests__/EncodedChunks.test.js +0 -100
  69. package/dist/__tests__/EncodedChunks.test.js.map +0 -1
  70. package/dist/__tests__/HardwareAcceleration.test.d.ts +0 -5
  71. package/dist/__tests__/HardwareAcceleration.test.d.ts.map +0 -1
  72. package/dist/__tests__/HardwareAcceleration.test.js +0 -85
  73. package/dist/__tests__/HardwareAcceleration.test.js.map +0 -1
  74. package/dist/__tests__/ImageDecoder.test.d.ts +0 -5
  75. package/dist/__tests__/ImageDecoder.test.d.ts.map +0 -1
  76. package/dist/__tests__/ImageDecoder.test.js +0 -558
  77. package/dist/__tests__/ImageDecoder.test.js.map +0 -1
  78. package/dist/__tests__/ImageDecoder.wpt.test.d.ts +0 -8
  79. package/dist/__tests__/ImageDecoder.wpt.test.d.ts.map +0 -1
  80. package/dist/__tests__/ImageDecoder.wpt.test.js +0 -135
  81. package/dist/__tests__/ImageDecoder.wpt.test.js.map +0 -1
  82. package/dist/__tests__/MediaCapabilities.test.d.ts +0 -5
  83. package/dist/__tests__/MediaCapabilities.test.d.ts.map +0 -1
  84. package/dist/__tests__/MediaCapabilities.test.js +0 -346
  85. package/dist/__tests__/MediaCapabilities.test.js.map +0 -1
  86. package/dist/__tests__/NodeAvDecoder.test.d.ts +0 -2
  87. package/dist/__tests__/NodeAvDecoder.test.d.ts.map +0 -1
  88. package/dist/__tests__/NodeAvDecoder.test.js +0 -206
  89. package/dist/__tests__/NodeAvDecoder.test.js.map +0 -1
  90. package/dist/__tests__/NodeAvEncoder.test.d.ts +0 -2
  91. package/dist/__tests__/NodeAvEncoder.test.d.ts.map +0 -1
  92. package/dist/__tests__/NodeAvEncoder.test.js +0 -176
  93. package/dist/__tests__/NodeAvEncoder.test.js.map +0 -1
  94. package/dist/__tests__/VideoDecoder.test.d.ts +0 -5
  95. package/dist/__tests__/VideoDecoder.test.d.ts.map +0 -1
  96. package/dist/__tests__/VideoDecoder.test.js +0 -675
  97. package/dist/__tests__/VideoDecoder.test.js.map +0 -1
  98. package/dist/__tests__/VideoEncoder.test.d.ts +0 -5
  99. package/dist/__tests__/VideoEncoder.test.d.ts.map +0 -1
  100. package/dist/__tests__/VideoEncoder.test.js +0 -468
  101. package/dist/__tests__/VideoEncoder.test.js.map +0 -1
  102. package/dist/__tests__/VideoFrame.test.d.ts +0 -5
  103. package/dist/__tests__/VideoFrame.test.d.ts.map +0 -1
  104. package/dist/__tests__/VideoFrame.test.js +0 -246
  105. package/dist/__tests__/VideoFrame.test.js.map +0 -1
  106. package/dist/__tests__/aac-utils.test.d.ts +0 -2
  107. package/dist/__tests__/aac-utils.test.d.ts.map +0 -1
  108. package/dist/__tests__/aac-utils.test.js +0 -37
  109. package/dist/__tests__/aac-utils.test.js.map +0 -1
  110. package/dist/__tests__/avc-utils.test.d.ts +0 -2
  111. package/dist/__tests__/avc-utils.test.d.ts.map +0 -1
  112. package/dist/__tests__/avc-utils.test.js +0 -63
  113. package/dist/__tests__/avc-utils.test.js.map +0 -1
  114. package/dist/__tests__/hevc-utils.test.d.ts +0 -2
  115. package/dist/__tests__/hevc-utils.test.d.ts.map +0 -1
  116. package/dist/__tests__/hevc-utils.test.js +0 -78
  117. package/dist/__tests__/hevc-utils.test.js.map +0 -1
  118. package/dist/demos/demo-conversion.d.ts +0 -13
  119. package/dist/demos/demo-conversion.d.ts.map +0 -1
  120. package/dist/demos/demo-conversion.js +0 -301
  121. package/dist/demos/demo-conversion.js.map +0 -1
  122. package/dist/demos/demo-hwaccel-conversion.d.ts +0 -8
  123. package/dist/demos/demo-hwaccel-conversion.d.ts.map +0 -1
  124. package/dist/demos/demo-hwaccel-conversion.js +0 -161
  125. package/dist/demos/demo-hwaccel-conversion.js.map +0 -1
  126. package/dist/demos/demo-mediabunny.d.ts +0 -7
  127. package/dist/demos/demo-mediabunny.d.ts.map +0 -1
  128. package/dist/demos/demo-mediabunny.js +0 -78
  129. package/dist/demos/demo-mediabunny.js.map +0 -1
  130. package/dist/ffmpeg/FFmpegProcess.d.ts +0 -111
  131. package/dist/ffmpeg/FFmpegProcess.d.ts.map +0 -1
  132. package/dist/ffmpeg/FFmpegProcess.js +0 -543
  133. package/dist/ffmpeg/FFmpegProcess.js.map +0 -1
  134. package/dist/ffmpeg/audio-codecs.d.ts +0 -59
  135. package/dist/ffmpeg/audio-codecs.d.ts.map +0 -1
  136. package/dist/ffmpeg/audio-codecs.js +0 -99
  137. package/dist/ffmpeg/audio-codecs.js.map +0 -1
  138. package/dist/ffmpeg/formats.d.ts +0 -42
  139. package/dist/ffmpeg/formats.d.ts.map +0 -1
  140. package/dist/ffmpeg/formats.js +0 -147
  141. package/dist/ffmpeg/formats.js.map +0 -1
  142. package/dist/ffmpeg/index.d.ts +0 -10
  143. package/dist/ffmpeg/index.d.ts.map +0 -1
  144. package/dist/ffmpeg/index.js +0 -13
  145. package/dist/ffmpeg/index.js.map +0 -1
  146. package/dist/ffmpeg/parsers/annexb.d.ts +0 -88
  147. package/dist/ffmpeg/parsers/annexb.d.ts.map +0 -1
  148. package/dist/ffmpeg/parsers/annexb.js +0 -201
  149. package/dist/ffmpeg/parsers/annexb.js.map +0 -1
  150. package/dist/ffmpeg/parsers/index.d.ts +0 -6
  151. package/dist/ffmpeg/parsers/index.d.ts.map +0 -1
  152. package/dist/ffmpeg/parsers/index.js +0 -8
  153. package/dist/ffmpeg/parsers/index.js.map +0 -1
  154. package/dist/ffmpeg/parsers/ivf.d.ts +0 -54
  155. package/dist/ffmpeg/parsers/ivf.d.ts.map +0 -1
  156. package/dist/ffmpeg/parsers/ivf.js +0 -109
  157. package/dist/ffmpeg/parsers/ivf.js.map +0 -1
  158. package/dist/ffmpeg/types.d.ts +0 -85
  159. package/dist/ffmpeg/types.d.ts.map +0 -1
  160. package/dist/ffmpeg/types.js +0 -8
  161. package/dist/ffmpeg/types.js.map +0 -1
  162. package/dist/mediabunny/FFmpegAudioDecoder.d.ts +0 -24
  163. package/dist/mediabunny/FFmpegAudioDecoder.d.ts.map +0 -1
  164. package/dist/mediabunny/FFmpegAudioDecoder.js +0 -126
  165. package/dist/mediabunny/FFmpegAudioDecoder.js.map +0 -1
  166. package/dist/mediabunny/FFmpegAudioEncoder.d.ts +0 -44
  167. package/dist/mediabunny/FFmpegAudioEncoder.d.ts.map +0 -1
  168. package/dist/mediabunny/FFmpegAudioEncoder.js +0 -221
  169. package/dist/mediabunny/FFmpegAudioEncoder.js.map +0 -1
  170. package/dist/mediabunny/FFmpegVideoDecoder.d.ts +0 -25
  171. package/dist/mediabunny/FFmpegVideoDecoder.d.ts.map +0 -1
  172. package/dist/mediabunny/FFmpegVideoDecoder.js +0 -122
  173. package/dist/mediabunny/FFmpegVideoDecoder.js.map +0 -1
  174. package/dist/mediabunny/FFmpegVideoEncoder.d.ts +0 -49
  175. package/dist/mediabunny/FFmpegVideoEncoder.d.ts.map +0 -1
  176. package/dist/mediabunny/FFmpegVideoEncoder.js +0 -264
  177. package/dist/mediabunny/FFmpegVideoEncoder.js.map +0 -1
  178. package/dist/mediabunny/index.d.ts +0 -21
  179. package/dist/mediabunny/index.d.ts.map +0 -1
  180. package/dist/mediabunny/index.js +0 -33
  181. package/dist/mediabunny/index.js.map +0 -1
  182. package/dist/types.d.ts +0 -6
  183. package/dist/types.d.ts.map +0 -1
  184. package/dist/types.js +0 -6
  185. package/dist/types.js.map +0 -1
@@ -1,733 +0,0 @@
1
- /**
2
- * Tests for AudioDecoder class
3
- */
4
- import { describe, it, expect } from 'vitest';
5
- import { AudioDecoder } from '../decoders/AudioDecoder.js';
6
- import { AudioEncoder } from '../encoders/AudioEncoder.js';
7
- import { AudioData } from '../core/AudioData.js';
8
- import { EncodedAudioChunk } from '../core/EncodedAudioChunk.js';
9
- describe('AudioDecoder', () => {
10
- describe('isConfigSupported', () => {
11
- it('should support Opus', async () => {
12
- const support = await AudioDecoder.isConfigSupported({
13
- codec: 'opus',
14
- sampleRate: 48000,
15
- numberOfChannels: 2,
16
- });
17
- expect(support.supported).toBe(true);
18
- });
19
- it('should support AAC', async () => {
20
- const support = await AudioDecoder.isConfigSupported({
21
- codec: 'mp4a.40.2',
22
- sampleRate: 44100,
23
- numberOfChannels: 2,
24
- });
25
- expect(support.supported).toBe(true);
26
- });
27
- it('should support MP3', async () => {
28
- const support = await AudioDecoder.isConfigSupported({
29
- codec: 'mp3',
30
- sampleRate: 44100,
31
- numberOfChannels: 2,
32
- });
33
- expect(support.supported).toBe(true);
34
- });
35
- it('should support FLAC', async () => {
36
- const support = await AudioDecoder.isConfigSupported({
37
- codec: 'flac',
38
- sampleRate: 48000,
39
- numberOfChannels: 2,
40
- });
41
- expect(support.supported).toBe(true);
42
- });
43
- it('should support Vorbis', async () => {
44
- const support = await AudioDecoder.isConfigSupported({
45
- codec: 'vorbis',
46
- sampleRate: 44100,
47
- numberOfChannels: 2,
48
- });
49
- expect(support.supported).toBe(true);
50
- });
51
- it('should not support missing codec', async () => {
52
- const support = await AudioDecoder.isConfigSupported({
53
- codec: '',
54
- sampleRate: 48000,
55
- numberOfChannels: 2,
56
- });
57
- expect(support.supported).toBe(false);
58
- });
59
- it('should not support missing sampleRate', async () => {
60
- const support = await AudioDecoder.isConfigSupported({
61
- codec: 'opus',
62
- sampleRate: 0,
63
- numberOfChannels: 2,
64
- });
65
- expect(support.supported).toBe(false);
66
- });
67
- });
68
- describe('constructor', () => {
69
- it('should create decoder with callbacks', () => {
70
- const output = jest.fn();
71
- const error = jest.fn();
72
- const decoder = new AudioDecoder({ output, error });
73
- expect(decoder.state).toBe('unconfigured');
74
- decoder.close();
75
- });
76
- it('should throw without output callback', () => {
77
- expect(() => new AudioDecoder({ output: null, error: () => { } })).toThrow();
78
- });
79
- it('should throw without error callback', () => {
80
- expect(() => new AudioDecoder({ output: () => { }, error: null })).toThrow();
81
- });
82
- });
83
- describe('configure', () => {
84
- it('should configure decoder', () => {
85
- const decoder = new AudioDecoder({
86
- output: () => { },
87
- error: () => { },
88
- });
89
- decoder.configure({
90
- codec: 'opus',
91
- sampleRate: 48000,
92
- numberOfChannels: 2,
93
- });
94
- expect(decoder.state).toBe('configured');
95
- decoder.close();
96
- });
97
- it('should throw without codec', () => {
98
- const decoder = new AudioDecoder({
99
- output: () => { },
100
- error: () => { },
101
- });
102
- expect(() => decoder.configure({
103
- codec: '',
104
- sampleRate: 48000,
105
- numberOfChannels: 2,
106
- })).toThrow();
107
- decoder.close();
108
- });
109
- it('should throw with invalid sampleRate', () => {
110
- const decoder = new AudioDecoder({
111
- output: () => { },
112
- error: () => { },
113
- });
114
- expect(() => decoder.configure({
115
- codec: 'opus',
116
- sampleRate: 0,
117
- numberOfChannels: 2,
118
- })).toThrow();
119
- decoder.close();
120
- });
121
- it('should throw with invalid numberOfChannels', () => {
122
- const decoder = new AudioDecoder({
123
- output: () => { },
124
- error: () => { },
125
- });
126
- expect(() => decoder.configure({
127
- codec: 'opus',
128
- sampleRate: 48000,
129
- numberOfChannels: 0,
130
- })).toThrow();
131
- decoder.close();
132
- });
133
- it('should throw on closed decoder', () => {
134
- const decoder = new AudioDecoder({
135
- output: () => { },
136
- error: () => { },
137
- });
138
- decoder.close();
139
- expect(() => decoder.configure({
140
- codec: 'opus',
141
- sampleRate: 48000,
142
- numberOfChannels: 2,
143
- })).toThrow();
144
- });
145
- it('should accept valid outputFormat', () => {
146
- const decoder = new AudioDecoder({
147
- output: () => { },
148
- error: () => { },
149
- });
150
- decoder.configure({
151
- codec: 'opus',
152
- sampleRate: 48000,
153
- numberOfChannels: 2,
154
- outputFormat: 's16',
155
- });
156
- expect(decoder.state).toBe('configured');
157
- decoder.close();
158
- });
159
- it('should throw with invalid outputFormat', () => {
160
- const decoder = new AudioDecoder({
161
- output: () => { },
162
- error: () => { },
163
- });
164
- expect(() => decoder.configure({
165
- codec: 'opus',
166
- sampleRate: 48000,
167
- numberOfChannels: 2,
168
- outputFormat: 'invalid',
169
- })).toThrow();
170
- decoder.close();
171
- });
172
- });
173
- describe('decode', () => {
174
- it('should throw when not configured', () => {
175
- const decoder = new AudioDecoder({
176
- output: () => { },
177
- error: () => { },
178
- });
179
- const chunk = new EncodedAudioChunk({
180
- type: 'key',
181
- timestamp: 0,
182
- data: new Uint8Array(100),
183
- });
184
- expect(() => decoder.decode(chunk)).toThrow();
185
- decoder.close();
186
- });
187
- it('should throw with invalid chunk', () => {
188
- const decoder = new AudioDecoder({
189
- output: () => { },
190
- error: () => { },
191
- });
192
- decoder.configure({
193
- codec: 'opus',
194
- sampleRate: 48000,
195
- numberOfChannels: 2,
196
- });
197
- expect(() => decoder.decode('invalid')).toThrow();
198
- decoder.close();
199
- });
200
- });
201
- describe('reset', () => {
202
- it('should reset decoder to unconfigured state', () => {
203
- const decoder = new AudioDecoder({
204
- output: () => { },
205
- error: () => { },
206
- });
207
- decoder.configure({
208
- codec: 'opus',
209
- sampleRate: 48000,
210
- numberOfChannels: 2,
211
- });
212
- expect(decoder.state).toBe('configured');
213
- decoder.reset();
214
- expect(decoder.state).toBe('unconfigured');
215
- decoder.close();
216
- });
217
- it('should throw on closed decoder', () => {
218
- const decoder = new AudioDecoder({
219
- output: () => { },
220
- error: () => { },
221
- });
222
- decoder.close();
223
- expect(() => decoder.reset()).toThrow();
224
- });
225
- });
226
- describe('close', () => {
227
- it('should close decoder', () => {
228
- const decoder = new AudioDecoder({
229
- output: () => { },
230
- error: () => { },
231
- });
232
- decoder.close();
233
- expect(decoder.state).toBe('closed');
234
- });
235
- it('should be idempotent', () => {
236
- const decoder = new AudioDecoder({
237
- output: () => { },
238
- error: () => { },
239
- });
240
- decoder.close();
241
- decoder.close(); // Should not throw
242
- expect(decoder.state).toBe('closed');
243
- });
244
- });
245
- describe('flush', () => {
246
- it('should throw when not configured', async () => {
247
- const decoder = new AudioDecoder({
248
- output: () => { },
249
- error: () => { },
250
- });
251
- await expect(decoder.flush()).rejects.toThrow();
252
- decoder.close();
253
- });
254
- });
255
- describe('decodeQueueSize', () => {
256
- it('should start at 0', () => {
257
- const decoder = new AudioDecoder({
258
- output: () => { },
259
- error: () => { },
260
- });
261
- expect(decoder.decodeQueueSize).toBe(0);
262
- decoder.close();
263
- });
264
- });
265
- });
266
- describe('AudioDecoder encode-decode roundtrip', () => {
267
- it('should decode Opus encoded audio', async () => {
268
- const sampleRate = 48000;
269
- const numberOfChannels = 2;
270
- const numberOfFrames = 960; // 20ms at 48kHz
271
- const chunkCount = 3;
272
- // Step 1: Encode audio
273
- const encodedChunks = [];
274
- const encoder = new AudioEncoder({
275
- output: (chunk) => encodedChunks.push(chunk),
276
- error: (err) => { throw err; },
277
- });
278
- encoder.configure({
279
- codec: 'opus',
280
- sampleRate,
281
- numberOfChannels,
282
- bitrate: 64000,
283
- });
284
- // Create and encode test audio (sine waves) - use interleaved f32 format
285
- for (let c = 0; c < chunkCount; c++) {
286
- const samples = new Float32Array(numberOfFrames * numberOfChannels);
287
- const frequency = 440 + c * 100; // Different frequency for each chunk
288
- for (let i = 0; i < numberOfFrames; i++) {
289
- const t = (c * numberOfFrames + i) / sampleRate;
290
- const value = Math.sin(2 * Math.PI * frequency * t);
291
- for (let ch = 0; ch < numberOfChannels; ch++) {
292
- samples[i * numberOfChannels + ch] = value;
293
- }
294
- }
295
- const audioData = new AudioData({
296
- format: 'f32', // Use interleaved format
297
- sampleRate,
298
- numberOfChannels,
299
- numberOfFrames,
300
- timestamp: c * (numberOfFrames * 1_000_000 / sampleRate),
301
- data: samples,
302
- });
303
- encoder.encode(audioData);
304
- audioData.close();
305
- }
306
- await encoder.flush();
307
- encoder.close();
308
- expect(encodedChunks.length).toBeGreaterThan(0);
309
- // Step 2: Decode audio
310
- const decodedAudio = [];
311
- const decoder = new AudioDecoder({
312
- output: (audio) => decodedAudio.push(audio),
313
- error: (err) => { throw err; },
314
- });
315
- decoder.configure({
316
- codec: 'opus',
317
- sampleRate,
318
- numberOfChannels,
319
- });
320
- for (const chunk of encodedChunks) {
321
- decoder.decode(chunk);
322
- }
323
- await decoder.flush();
324
- decoder.close();
325
- // Verify decoded audio
326
- expect(decodedAudio.length).toBeGreaterThan(0);
327
- let totalFrames = 0;
328
- for (const audio of decodedAudio) {
329
- expect(audio.sampleRate).toBe(sampleRate);
330
- expect(audio.numberOfChannels).toBe(numberOfChannels);
331
- totalFrames += audio.numberOfFrames;
332
- audio.close();
333
- }
334
- // Total decoded frames should be close to original
335
- const expectedFrames = numberOfFrames * chunkCount;
336
- expect(totalFrames).toBeGreaterThanOrEqual(expectedFrames * 0.9);
337
- }, 30000);
338
- it('should decode FLAC encoded audio', async () => {
339
- const sampleRate = 48000;
340
- const numberOfChannels = 2;
341
- const numberOfFrames = 4608; // FLAC minimum frame size
342
- const chunkCount = 2;
343
- // Step 1: Encode audio
344
- const encodedChunks = [];
345
- const encoder = new AudioEncoder({
346
- output: (chunk) => encodedChunks.push(chunk),
347
- error: (err) => { throw err; },
348
- });
349
- encoder.configure({
350
- codec: 'flac',
351
- sampleRate,
352
- numberOfChannels,
353
- });
354
- for (let c = 0; c < chunkCount; c++) {
355
- const samples = new Float32Array(numberOfFrames * numberOfChannels);
356
- for (let i = 0; i < numberOfFrames; i++) {
357
- const t = (c * numberOfFrames + i) / sampleRate;
358
- const value = Math.sin(2 * Math.PI * 880 * t) * 0.5;
359
- for (let ch = 0; ch < numberOfChannels; ch++) {
360
- samples[i * numberOfChannels + ch] = value;
361
- }
362
- }
363
- const audioData = new AudioData({
364
- format: 'f32', // Use interleaved format
365
- sampleRate,
366
- numberOfChannels,
367
- numberOfFrames,
368
- timestamp: c * (numberOfFrames * 1_000_000 / sampleRate),
369
- data: samples,
370
- });
371
- encoder.encode(audioData);
372
- audioData.close();
373
- }
374
- await encoder.flush();
375
- encoder.close();
376
- expect(encodedChunks.length).toBeGreaterThan(0);
377
- // Step 2: Decode audio
378
- const decodedAudio = [];
379
- const decoder = new AudioDecoder({
380
- output: (audio) => decodedAudio.push(audio),
381
- error: (err) => { throw err; },
382
- });
383
- decoder.configure({
384
- codec: 'flac',
385
- sampleRate,
386
- numberOfChannels,
387
- });
388
- for (const chunk of encodedChunks) {
389
- decoder.decode(chunk);
390
- }
391
- await decoder.flush();
392
- decoder.close();
393
- // Verify decoded audio
394
- expect(decodedAudio.length).toBeGreaterThan(0);
395
- for (const audio of decodedAudio) {
396
- expect(audio.sampleRate).toBe(sampleRate);
397
- expect(audio.numberOfChannels).toBe(numberOfChannels);
398
- audio.close();
399
- }
400
- }, 30000);
401
- it('should handle mono audio', async () => {
402
- const sampleRate = 48000; // libopus only supports specific rates: 48000, 24000, 16000, 12000, 8000
403
- const numberOfChannels = 1;
404
- const numberOfFrames = 960; // Opus frame size
405
- // Encode
406
- const encodedChunks = [];
407
- const encoder = new AudioEncoder({
408
- output: (chunk) => encodedChunks.push(chunk),
409
- error: (err) => { throw err; },
410
- });
411
- encoder.configure({
412
- codec: 'opus',
413
- sampleRate,
414
- numberOfChannels,
415
- bitrate: 32000,
416
- });
417
- const samples = new Float32Array(numberOfFrames);
418
- for (let i = 0; i < numberOfFrames; i++) {
419
- samples[i] = Math.sin(2 * Math.PI * 440 * i / sampleRate);
420
- }
421
- const audioData = new AudioData({
422
- format: 'f32', // Use interleaved format (same as planar for mono)
423
- sampleRate,
424
- numberOfChannels,
425
- numberOfFrames,
426
- timestamp: 0,
427
- data: samples,
428
- });
429
- encoder.encode(audioData);
430
- audioData.close();
431
- await encoder.flush();
432
- encoder.close();
433
- expect(encodedChunks.length).toBeGreaterThan(0);
434
- // Decode
435
- const decodedAudio = [];
436
- const decoder = new AudioDecoder({
437
- output: (audio) => decodedAudio.push(audio),
438
- error: (err) => { throw err; },
439
- });
440
- decoder.configure({
441
- codec: 'opus',
442
- sampleRate,
443
- numberOfChannels,
444
- });
445
- for (const chunk of encodedChunks) {
446
- decoder.decode(chunk);
447
- }
448
- await decoder.flush();
449
- decoder.close();
450
- expect(decodedAudio.length).toBeGreaterThan(0);
451
- for (const audio of decodedAudio) {
452
- expect(audio.numberOfChannels).toBe(numberOfChannels);
453
- audio.close();
454
- }
455
- }, 30000);
456
- });
457
- describe('AudioDecoder output formats', () => {
458
- // Helper to encode test audio for format tests
459
- async function encodeTestAudio() {
460
- const sampleRate = 48000;
461
- const numberOfChannels = 2;
462
- const numberOfFrames = 960;
463
- const encodedChunks = [];
464
- const encoder = new AudioEncoder({
465
- output: (chunk) => encodedChunks.push(chunk),
466
- error: (err) => { throw err; },
467
- });
468
- encoder.configure({
469
- codec: 'opus',
470
- sampleRate,
471
- numberOfChannels,
472
- bitrate: 64000,
473
- });
474
- // Create test audio - interleaved f32
475
- const samples = new Float32Array(numberOfFrames * numberOfChannels);
476
- for (let i = 0; i < numberOfFrames; i++) {
477
- const value = Math.sin(2 * Math.PI * 440 * i / sampleRate);
478
- samples[i * numberOfChannels] = value;
479
- samples[i * numberOfChannels + 1] = value;
480
- }
481
- const audioData = new AudioData({
482
- format: 'f32',
483
- sampleRate,
484
- numberOfChannels,
485
- numberOfFrames,
486
- timestamp: 0,
487
- data: samples,
488
- });
489
- encoder.encode(audioData);
490
- audioData.close();
491
- await encoder.flush();
492
- encoder.close();
493
- return encodedChunks;
494
- }
495
- it('should decode to s16 format', async () => {
496
- const encodedChunks = await encodeTestAudio();
497
- expect(encodedChunks.length).toBeGreaterThan(0);
498
- const decodedAudio = [];
499
- const decoder = new AudioDecoder({
500
- output: (audio) => decodedAudio.push(audio),
501
- error: (err) => { throw err; },
502
- });
503
- decoder.configure({
504
- codec: 'opus',
505
- sampleRate: 48000,
506
- numberOfChannels: 2,
507
- outputFormat: 's16',
508
- });
509
- for (const chunk of encodedChunks) {
510
- decoder.decode(chunk);
511
- }
512
- await decoder.flush();
513
- decoder.close();
514
- expect(decodedAudio.length).toBeGreaterThan(0);
515
- for (const audio of decodedAudio) {
516
- expect(audio.format).toBe('s16');
517
- expect(audio.numberOfChannels).toBe(2);
518
- audio.close();
519
- }
520
- }, 30000);
521
- it('should decode to s32 format', async () => {
522
- const encodedChunks = await encodeTestAudio();
523
- expect(encodedChunks.length).toBeGreaterThan(0);
524
- const decodedAudio = [];
525
- const decoder = new AudioDecoder({
526
- output: (audio) => decodedAudio.push(audio),
527
- error: (err) => { throw err; },
528
- });
529
- decoder.configure({
530
- codec: 'opus',
531
- sampleRate: 48000,
532
- numberOfChannels: 2,
533
- outputFormat: 's32',
534
- });
535
- for (const chunk of encodedChunks) {
536
- decoder.decode(chunk);
537
- }
538
- await decoder.flush();
539
- decoder.close();
540
- expect(decodedAudio.length).toBeGreaterThan(0);
541
- for (const audio of decodedAudio) {
542
- expect(audio.format).toBe('s32');
543
- audio.close();
544
- }
545
- }, 30000);
546
- it('should decode to u8 format', async () => {
547
- const encodedChunks = await encodeTestAudio();
548
- expect(encodedChunks.length).toBeGreaterThan(0);
549
- const decodedAudio = [];
550
- const decoder = new AudioDecoder({
551
- output: (audio) => decodedAudio.push(audio),
552
- error: (err) => { throw err; },
553
- });
554
- decoder.configure({
555
- codec: 'opus',
556
- sampleRate: 48000,
557
- numberOfChannels: 2,
558
- outputFormat: 'u8',
559
- });
560
- for (const chunk of encodedChunks) {
561
- decoder.decode(chunk);
562
- }
563
- await decoder.flush();
564
- decoder.close();
565
- expect(decodedAudio.length).toBeGreaterThan(0);
566
- for (const audio of decodedAudio) {
567
- expect(audio.format).toBe('u8');
568
- audio.close();
569
- }
570
- }, 30000);
571
- it('should decode to f32-planar format', async () => {
572
- const encodedChunks = await encodeTestAudio();
573
- expect(encodedChunks.length).toBeGreaterThan(0);
574
- const decodedAudio = [];
575
- const decoder = new AudioDecoder({
576
- output: (audio) => decodedAudio.push(audio),
577
- error: (err) => { throw err; },
578
- });
579
- decoder.configure({
580
- codec: 'opus',
581
- sampleRate: 48000,
582
- numberOfChannels: 2,
583
- outputFormat: 'f32-planar',
584
- });
585
- for (const chunk of encodedChunks) {
586
- decoder.decode(chunk);
587
- }
588
- await decoder.flush();
589
- decoder.close();
590
- expect(decodedAudio.length).toBeGreaterThan(0);
591
- for (const audio of decodedAudio) {
592
- expect(audio.format).toBe('f32-planar');
593
- expect(audio.numberOfChannels).toBe(2);
594
- audio.close();
595
- }
596
- }, 30000);
597
- it('should decode to s16-planar format', async () => {
598
- const encodedChunks = await encodeTestAudio();
599
- expect(encodedChunks.length).toBeGreaterThan(0);
600
- const decodedAudio = [];
601
- const decoder = new AudioDecoder({
602
- output: (audio) => decodedAudio.push(audio),
603
- error: (err) => { throw err; },
604
- });
605
- decoder.configure({
606
- codec: 'opus',
607
- sampleRate: 48000,
608
- numberOfChannels: 2,
609
- outputFormat: 's16-planar',
610
- });
611
- for (const chunk of encodedChunks) {
612
- decoder.decode(chunk);
613
- }
614
- await decoder.flush();
615
- decoder.close();
616
- expect(decodedAudio.length).toBeGreaterThan(0);
617
- for (const audio of decodedAudio) {
618
- expect(audio.format).toBe('s16-planar');
619
- audio.close();
620
- }
621
- }, 30000);
622
- });
623
- describe('AudioEncoder input formats', () => {
624
- it('should encode from s16 format', async () => {
625
- const sampleRate = 48000;
626
- const numberOfChannels = 2;
627
- const numberOfFrames = 960;
628
- const encodedChunks = [];
629
- const encoder = new AudioEncoder({
630
- output: (chunk) => encodedChunks.push(chunk),
631
- error: (err) => { throw err; },
632
- });
633
- encoder.configure({
634
- codec: 'opus',
635
- sampleRate,
636
- numberOfChannels,
637
- bitrate: 64000,
638
- });
639
- // Create s16 interleaved samples
640
- const samples = new Int16Array(numberOfFrames * numberOfChannels);
641
- for (let i = 0; i < numberOfFrames; i++) {
642
- const value = Math.round(Math.sin(2 * Math.PI * 440 * i / sampleRate) * 32767);
643
- samples[i * numberOfChannels] = value;
644
- samples[i * numberOfChannels + 1] = value;
645
- }
646
- const audioData = new AudioData({
647
- format: 's16',
648
- sampleRate,
649
- numberOfChannels,
650
- numberOfFrames,
651
- timestamp: 0,
652
- data: new Uint8Array(samples.buffer),
653
- });
654
- encoder.encode(audioData);
655
- audioData.close();
656
- await encoder.flush();
657
- encoder.close();
658
- expect(encodedChunks.length).toBeGreaterThan(0);
659
- }, 30000);
660
- it('should encode from f32-planar format', async () => {
661
- const sampleRate = 48000;
662
- const numberOfChannels = 2;
663
- const numberOfFrames = 960;
664
- const encodedChunks = [];
665
- const encoder = new AudioEncoder({
666
- output: (chunk) => encodedChunks.push(chunk),
667
- error: (err) => { throw err; },
668
- });
669
- encoder.configure({
670
- codec: 'opus',
671
- sampleRate,
672
- numberOfChannels,
673
- bitrate: 64000,
674
- });
675
- // Create f32-planar samples (channel 0 followed by channel 1)
676
- const samples = new Float32Array(numberOfFrames * numberOfChannels);
677
- for (let i = 0; i < numberOfFrames; i++) {
678
- const value = Math.sin(2 * Math.PI * 440 * i / sampleRate);
679
- samples[i] = value; // Channel 0
680
- samples[numberOfFrames + i] = value; // Channel 1
681
- }
682
- const audioData = new AudioData({
683
- format: 'f32-planar',
684
- sampleRate,
685
- numberOfChannels,
686
- numberOfFrames,
687
- timestamp: 0,
688
- data: new Uint8Array(samples.buffer),
689
- });
690
- encoder.encode(audioData);
691
- audioData.close();
692
- await encoder.flush();
693
- encoder.close();
694
- expect(encodedChunks.length).toBeGreaterThan(0);
695
- }, 30000);
696
- it('should encode from s16-planar format', async () => {
697
- const sampleRate = 48000;
698
- const numberOfChannels = 2;
699
- const numberOfFrames = 960;
700
- const encodedChunks = [];
701
- const encoder = new AudioEncoder({
702
- output: (chunk) => encodedChunks.push(chunk),
703
- error: (err) => { throw err; },
704
- });
705
- encoder.configure({
706
- codec: 'opus',
707
- sampleRate,
708
- numberOfChannels,
709
- bitrate: 64000,
710
- });
711
- // Create s16-planar samples
712
- const samples = new Int16Array(numberOfFrames * numberOfChannels);
713
- for (let i = 0; i < numberOfFrames; i++) {
714
- const value = Math.round(Math.sin(2 * Math.PI * 440 * i / sampleRate) * 32767);
715
- samples[i] = value; // Channel 0
716
- samples[numberOfFrames + i] = value; // Channel 1
717
- }
718
- const audioData = new AudioData({
719
- format: 's16-planar',
720
- sampleRate,
721
- numberOfChannels,
722
- numberOfFrames,
723
- timestamp: 0,
724
- data: new Uint8Array(samples.buffer),
725
- });
726
- encoder.encode(audioData);
727
- audioData.close();
728
- await encoder.flush();
729
- encoder.close();
730
- expect(encodedChunks.length).toBeGreaterThan(0);
731
- }, 30000);
732
- });
733
- //# sourceMappingURL=AudioDecoder.test.js.map