@audio/encode 1.6.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dmitry Iv.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # @audio/encode [![test](https://github.com/audiojs/encode/actions/workflows/test.js.yml/badge.svg)](https://github.com/audiojs/encode/actions/workflows/test.js.yml)
2
+
3
+ Encode raw audio samples to any format.<br>
4
+ JS / WASM – no ffmpeg, no native bindings, works in both node and browser.<br>
5
+ Small API, minimal size, near-native performance, stream encoding.
6
+
7
+ [![npm install @audio/encode](https://nodei.co/npm/encode-audio.png?mini=true)](https://npmjs.org/package/@audio/encode/)
8
+
9
+ ```js
10
+ import encode from '@audio/encode';
11
+
12
+ const buf = await encode.wav(channelData, { sampleRate: 44100 });
13
+ ```
14
+
15
+ #### Supported formats:
16
+
17
+ | Format | Package | Engine |
18
+ |--------|---------|--------|
19
+ | WAV | [@audio/encode-wav](https://npmjs.com/package/@audio/encode-wav) | JS |
20
+ | MP3 | [@audio/encode-mp3](https://npmjs.com/package/@audio/encode-mp3) | WASM |
21
+ | OGG Vorbis | [@audio/encode-ogg](https://npmjs.com/package/@audio/encode-ogg) | WASM |
22
+ | Opus | [@audio/encode-opus](https://npmjs.com/package/@audio/encode-opus) | WASM |
23
+ | WebM | [@audio/encode-webm](https://npmjs.com/package/@audio/encode-webm) | WASM (Opus) |
24
+ | FLAC | [@audio/encode-flac](https://npmjs.com/package/@audio/encode-flac) | WASM |
25
+ | AAC | [@audio/encode-aac](https://npmjs.com/package/@audio/encode-aac) | WebCodecs* |
26
+ | AIFF | [@audio/encode-aiff](https://npmjs.com/package/@audio/encode-aiff) | JS |
27
+ | CAF | [@audio/encode-caf](https://npmjs.com/package/@audio/encode-caf) | JS |
28
+ | QOA | [@audio/encode-qoa](https://npmjs.com/package/@audio/encode-qoa) | JS |
29
+
30
+ <sub>* AAC uses the native [WebCodecs](https://developer.mozilla.org/en-US/docs/Web/API/AudioEncoder) `AudioEncoder` — browser-only (Chromium/Safari), throws in Node.</sub>
31
+
32
+ ### Whole-file encode
33
+
34
+ Specify the format as method name. Input is _Float32Array[]_ (one per channel), a single _Float32Array_ (mono), or an [AudioBuffer](https://npmjs.com/package/audio-buffer).
35
+
36
+ ```js
37
+ import encode from '@audio/encode';
38
+
39
+ const wav = await encode.wav(channelData, { sampleRate: 44100 });
40
+ const aiff = await encode.aiff(channelData, { sampleRate: 44100 });
41
+ const caf = await encode.caf(channelData, { sampleRate: 44100 });
42
+ const mp3 = await encode.mp3(channelData, { sampleRate: 44100, bitrate: 128 });
43
+ const ogg = await encode.ogg(channelData, { sampleRate: 44100, quality: 5 });
44
+ const flac = await encode.flac(channelData, { sampleRate: 44100 });
45
+ const opus = await encode.opus(channelData, { sampleRate: 48000, bitrate: 96 });
46
+ const webm = await encode.webm(channelData, { sampleRate: 48000, bitrate: 96 });
47
+ const qoa = await encode.qoa(channelData, { sampleRate: 44100 });
48
+ const aac = await encode.aac(channelData, { sampleRate: 44100, bitrate: 128 }); // browser only
49
+ ```
50
+
51
+ `encode.formats` lists the supported names and `encode.mime` maps each to a MIME type — handy for format-agnostic pipelines.
52
+
53
+ ### Chunked encoding
54
+
55
+ Call with just options (no data) to create a streaming encoder:
56
+
57
+ ```js
58
+ import encode from '@audio/encode';
59
+
60
+ const enc = await encode.mp3({ sampleRate: 44100, bitrate: 128 });
61
+
62
+ const a = await enc(chunk1); // Uint8Array
63
+ const b = await enc(chunk2);
64
+ const c = await enc(null); // end of stream — flush + free
65
+
66
+ // explicit control: enc.flush(), enc.free()
67
+ ```
68
+
69
+ ### Streaming
70
+
71
+ Pass an async iterable as data — returns an async generator:
72
+
73
+ ```js
74
+ import encode from '@audio/encode'
75
+
76
+ for await (let buf of encode.mp3(audioSource, { sampleRate: 44100, bitrate: 128 })) {
77
+ // buf is Uint8Array
78
+ }
79
+ ```
80
+
81
+ Works with any async iterable source.
82
+
83
+ ### Options
84
+
85
+ | Option | Description | Applies to |
86
+ |--------|-------------|------------|
87
+ | `sampleRate` | Output sample rate (required) | all |
88
+ | `bitrate` | Target bitrate in kbps | mp3, opus, webm, aac |
89
+ | `quality` | Quality 0–10 (VBR) | ogg, mp3 |
90
+ | `channels` | Output channel count | all |
91
+ | `bitDepth` | Bit depth: 16/24/32 (wav), 16/24 (aiff, flac), 16/32 (caf) | wav, aiff, flac, caf |
92
+ | `compression` | FLAC compression level 0–8 | flac |
93
+ | `application` | `'audio'`, `'voip'`, or `'lowdelay'` | opus, webm |
94
+ | `meta` | Tags (see below) | wav, mp3, flac, aiff, ogg, opus |
95
+
96
+
97
+ ### Metadata
98
+
99
+ Pass `meta` (and, for `wav`, `markers`/`regions`) straight to the encoder:
100
+
101
+ ```js
102
+ let bytes = await encode.flac(channelData, {
103
+ sampleRate: 44100,
104
+ meta: { title: 'Hare Krishna', artist: 'Prabhupada', year: '1966' }
105
+ })
106
+ ```
107
+
108
+ Tags work for `wav`, `mp3`, `flac`, `aiff`, `ogg` and `opus`. Cue `markers` and `regions` are `wav`-only. `opus` bakes tags into the OpusTags header at encode time (stays fully streaming); the others splice tags into the finished file — so passing `meta` to a **streaming/chunked** encode of `wav`/`mp3`/`flac`/`aiff`/`ogg` buffers the output and emits it on flush.
109
+
110
+ You can also tag already-encoded bytes via `@audio/encode/meta`:
111
+
112
+ ```js
113
+ import { wav } from '@audio/encode/meta'
114
+
115
+ let out = wav(bytes, {
116
+ meta: { title: 'Hare Krishna', artist: 'Prabhupada', year: '1966' },
117
+ markers: [{ sample: 44100, label: 'verse' }],
118
+ regions: [{ sample: 88200, length: 44100, label: 'chorus' }]
119
+ })
120
+ ```
121
+
122
+ Each codec sub-package also exposes its writer directly:
123
+
124
+ ```js
125
+ import { writeMeta } from '@audio/encode-mp3/meta'
126
+ let tagged = writeMeta(mp3Bytes, { meta: { title: 'foo' } })
127
+ ```
128
+
129
+
130
+ ## See also
131
+
132
+ * [decode](https://github.com/audiojs/decode) – decode any audio format to raw samples.
133
+ * [wasm-media-encoders](https://github.com/arseneyr/wasm-media-encoders) – compact WASM MP3 & Vorbis encoders.
134
+ * [AudioEncoder](https://developer.mozilla.org/en-US/docs/Web/API/AudioEncoder) – native WebCodecs encoder API.
135
+
136
+ ## License
137
+
138
+ [MIT](LICENSE)
139
+
140
+ <a href="https://github.com/krishnized/license/">ॐ</a>
@@ -0,0 +1,106 @@
1
+ type AudioInput = Float32Array[] | Float32Array | { numberOfChannels: number; getChannelData(i: number): Float32Array };
2
+
3
+ export interface Meta {
4
+ title?: string; artist?: string; album?: string; albumartist?: string;
5
+ composer?: string; genre?: string; year?: string | number; track?: string | number;
6
+ disc?: string | number; bpm?: string | number; key?: string; comment?: string;
7
+ copyright?: string; isrc?: string; publisher?: string; software?: string; lyrics?: string;
8
+ pictures?: { mime?: string; description?: string; type?: number; data: Uint8Array }[];
9
+ [key: string]: any;
10
+ }
11
+
12
+ export interface Marker { sample: number; label?: string; }
13
+ export interface Region { sample: number; length: number; label?: string; }
14
+
15
+ export interface EncodeOptions {
16
+ /** Output sample rate (required). */
17
+ sampleRate: number;
18
+ /** Output channel count. */
19
+ channels?: number;
20
+ /** Target bitrate in kbps (lossy: mp3, opus, webm, aac). */
21
+ bitrate?: number;
22
+ /** Quality 0-10 (VBR, format-specific: ogg, mp3). */
23
+ quality?: number;
24
+ /** Bit depth: 16|24|32 for wav, 16|24 for aiff/flac, 16|32 for caf. */
25
+ bitDepth?: number;
26
+ /** FLAC compression level 0-8. */
27
+ compression?: number;
28
+ /** Opus/WebM application: 'audio', 'voip', 'lowdelay'. */
29
+ application?: string;
30
+ /** Tags. Baked in for opus; for wav/mp3/flac/aiff/ogg also available via encode-audio/meta. */
31
+ meta?: Meta;
32
+ /** Cue markers (wav). */
33
+ markers?: Marker[];
34
+ /** Labeled regions (wav). */
35
+ regions?: Region[];
36
+ [key: string]: any;
37
+ }
38
+
39
+ export interface StreamEncoder {
40
+ /** Encode a chunk of audio. */
41
+ (channelData: AudioInput): Promise<Uint8Array>;
42
+ /** Flush remaining data, finalize, and free resources. */
43
+ (): Promise<Uint8Array>;
44
+ /** Flush without freeing. */
45
+ flush(): Promise<Uint8Array>;
46
+ /** Free resources without flushing. */
47
+ free(): void;
48
+ }
49
+
50
+ export interface FormatEncoder {
51
+ /** Whole-file encode. */
52
+ (channelData: AudioInput, opts: EncodeOptions): Promise<Uint8Array>;
53
+ /** Chunked encode from async iterable. */
54
+ (source: AsyncIterable<AudioInput>, opts: EncodeOptions): AsyncGenerator<Uint8Array>;
55
+ /** Create streaming encoder. */
56
+ (opts: EncodeOptions): Promise<StreamEncoder>;
57
+ }
58
+
59
+ declare const encode: {
60
+ /** Whole-file encode. */
61
+ (format: string, channelData: AudioInput, opts: EncodeOptions): Promise<Uint8Array>;
62
+ /** Chunked encode from async iterable. */
63
+ (format: string, source: AsyncIterable<AudioInput>, opts: EncodeOptions): AsyncGenerator<Uint8Array>;
64
+ /** Create streaming encoder. */
65
+ (format: string, opts: EncodeOptions): Promise<StreamEncoder>;
66
+
67
+ wav: FormatEncoder;
68
+ aiff: FormatEncoder;
69
+ caf: FormatEncoder;
70
+ mp3: FormatEncoder;
71
+ ogg: FormatEncoder;
72
+ flac: FormatEncoder;
73
+ opus: FormatEncoder;
74
+ /** WebM (Opus). */
75
+ webm: FormatEncoder;
76
+ /** AAC (ADTS) — browser-only via WebCodecs; throws in Node. */
77
+ aac: FormatEncoder;
78
+ /** QOA (Quite OK Audio). */
79
+ qoa: FormatEncoder;
80
+ /** Supported format names. */
81
+ formats: string[];
82
+ /** Format → MIME type. */
83
+ mime: Record<string, string>;
84
+ [format: string]: any;
85
+ };
86
+
87
+ export default encode;
88
+
89
+ /** Supported format names. */
90
+ export const formats: string[];
91
+ /** Format → MIME type map. */
92
+ export const mime: Record<string, string>;
93
+
94
+ /** Chunked encode from async iterable. */
95
+ export function encodeChunked(
96
+ source: AsyncIterable<AudioInput>,
97
+ format: string,
98
+ opts: EncodeOptions
99
+ ): AsyncGenerator<Uint8Array>;
100
+
101
+ /** Wrap codec callbacks into a StreamEncoder with lifecycle management. */
102
+ export function streamEncoder(
103
+ onEncode: (channels: Float32Array[]) => Uint8Array | Promise<Uint8Array>,
104
+ onFlush?: (() => Uint8Array | Promise<Uint8Array>) | null,
105
+ onFree?: (() => void) | null
106
+ ): StreamEncoder;
@@ -0,0 +1,215 @@
1
+ /**
2
+ * Audio encoder: whole-file and chunked
3
+ * @module encode-audio
4
+ *
5
+ * let buf = await encode.wav(channelData, { sampleRate: 44100 })
6
+ *
7
+ * for await (let bytes of encode.mp3(source, { sampleRate: 44100 })) { ... }
8
+ *
9
+ * let enc = await encode.mp3({ sampleRate: 44100, bitrate: 128 })
10
+ * let chunk = await enc(channelData)
11
+ * let final = await enc() // flush + free
12
+ */
13
+
14
+ const EMPTY = new Uint8Array(0)
15
+
16
+ /**
17
+ * Encode audio — delegates to format-specific encoder.
18
+ * encode('wav', channelData, { sampleRate }) → Promise<Uint8Array>
19
+ * encode('wav', source(), { sampleRate }) → AsyncGenerator<Uint8Array>
20
+ * encode('wav', { sampleRate }) → Promise<StreamEncoder>
21
+ */
22
+ function encode(format, data, opts) {
23
+ if (!encode[format]) throw Error('Unknown format: ' + format)
24
+ return encode[format](data, opts)
25
+ }
26
+ export default encode
27
+
28
+ function isAudioData(d) {
29
+ return d instanceof Float32Array || Array.isArray(d) || (d?.getChannelData && d?.numberOfChannels)
30
+ }
31
+
32
+ /**
33
+ * Encode a stream of PCM chunks to the given format.
34
+ * @param {AsyncIterable<Float32Array[]|Float32Array>} source
35
+ * @param {string} format
36
+ * @param {object} opts - encoder options (sampleRate required)
37
+ * @returns {AsyncGenerator<Uint8Array>}
38
+ */
39
+ async function* encodeChunked(source, format, opts) {
40
+ let enc = await encode[format](opts)
41
+ try {
42
+ for await (let chunk of source) {
43
+ let buf = await enc(chunk)
44
+ if (buf.length) yield buf
45
+ }
46
+ let final = await enc()
47
+ if (final.length) yield final
48
+ } catch (e) { enc.free(); throw e }
49
+ }
50
+ export { encodeChunked }
51
+
52
+ // --- format registration ---
53
+
54
+ // Lazy-loaded meta writers (per-format), keyed by format name. Loaded on first
55
+ // use when `meta`/`markers`/`regions` is passed to that format's encoder.
56
+ const META_WRITERS = {
57
+ wav: () => import('@audio/encode-wav/meta').then(m => m.writeMeta),
58
+ mp3: () => import('@audio/encode-mp3/meta').then(m => m.writeMeta),
59
+ flac: () => import('@audio/encode-flac/meta').then(m => m.writeMeta),
60
+ aiff: () => import('@audio/encode-aiff/meta').then(m => m.writeMeta),
61
+ ogg: () => import('@audio/encode-ogg/meta').then(m => m.writeMeta),
62
+ }
63
+
64
+ // Formats that bake metadata into the encoder itself (Ogg OpusTags) — streamed,
65
+ // never buffered. The rest splice meta post-hoc via META_WRITERS on flush.
66
+ const NATIVE_META = new Set(['opus'])
67
+
68
+ function reg(name, load) {
69
+ encode[name] = fmt(name, async (opts) => {
70
+ let { meta, markers, regions, ...rest } = opts || {}
71
+ let hasMeta = meta || markers?.length || regions?.length
72
+ let init = (await load()).default
73
+ let codec = await init(NATIVE_META.has(name) && hasMeta ? { ...rest, meta } : rest)
74
+ // Native-meta, no post-splice writer, or no meta requested: pass through.
75
+ if (NATIVE_META.has(name) || !META_WRITERS[name] || !hasMeta)
76
+ return streamEncoder(ch => codec.encode(ch), () => codec.flush(), () => codec.free())
77
+ // Meta requested: buffer encoder output, splice via writeMeta on flush.
78
+ let writeMeta = await META_WRITERS[name]()
79
+ let parts = []
80
+ return streamEncoder(
81
+ async ch => { let b = await codec.encode(ch); if (b?.length) parts.push(b); return EMPTY },
82
+ async () => {
83
+ let f = await codec.flush(); if (f?.length) parts.push(f)
84
+ let total = 0; for (let p of parts) total += p.length
85
+ let all = new Uint8Array(total), off = 0
86
+ for (let p of parts) { all.set(p, off); off += p.length }
87
+ return writeMeta(all, { meta: meta || {}, markers: markers || [], regions: regions || [] })
88
+ },
89
+ () => codec.free(),
90
+ )
91
+ })
92
+ }
93
+
94
+ reg('wav', () => import('@audio/encode-wav'))
95
+ reg('aiff', () => import('@audio/encode-aiff'))
96
+ reg('caf', () => import('@audio/encode-caf'))
97
+ reg('mp3', () => import('@audio/encode-mp3'))
98
+ reg('ogg', () => import('@audio/encode-ogg'))
99
+ reg('flac', () => import('@audio/encode-flac'))
100
+ reg('opus', () => import('@audio/encode-opus'))
101
+ reg('webm', () => import('@audio/encode-webm'))
102
+ reg('aac', () => import('@audio/encode-aac'))
103
+ reg('qoa', () => import('@audio/encode-qoa'))
104
+
105
+ // Supported format names and their MIME types — for format-agnostic pipelines.
106
+ export const formats = ['wav', 'aiff', 'caf', 'mp3', 'ogg', 'flac', 'opus', 'webm', 'aac', 'qoa']
107
+ export const mime = {
108
+ wav: 'audio/wav', aiff: 'audio/aiff', caf: 'audio/x-caf',
109
+ mp3: 'audio/mpeg', ogg: 'audio/ogg', flac: 'audio/flac',
110
+ opus: 'audio/ogg', webm: 'audio/webm', aac: 'audio/aac', qoa: 'audio/qoa',
111
+ }
112
+ encode.formats = formats
113
+ encode.mime = mime
114
+
115
+ /**
116
+ * Wrap a stream factory into whole-file encoder + streaming
117
+ * 1 arg (opts) → streaming encoder function
118
+ * 2 args (data, opts) → whole-file encode
119
+ */
120
+ function fmt(name, init) {
121
+ let fn = (data, opts) => {
122
+ // 1 arg = streaming: encode.mp3({ sampleRate })
123
+ if (!opts) return init(data)
124
+ // 2 args, async iterable = chunked: encode.mp3(source(), { sampleRate })
125
+ if (data && (typeof data[Symbol.asyncIterator] === 'function' || typeof data[Symbol.iterator] === 'function' && !isAudioData(data)))
126
+ return encodeChunked(data, name, opts)
127
+ // 2 args = whole-file: encode.mp3(channelData, { sampleRate })
128
+ return wholeFile(data, opts, init)
129
+ }
130
+ return fn
131
+ }
132
+
133
+ async function wholeFile(data, opts, init) {
134
+ if (!opts.sampleRate) throw Error('sampleRate is required')
135
+ let ch = channels(data)
136
+ if (!ch.length || !ch[0].length) return EMPTY
137
+ let enc = await init({ channels: ch.length, ...opts })
138
+ try {
139
+ let result = await enc(ch)
140
+ let flushed = await enc()
141
+ return merge(result, flushed)
142
+ } catch (e) { enc.free(); throw e }
143
+ }
144
+
145
+ // normalize input to Float32Array[]
146
+ function channels(data) {
147
+ if (!data) return []
148
+ if (Array.isArray(data)) {
149
+ if (data[0] instanceof Float32Array) return data
150
+ return []
151
+ }
152
+ if (data instanceof Float32Array) return [data]
153
+ // AudioBuffer or AudioBuffer-like ({ numberOfChannels, getChannelData })
154
+ if (data.getChannelData && data.numberOfChannels) {
155
+ let ch = []
156
+ for (let i = 0; i < data.numberOfChannels; i++) ch.push(data.getChannelData(i))
157
+ return ch
158
+ }
159
+ return []
160
+ }
161
+
162
+ /**
163
+ * StreamEncoder — a callable function:
164
+ * enc(channelData) — encode audio, returns Uint8Array
165
+ * enc() — flush + finalize + free
166
+ * enc.flush() — flush without freeing
167
+ * enc.free() — release without flushing
168
+ */
169
+ export function streamEncoder(onEncode, onFlush, onFree) {
170
+ let done = false
171
+ let fn = async (data) => {
172
+ if (data) {
173
+ if (done) throw Error('Encoder already freed')
174
+ let ch = channels(data)
175
+ try { return norm(await onEncode(ch)) }
176
+ catch (e) { done = true; onFree?.(); throw e }
177
+ }
178
+ // no args = end of stream
179
+ if (done) return EMPTY
180
+ done = true
181
+ try {
182
+ let result = onFlush ? norm(await onFlush()) : EMPTY
183
+ onFree?.()
184
+ return result
185
+ } catch (e) { onFree?.(); throw e }
186
+ }
187
+ fn.flush = async () => {
188
+ if (done) return EMPTY
189
+ return onFlush ? norm(await onFlush()) : EMPTY
190
+ }
191
+ fn.free = () => {
192
+ if (done) return
193
+ done = true
194
+ onFree?.()
195
+ }
196
+ return fn
197
+ }
198
+
199
+ // ensure Uint8Array
200
+ function norm(r) {
201
+ if (!r?.length) return EMPTY
202
+ if (r instanceof Uint8Array) return r
203
+ if (r.buffer) return new Uint8Array(r.buffer, r.byteOffset, r.byteLength)
204
+ return new Uint8Array(r)
205
+ }
206
+
207
+ // concat two Uint8Arrays
208
+ function merge(a, b) {
209
+ if (!b?.length) return a || EMPTY
210
+ if (!a?.length) return b || EMPTY
211
+ let out = new Uint8Array(a.length + b.length)
212
+ out.set(a)
213
+ out.set(b, a.length)
214
+ return out
215
+ }
package/meta.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Meta writers — re-export from codec packages.
3
+ * @module encode-audio/meta
4
+ *
5
+ * import { wav, mp3, flac, aiff, ogg } from 'encode-audio/meta'
6
+ * let out = wav(bytes, { meta, markers, regions })
7
+ *
8
+ * Opus bakes tags at encode time — pass `meta` to `encode.opus(...)` directly.
9
+ */
10
+
11
+ export { writeMeta as wav } from '@audio/encode-wav/meta'
12
+ export { writeMeta as mp3 } from '@audio/encode-mp3/meta'
13
+ export { writeMeta as flac } from '@audio/encode-flac/meta'
14
+ export { writeMeta as aiff } from '@audio/encode-aiff/meta'
15
+ export { writeMeta as ogg } from '@audio/encode-ogg/meta'
package/package.json ADDED
@@ -0,0 +1,90 @@
1
+ {
2
+ "name": "@audio/encode",
3
+ "version": "1.6.0",
4
+ "description": "Encode audio data in node or browser",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "main": "audio-encode.js",
8
+ "types": "audio-encode.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "browser": "./audio-encode.js",
12
+ "node": "./audio-encode.js",
13
+ "default": "./audio-encode.js"
14
+ },
15
+ "./stream": "./stream.js",
16
+ "./meta": "./meta.js",
17
+ "./package.json": "./package.json"
18
+ },
19
+ "files": [
20
+ "audio-encode.js",
21
+ "audio-encode.d.ts",
22
+ "stream.js",
23
+ "stream.d.ts",
24
+ "meta.js",
25
+ "LICENSE"
26
+ ],
27
+ "workspaces": [
28
+ "packages/*"
29
+ ],
30
+ "scripts": {
31
+ "test": "node test.js",
32
+ "test:all": "npm test --workspaces && npm test",
33
+ "publish:all": "for d in packages/* .; do id=$(node -p \"require('./$d/package.json').name+'@'+require('./$d/package.json').version\"); npm view \"$id\" version >/dev/null 2>&1 && echo \"skip $id\" || (cd \"$d\" && npm publish); done",
34
+ "build": "npm run build --workspaces --if-present"
35
+ },
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/audiojs/encode.git"
39
+ },
40
+ "keywords": [
41
+ "audio",
42
+ "encode",
43
+ "encoder",
44
+ "codec",
45
+ "wav",
46
+ "mp3",
47
+ "ogg",
48
+ "vorbis",
49
+ "opus",
50
+ "flac",
51
+ "aiff",
52
+ "caf",
53
+ "webm",
54
+ "aac",
55
+ "qoa",
56
+ "pcm",
57
+ "streaming"
58
+ ],
59
+ "author": "Dmitry Iv. <dfcreative@gmail.com>",
60
+ "license": "MIT",
61
+ "bugs": {
62
+ "url": "https://github.com/audiojs/encode/issues"
63
+ },
64
+ "homepage": "https://github.com/audiojs/encode#readme",
65
+ "dependencies": {
66
+ "@audio/encode-aac": "^1.0.0",
67
+ "@audio/encode-aiff": "^1.1.0",
68
+ "@audio/encode-caf": "^1.0.0",
69
+ "@audio/encode-flac": "^1.1.0",
70
+ "@audio/encode-mp3": "^1.1.0",
71
+ "@audio/encode-ogg": "^1.1.0",
72
+ "@audio/encode-opus": "^1.1.0",
73
+ "@audio/encode-qoa": "^1.0.0",
74
+ "@audio/encode-wav": "^1.2.0",
75
+ "@audio/encode-webm": "^1.0.0"
76
+ },
77
+ "devDependencies": {
78
+ "audio-buffer": "^7.3.0",
79
+ "audio-decode": "^4.0.0",
80
+ "audio-lena": "^3.0.0",
81
+ "esbuild": "^0.28.0",
82
+ "tst": "^9.2.2"
83
+ },
84
+ "publishConfig": {
85
+ "access": "public"
86
+ },
87
+ "engines": {
88
+ "node": ">=18"
89
+ }
90
+ }
package/stream.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { encodeChunked as default, encodeChunked } from './audio-encode.js';
package/stream.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Chunked encoder — re-exports encodeChunked from main module.
3
+ * @module encode-audio/stream
4
+ *
5
+ * for await (let bytes of encode.mp3(pcmSource, { sampleRate: 44100 })) { ... }
6
+ */
7
+ export { encodeChunked as default, encodeChunked } from './audio-encode.js'