@qvac/decoder-audio 0.4.0 → 0.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/README.md +1 -1
- package/constants.d.ts +2 -3
- package/constants.js +20 -25
- package/index.d.ts +106 -54
- package/index.js +324 -391
- package/package.json +29 -15
- package/test/mobile/integration-runtime.cjs +24 -0
- package/utils/createStreamAccumulator.d.ts +24 -0
- package/utils/createStreamAccumulator.js +44 -57
- package/utils/error.d.ts +19 -0
- package/utils/error.js +75 -79
package/package.json
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qvac/decoder-audio",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Tether",
|
|
7
7
|
"type": "commonjs",
|
|
8
8
|
"main": "index.js",
|
|
9
9
|
"scripts": {
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
10
|
+
"build": "npm run build:ts",
|
|
11
|
+
"build:ts": "tsc -p tsconfig.build.json",
|
|
12
|
+
"check:generated": "node scripts/check-generated.mjs",
|
|
13
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
14
|
+
"test:dts": "tsc --noEmit -p tsconfig.dts.json",
|
|
15
|
+
"test:types": "npm run typecheck && npm run test:dts && npm run check:generated",
|
|
16
|
+
"test:unit": "npm run build:ts && brittle-bare test/unit/*.test.js && npm run test:package",
|
|
17
|
+
"test:package": "node --test test/package/package-contract.test.js",
|
|
18
|
+
"test": "npm run test:types && npm run test:unit && npm run test:integration",
|
|
13
19
|
"coverage:unit": "brittle-bare --coverage --cov-dir=coverage/unit test/unit/*.test.js && mkdir -p .nyc_output && cp coverage/unit/coverage-final.json .nyc_output/out.json && npx nyc report --reporter=html --report-dir=coverage/html",
|
|
14
20
|
"coverage": "brittle-bare --coverage --cov-dir=coverage/unit test/unit/*.test.js && mkdir -p .nyc_output && cp coverage/unit/coverage-final.json .nyc_output/out.json && npx nyc report --reporter=html --report-dir=coverage/html",
|
|
15
|
-
"lint": "
|
|
16
|
-
"lint:
|
|
17
|
-
"
|
|
21
|
+
"lint": "npm run lint:js && npm run lint:ts && npm run test:types",
|
|
22
|
+
"lint:js": "prettier --check \"test/**/*.js\" \"scripts/**/*.js\" && lunte \"test/**/*.js\" \"scripts/**/*.js\"",
|
|
23
|
+
"lint:ts": "eslint \"src/**/*.ts\" --max-warnings=0",
|
|
24
|
+
"lint:ts:fix": "eslint \"src/**/*.ts\" --fix",
|
|
25
|
+
"format": "prettier --write \"test/**/*.js\" \"scripts/**/*.js\"",
|
|
26
|
+
"test:integration": "npm run build:ts && npm run test:integration:generate && brittle-bare test/integration/*.test.js",
|
|
18
27
|
"test:integration:generate": "brittle -r test/integration/all.js test/integration/*.test.js && npm run test:mobile:generate",
|
|
19
28
|
"test:mobile:generate": "bare ./scripts/generate-mobile-integration-tests.js",
|
|
20
29
|
"test:mobile:validate": "node scripts/validate-mobile-tests.js"
|
|
@@ -37,23 +46,28 @@
|
|
|
37
46
|
},
|
|
38
47
|
"devDependencies": {
|
|
39
48
|
"@types/node": "^22.14.1",
|
|
49
|
+
"bare-abort-controller": "^1.1.2",
|
|
40
50
|
"bare-os": "^3.6.2",
|
|
41
|
-
"bare-
|
|
51
|
+
"bare-process": "^4.2.2",
|
|
42
52
|
"brittle": "^3.13.1",
|
|
53
|
+
"eslint": "^9.39.4",
|
|
54
|
+
"eslint-import-resolver-typescript": "^4.4.5",
|
|
55
|
+
"eslint-plugin-import": "^2.32.0",
|
|
56
|
+
"lunte": "^1.8.0",
|
|
43
57
|
"nyc": "^17.1.0",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
58
|
+
"prettier": "^3.6.2",
|
|
59
|
+
"prettier-config-holepunch": "^2.0.0",
|
|
60
|
+
"typescript": "^5.9.3",
|
|
61
|
+
"typescript-eslint": "^8.63.0"
|
|
46
62
|
},
|
|
47
63
|
"dependencies": {
|
|
48
64
|
"@qvac/error": "^0.1.0",
|
|
49
|
-
"@qvac/infer-base": "^0.
|
|
65
|
+
"@qvac/infer-base": "^0.6.0",
|
|
50
66
|
"@qvac/logging": "^0.1.0",
|
|
51
|
-
"bare-assert": "^1.1.0",
|
|
52
|
-
"bare-channel": "^5.2.2",
|
|
53
67
|
"bare-ffmpeg": "^1.0.0-32",
|
|
54
68
|
"bare-fs": "^4.5.1",
|
|
55
69
|
"bare-path": "^3.0.0",
|
|
56
|
-
"bare-
|
|
70
|
+
"bare-url": "^2.1.6"
|
|
57
71
|
},
|
|
58
72
|
"repository": {
|
|
59
73
|
"type": "git",
|
|
@@ -61,6 +75,6 @@
|
|
|
61
75
|
"directory": "packages/decoder-audio"
|
|
62
76
|
},
|
|
63
77
|
"bugs": "https://github.com/tetherto/qvac/issues",
|
|
64
|
-
"homepage": "https://
|
|
78
|
+
"homepage": "https://qvac.tether.io",
|
|
65
79
|
"types": "index.d.ts"
|
|
66
80
|
}
|
|
@@ -4,6 +4,30 @@ const path = require('bare-path')
|
|
|
4
4
|
const fs = require('bare-fs')
|
|
5
5
|
const { pathToFileURL } = require('bare-url')
|
|
6
6
|
|
|
7
|
+
// A dlopen failure (or any unhandled error) MUST fail the run, not just get
|
|
8
|
+
// logged: Bare surfaces addon-load failures as an unhandledRejection on the
|
|
9
|
+
// worklet thread. Without a hard exit the run can SIGABRT (ambiguous timeout)
|
|
10
|
+
// or a log-only handler would falsely pass. Catch, record the first failure,
|
|
11
|
+
// and force a non-zero exit on drain.
|
|
12
|
+
let _integrationFatalError = null
|
|
13
|
+
const _bareHost = typeof globalThis !== 'undefined' ? globalThis.Bare : undefined
|
|
14
|
+
if (_bareHost && typeof _bareHost.on === 'function') {
|
|
15
|
+
_bareHost.on('unhandledRejection', (reason) => {
|
|
16
|
+
if (!_integrationFatalError) _integrationFatalError = reason || new Error('unhandledRejection')
|
|
17
|
+
console.error('[integration-runner] Unhandled rejection:', reason instanceof Error ? reason.stack : reason)
|
|
18
|
+
})
|
|
19
|
+
_bareHost.on('uncaughtException', (err) => {
|
|
20
|
+
if (!_integrationFatalError) _integrationFatalError = err || new Error('uncaughtException')
|
|
21
|
+
console.error('[integration-runner] Uncaught exception:', err instanceof Error ? err.stack : err)
|
|
22
|
+
})
|
|
23
|
+
_bareHost.on('beforeExit', () => {
|
|
24
|
+
if (!_integrationFatalError) return
|
|
25
|
+
console.error('[integration-runner] FATAL: failing run due to an earlier unhandled error.')
|
|
26
|
+
if (typeof _bareHost.exit === 'function') _bareHost.exit(1)
|
|
27
|
+
else if (typeof globalThis.process !== 'undefined' && globalThis.process.exit) globalThis.process.exit(1)
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
7
31
|
async function runIntegrationModule (relativeModulePath, options = {}) {
|
|
8
32
|
const modulePath = path.join(__dirname, relativeModulePath)
|
|
9
33
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a stream accumulator that processes incoming audio data in chunks of a specified size.
|
|
3
|
+
* The accumulator maintains a buffer of incoming data and emits chunks when the target size is reached.
|
|
4
|
+
*
|
|
5
|
+
* @param options - Configuration options for the stream accumulator
|
|
6
|
+
* @returns An object with methods to process data and finish the stream
|
|
7
|
+
* @throws {QvacErrorDecoderAudio} If the target buffer size is smaller than the minimum required size
|
|
8
|
+
*/
|
|
9
|
+
declare function createStreamAccumulator({ onChunk, onFinish, targetBufferSize, }: createStreamAccumulator.StreamAccumulatorOptions): createStreamAccumulator.StreamAccumulator;
|
|
10
|
+
declare namespace createStreamAccumulator {
|
|
11
|
+
interface StreamAccumulatorOptions {
|
|
12
|
+
/** Called with each full chunk, and with the remainder on `finish()`. */
|
|
13
|
+
onChunk: (chunk: Uint8Array) => void | Promise<void>;
|
|
14
|
+
/** Called once after the final chunk has been emitted. */
|
|
15
|
+
onFinish: () => void | Promise<void>;
|
|
16
|
+
/** Chunk size in bytes. Must be at least 64000. */
|
|
17
|
+
targetBufferSize?: number;
|
|
18
|
+
}
|
|
19
|
+
interface StreamAccumulator {
|
|
20
|
+
processData(data: Buffer): Promise<void>;
|
|
21
|
+
finish(): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export = createStreamAccumulator;
|
|
@@ -1,64 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const TARGET_SECONDS = 1 // Desired chunk size in seconds
|
|
4
|
-
const SAMPLE_RATE = 16000 // PCM audio sample rate
|
|
5
|
-
const BYTES_PER_SAMPLE = 4 // PCM S16LE (16-bit)
|
|
6
|
-
const TARGET_BUFFER_SIZE = TARGET_SECONDS * SAMPLE_RATE * BYTES_PER_SAMPLE
|
|
7
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
const error_1 = require("./error");
|
|
3
|
+
const TARGET_SECONDS = 1; // Desired chunk size in seconds
|
|
4
|
+
const SAMPLE_RATE = 16000; // PCM audio sample rate
|
|
5
|
+
const BYTES_PER_SAMPLE = 4; // PCM S16LE (16-bit)
|
|
6
|
+
const TARGET_BUFFER_SIZE = TARGET_SECONDS * SAMPLE_RATE * BYTES_PER_SAMPLE;
|
|
8
7
|
/**
|
|
9
8
|
* Creates a stream accumulator that processes incoming audio data in chunks of a specified size.
|
|
10
9
|
* The accumulator maintains a buffer of incoming data and emits chunks when the target size is reached.
|
|
11
10
|
*
|
|
12
|
-
* @param
|
|
13
|
-
* @
|
|
14
|
-
* @
|
|
15
|
-
* @param {number} [options.targetBufferSize=TARGET_BUFFER_SIZE] - Target size for each chunk in bytes
|
|
16
|
-
* @returns {Object} An object with methods to process data and finish the stream
|
|
17
|
-
* @throws {Error} If the target buffer size is smaller than the minimum required size
|
|
11
|
+
* @param options - Configuration options for the stream accumulator
|
|
12
|
+
* @returns An object with methods to process data and finish the stream
|
|
13
|
+
* @throws {QvacErrorDecoderAudio} If the target buffer size is smaller than the minimum required size
|
|
18
14
|
*/
|
|
19
|
-
function createStreamAccumulator
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
targetBufferSize = TARGET_BUFFER_SIZE
|
|
23
|
-
}) {
|
|
24
|
-
if (targetBufferSize < TARGET_BUFFER_SIZE) {
|
|
25
|
-
throw new QvacErrorDecoderAudio({ code: ERR_CODES.BUFFER_SIZE_TOO_SMALL })
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
let accumulator = Buffer.alloc(0)
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
/**
|
|
32
|
-
* Process incoming data and emit chunks when target size is reached.
|
|
33
|
-
* Accumulates incoming data until it reaches the target buffer size,
|
|
34
|
-
* then emits a chunk and continues with the remaining data.
|
|
35
|
-
*
|
|
36
|
-
* @param {Buffer} data - The incoming data to process
|
|
37
|
-
* @returns {Promise<void>} A promise that resolves when the chunk is processed
|
|
38
|
-
*/
|
|
39
|
-
async processData (data) {
|
|
40
|
-
accumulator = Buffer.concat([accumulator, data])
|
|
41
|
-
|
|
42
|
-
while (accumulator.length >= targetBufferSize) {
|
|
43
|
-
const chunk = accumulator.subarray(0, targetBufferSize)
|
|
44
|
-
await onChunk(new Uint8Array(chunk))
|
|
45
|
-
accumulator = accumulator.subarray(targetBufferSize)
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Finish processing and emit any remaining data.
|
|
51
|
-
* Processes any remaining data in the accumulator and calls the finish callback.
|
|
52
|
-
*
|
|
53
|
-
* @returns {Promise<void>} A promise that resolves when all remaining data is processed
|
|
54
|
-
*/
|
|
55
|
-
async finish () {
|
|
56
|
-
if (accumulator.length > 0) {
|
|
57
|
-
await onChunk(new Uint8Array(accumulator))
|
|
58
|
-
}
|
|
59
|
-
await onFinish()
|
|
15
|
+
function createStreamAccumulator({ onChunk, onFinish, targetBufferSize = TARGET_BUFFER_SIZE, }) {
|
|
16
|
+
if (targetBufferSize < TARGET_BUFFER_SIZE) {
|
|
17
|
+
throw new error_1.QvacErrorDecoderAudio({ code: error_1.ERR_CODES.BUFFER_SIZE_TOO_SMALL });
|
|
60
18
|
}
|
|
61
|
-
|
|
19
|
+
let accumulator = Buffer.alloc(0);
|
|
20
|
+
return {
|
|
21
|
+
/**
|
|
22
|
+
* Process incoming data and emit chunks when target size is reached.
|
|
23
|
+
* Accumulates incoming data until it reaches the target buffer size,
|
|
24
|
+
* then emits a chunk and continues with the remaining data.
|
|
25
|
+
*
|
|
26
|
+
* @param data - The incoming data to process
|
|
27
|
+
* @returns A promise that resolves when the chunk is processed
|
|
28
|
+
*/
|
|
29
|
+
async processData(data) {
|
|
30
|
+
accumulator = Buffer.concat([accumulator, data]);
|
|
31
|
+
while (accumulator.length >= targetBufferSize) {
|
|
32
|
+
const chunk = accumulator.subarray(0, targetBufferSize);
|
|
33
|
+
await onChunk(new Uint8Array(chunk));
|
|
34
|
+
accumulator = accumulator.subarray(targetBufferSize);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
/**
|
|
38
|
+
* Finish processing and emit any remaining data.
|
|
39
|
+
* Processes any remaining data in the accumulator and calls the finish callback.
|
|
40
|
+
*
|
|
41
|
+
* @returns A promise that resolves when all remaining data is processed
|
|
42
|
+
*/
|
|
43
|
+
async finish() {
|
|
44
|
+
if (accumulator.length > 0) {
|
|
45
|
+
await onChunk(new Uint8Array(accumulator));
|
|
46
|
+
}
|
|
47
|
+
await onFinish();
|
|
48
|
+
},
|
|
49
|
+
};
|
|
62
50
|
}
|
|
63
|
-
|
|
64
|
-
module.exports = createStreamAccumulator
|
|
51
|
+
module.exports = createStreamAccumulator;
|
package/utils/error.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import QvacError = require("@qvac/error");
|
|
2
|
+
declare const QvacErrorBase: typeof QvacError.QvacErrorBase;
|
|
3
|
+
export declare class QvacErrorDecoderAudio extends QvacErrorBase {
|
|
4
|
+
}
|
|
5
|
+
export declare const ERR_CODES: Readonly<{
|
|
6
|
+
FAILED_TO_LOAD_WEIGHTS: 11001;
|
|
7
|
+
FAILED_TO_ACTIVATE: 11002;
|
|
8
|
+
FAILED_TO_PAUSE: 11003;
|
|
9
|
+
FAILED_TO_CANCEL: 11004;
|
|
10
|
+
FAILED_TO_APPEND: 11005;
|
|
11
|
+
FAILED_TO_GET_STATUS: 11006;
|
|
12
|
+
FAILED_TO_DESTROY: 11007;
|
|
13
|
+
BUFFER_SIZE_TOO_SMALL: 11008;
|
|
14
|
+
UNSUPPORTED_AUDIO_FORMAT: 11009;
|
|
15
|
+
DECODER_NOT_LOADED: 11010;
|
|
16
|
+
STREAM_INDEX_OUT_OF_BOUNDS: 11011;
|
|
17
|
+
JOB_CANCELLED: 11012;
|
|
18
|
+
}>;
|
|
19
|
+
export {};
|
package/utils/error.js
CHANGED
|
@@ -1,81 +1,77 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ERR_CODES = exports.QvacErrorDecoderAudio = void 0;
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-require-imports -- @qvac/error exposes a CommonJS export shape. */
|
|
5
|
+
const QvacError = require("@qvac/error");
|
|
6
|
+
/* eslint-enable @typescript-eslint/no-require-imports */
|
|
7
|
+
const { QvacErrorBase, addCodes } = QvacError;
|
|
8
|
+
class QvacErrorDecoderAudio extends QvacErrorBase {
|
|
9
|
+
}
|
|
10
|
+
exports.QvacErrorDecoderAudio = QvacErrorDecoderAudio;
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports -- package metadata is read from the package root at runtime.
|
|
12
|
+
const { name, version } = require("../package.json");
|
|
8
13
|
// This library has error code range from 11,001 to 12,000
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
})
|
|
23
|
-
|
|
14
|
+
exports.ERR_CODES = Object.freeze({
|
|
15
|
+
FAILED_TO_LOAD_WEIGHTS: 11001,
|
|
16
|
+
FAILED_TO_ACTIVATE: 11002,
|
|
17
|
+
FAILED_TO_PAUSE: 11003,
|
|
18
|
+
FAILED_TO_CANCEL: 11004,
|
|
19
|
+
FAILED_TO_APPEND: 11005,
|
|
20
|
+
FAILED_TO_GET_STATUS: 11006,
|
|
21
|
+
FAILED_TO_DESTROY: 11007,
|
|
22
|
+
BUFFER_SIZE_TOO_SMALL: 11008,
|
|
23
|
+
UNSUPPORTED_AUDIO_FORMAT: 11009,
|
|
24
|
+
DECODER_NOT_LOADED: 11010,
|
|
25
|
+
STREAM_INDEX_OUT_OF_BOUNDS: 11011,
|
|
26
|
+
JOB_CANCELLED: 11012,
|
|
27
|
+
});
|
|
24
28
|
addCodes({
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}, {
|
|
74
|
-
name,
|
|
75
|
-
version
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
module.exports = {
|
|
79
|
-
ERR_CODES,
|
|
80
|
-
QvacErrorDecoderAudio
|
|
81
|
-
}
|
|
29
|
+
[exports.ERR_CODES.FAILED_TO_LOAD_WEIGHTS]: {
|
|
30
|
+
name: "FAILED_TO_LOAD_WEIGHTS",
|
|
31
|
+
message: (message) => `Failed to load weights, error: ${message}`,
|
|
32
|
+
},
|
|
33
|
+
[exports.ERR_CODES.FAILED_TO_ACTIVATE]: {
|
|
34
|
+
name: "FAILED_TO_ACTIVATE",
|
|
35
|
+
message: (message) => `Failed to activate model, error: ${message}`,
|
|
36
|
+
},
|
|
37
|
+
[exports.ERR_CODES.FAILED_TO_PAUSE]: {
|
|
38
|
+
name: "FAILED_TO_PAUSE",
|
|
39
|
+
message: (message) => `Failed to pause inference, error: ${message}`,
|
|
40
|
+
},
|
|
41
|
+
[exports.ERR_CODES.FAILED_TO_CANCEL]: {
|
|
42
|
+
name: "FAILED_TO_CANCEL",
|
|
43
|
+
message: (message) => `Failed to cancel inference, error: ${message}`,
|
|
44
|
+
},
|
|
45
|
+
[exports.ERR_CODES.FAILED_TO_APPEND]: {
|
|
46
|
+
name: "FAILED_TO_APPEND",
|
|
47
|
+
message: (message) => `Failed to append data to processing queue, error: ${message}`,
|
|
48
|
+
},
|
|
49
|
+
[exports.ERR_CODES.FAILED_TO_GET_STATUS]: {
|
|
50
|
+
name: "FAILED_TO_GET_STATUS",
|
|
51
|
+
message: (message) => `Failed to get decoder status, error: ${message}`,
|
|
52
|
+
},
|
|
53
|
+
[exports.ERR_CODES.FAILED_TO_DESTROY]: {
|
|
54
|
+
name: "FAILED_TO_DESTROY",
|
|
55
|
+
message: (message) => `Failed to destroy instance, error: ${message}`,
|
|
56
|
+
},
|
|
57
|
+
[exports.ERR_CODES.BUFFER_SIZE_TOO_SMALL]: {
|
|
58
|
+
name: "BUFFER_SIZE_TOO_SMALL",
|
|
59
|
+
message: "Target buffer size is too small",
|
|
60
|
+
},
|
|
61
|
+
[exports.ERR_CODES.UNSUPPORTED_AUDIO_FORMAT]: {
|
|
62
|
+
name: "UNSUPPORTED_AUDIO_FORMAT",
|
|
63
|
+
message: (format) => `Unsupported audio format: ${format}`,
|
|
64
|
+
},
|
|
65
|
+
[exports.ERR_CODES.DECODER_NOT_LOADED]: {
|
|
66
|
+
name: "DECODER_NOT_LOADED",
|
|
67
|
+
message: "Decoder not loaded. Call load() first.",
|
|
68
|
+
},
|
|
69
|
+
[exports.ERR_CODES.STREAM_INDEX_OUT_OF_BOUNDS]: {
|
|
70
|
+
name: "STREAM_INDEX_OUT_OF_BOUNDS",
|
|
71
|
+
message: (index) => `Stream index out of bounds: ${index}`,
|
|
72
|
+
},
|
|
73
|
+
[exports.ERR_CODES.JOB_CANCELLED]: {
|
|
74
|
+
name: "JOB_CANCELLED",
|
|
75
|
+
message: "Decoder job cancelled",
|
|
76
|
+
},
|
|
77
|
+
}, { name, version });
|