@qvac/decoder-audio 0.2.9 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -43
- package/index.d.ts +34 -52
- package/index.js +0 -115
- package/lib/ffmpeg/ffmpeg-decoder.js +26 -0
- package/package.json +1 -7
- package/test/mobile/testAssets/corrupted.mp3 +0 -0
- package/binding.js +0 -3
- package/gstreamer.js +0 -131
- package/prebuilds/android-arm/qvac__decoder-audio.bare +0 -0
- package/prebuilds/android-arm64/qvac__decoder-audio.bare +0 -0
- package/prebuilds/android-ia32/qvac__decoder-audio.bare +0 -0
- package/prebuilds/android-x64/qvac__decoder-audio.bare +0 -0
- package/prebuilds/darwin-arm64/qvac__decoder-audio.bare +0 -0
- package/prebuilds/darwin-arm64/qvac__decoder-audio.bare.exports +0 -7163
- package/prebuilds/ios-arm64/qvac__decoder-audio.bare +0 -0
- package/prebuilds/ios-arm64/qvac__decoder-audio.bare.exports +0 -7163
- package/prebuilds/ios-arm64-simulator/qvac__decoder-audio.bare +0 -0
- package/prebuilds/ios-arm64-simulator/qvac__decoder-audio.bare.exports +0 -7163
- package/prebuilds/ios-x64-simulator/qvac__decoder-audio.bare +0 -0
- package/prebuilds/ios-x64-simulator/qvac__decoder-audio.bare.exports +0 -7141
- package/prebuilds/linux-x64/qvac__decoder-audio.bare +0 -0
- package/prebuilds/win32-x64/qvac__decoder-audio.bare +0 -0
- package/prebuilds/win32-x64/qvac__decoder-audio.bare.exports +0 -0
- package/test/mobile/gst-test.cjs +0 -103
package/README.md
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
# qvac-lib-decoder-audio
|
|
2
2
|
|
|
3
|
-
This decoder
|
|
3
|
+
This decoder library leverages FFmpeg for efficient audio decoding. It simplifies processing of input audio, particularly as a preprocessing step for other addons.
|
|
4
4
|
|
|
5
5
|
## Table of Contents
|
|
6
6
|
|
|
7
7
|
- [Installation](#installation)
|
|
8
8
|
- [Usage](#usage)
|
|
9
|
-
- [Supported Audio Formats](#supported-audio-formats)
|
|
10
9
|
- [1. Creating the Decoder Instance](#1-creating-the-decoder-instance)
|
|
11
10
|
- [2. Loading the Decoder](#2-loading-the-decoder)
|
|
12
11
|
- [3. Decoding Audio](#3-decoding-audio)
|
|
@@ -57,34 +56,16 @@ npm install @tetherto/qvac-lib-decoder-audio@latest
|
|
|
57
56
|
|
|
58
57
|
This library provides a simple workflow for decoding audio streams.
|
|
59
58
|
|
|
60
|
-
### Supported Audio Formats
|
|
61
|
-
|
|
62
|
-
The library exports two constants that define the supported audio formats:
|
|
63
|
-
|
|
64
|
-
```javascript
|
|
65
|
-
const GSTDecoder = require('@tetherto/qvac-lib-decoder-audio')
|
|
66
|
-
|
|
67
|
-
// Audio formats that require decoding before processing
|
|
68
|
-
console.log(GSTDecoder.FORMATS_NEEDING_DECODE)
|
|
69
|
-
// ['.mp3', '.m4a', '.ogg', '.flac', '.aac', '.wav']
|
|
70
|
-
|
|
71
|
-
// All supported audio formats (including raw)
|
|
72
|
-
console.log(GSTDecoder.SUPPORTED_AUDIO_FORMATS)
|
|
73
|
-
// ['.mp3', '.m4a', '.ogg', '.wav', '.flac', '.aac', '.raw']
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
These constants can be used to validate input file formats or to determine if a file needs decoding before processing.
|
|
77
|
-
|
|
78
59
|
### 1. Creating the Decoder Instance
|
|
79
60
|
|
|
80
|
-
To get started, import the decoder
|
|
61
|
+
To get started, import the decoder and create an instance:
|
|
81
62
|
|
|
82
63
|
```javascript
|
|
83
|
-
const
|
|
64
|
+
const { FFmpegDecoder } = require('@tetherto/qvac-lib-decoder-audio')
|
|
84
65
|
|
|
85
|
-
const decoder = new
|
|
66
|
+
const decoder = new FFmpegDecoder({
|
|
86
67
|
config: {
|
|
87
|
-
audioFormat: '
|
|
68
|
+
audioFormat: 's16le', // 's16le' | 'f32le'; default is 's16le'
|
|
88
69
|
sampleRate: 16000 // in Hz; default is 16000
|
|
89
70
|
}
|
|
90
71
|
})
|
|
@@ -92,20 +73,19 @@ const decoder = new GSTDecoder({
|
|
|
92
73
|
|
|
93
74
|
The `config` object accepts the following parameters:
|
|
94
75
|
|
|
95
|
-
* **`audioFormat`**: Specifies the format of the
|
|
76
|
+
* **`audioFormat`**: Specifies the output format of the decoded audio. Supported values:
|
|
96
77
|
|
|
97
|
-
* `'encoded'`: For encoded audio input. Currently supported formats are OGG, WAV, MP3 and M4A.
|
|
98
78
|
* `'s16le'`: Signed 16-bit little-endian PCM — a widely used raw format.
|
|
99
79
|
* `'f32le'`: 32-bit floating-point little-endian PCM — ideal for high-precision audio processing.
|
|
100
80
|
|
|
101
|
-
Default: `'
|
|
81
|
+
Default: `'s16le'`.
|
|
102
82
|
|
|
103
|
-
* **`sampleRate`**: Sample rate of the
|
|
83
|
+
* **`sampleRate`**: Sample rate of the output audio in Hertz (Hz).
|
|
104
84
|
Default: `16000` (16 kHz), commonly used for speech processing.
|
|
105
85
|
|
|
106
86
|
### 2. Loading the Decoder
|
|
107
87
|
|
|
108
|
-
Initializes and activates the decoder
|
|
88
|
+
Initializes and activates the decoder with the provided or default configuration. This method must be called before decoding any audio input.
|
|
109
89
|
|
|
110
90
|
```javascript
|
|
111
91
|
try {
|
|
@@ -156,7 +136,7 @@ try {
|
|
|
156
136
|
|
|
157
137
|
## Quickstart Example
|
|
158
138
|
|
|
159
|
-
The following example demonstrates how to use the decoder
|
|
139
|
+
The following example demonstrates how to use the decoder to decode a sample OGG file into a raw audio file. Follow these steps, to run the example:
|
|
160
140
|
|
|
161
141
|
### 1. Create a new project:
|
|
162
142
|
|
|
@@ -178,45 +158,38 @@ npm install bare-fs @tetherto/qvac-lib-decoder-audio
|
|
|
178
158
|
'use strict'
|
|
179
159
|
|
|
180
160
|
const fs = require('bare-fs')
|
|
181
|
-
const
|
|
161
|
+
const { FFmpegDecoder } = require('@tetherto/qvac-lib-decoder-audio')
|
|
182
162
|
|
|
183
163
|
const audioFilePath = './path/to/audio/file.ogg'
|
|
184
164
|
const outputFilePath = './path/to/output/file.raw'
|
|
185
165
|
|
|
186
166
|
async function main () {
|
|
187
|
-
|
|
188
|
-
const decoder = new GSTDecoder({
|
|
167
|
+
const decoder = new FFmpegDecoder({
|
|
189
168
|
config: {
|
|
190
|
-
audioFormat: '
|
|
169
|
+
audioFormat: 's16le',
|
|
170
|
+
sampleRate: 16000
|
|
191
171
|
}
|
|
192
172
|
})
|
|
193
173
|
|
|
194
174
|
try {
|
|
195
|
-
// 2. Load the decoder
|
|
196
175
|
await decoder.load()
|
|
197
176
|
|
|
198
|
-
// 3. Create audio stream and pass it to the decoder
|
|
199
177
|
const audioStream = fs.createReadStream(audioFilePath)
|
|
200
178
|
const response = await decoder.run(audioStream)
|
|
201
179
|
|
|
202
180
|
const decodedFileBuffer = []
|
|
203
181
|
|
|
204
|
-
// 4. Handle response updates
|
|
205
182
|
await response
|
|
206
183
|
.onUpdate(output => {
|
|
207
184
|
const bytes = new Uint8Array(output.outputArray)
|
|
208
|
-
|
|
209
|
-
// Collect decoded bytes
|
|
210
185
|
decodedFileBuffer.push(bytes)
|
|
211
186
|
})
|
|
212
187
|
.onFinish(() => {
|
|
213
|
-
// Write the decoded bytes to a file on finish
|
|
214
188
|
fs.writeFileSync(outputFilePath, Buffer.concat(decodedFileBuffer))
|
|
215
189
|
console.log('Decoded file saved to', outputFilePath)
|
|
216
190
|
})
|
|
217
191
|
.await()
|
|
218
192
|
} finally {
|
|
219
|
-
// 5. Unload the decoder
|
|
220
193
|
await decoder.unload()
|
|
221
194
|
}
|
|
222
195
|
}
|
|
@@ -267,10 +240,9 @@ Coverage reports are generated in the 'coverage/unit/' directory. Open the corre
|
|
|
267
240
|
## Resources
|
|
268
241
|
|
|
269
242
|
* GitHub Repo: [tetherto/qvac-lib-decoder-audio](https://github.com/tetherto/qvac-lib-decoder-audio)
|
|
270
|
-
* GStreamer: [gstreamer.freedesktop.org](https://gstreamer.freedesktop.org/)
|
|
271
243
|
|
|
272
244
|
## License
|
|
273
245
|
|
|
274
246
|
This project is licensed under the Apache-2.0 License – see the [LICENSE](LICENSE) file for details.
|
|
275
247
|
|
|
276
|
-
*For questions or issues, please open an issue on the GitHub repository.*
|
|
248
|
+
*For questions or issues, please open an issue on the GitHub repository.*
|
package/index.d.ts
CHANGED
|
@@ -1,69 +1,51 @@
|
|
|
1
1
|
import BaseInference = require('@qvac/infer-base/WeightsProvider/BaseInference')
|
|
2
2
|
import QvacResponse from '@qvac/response'
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
priority?: number
|
|
4
|
+
interface AudioFormatConfig {
|
|
5
|
+
format: number | null
|
|
6
|
+
byteLength: number
|
|
8
7
|
}
|
|
9
8
|
|
|
10
|
-
interface
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
[key: string]: any
|
|
9
|
+
interface SupportedAudioFormats {
|
|
10
|
+
s16le: AudioFormatConfig
|
|
11
|
+
f32le: AudioFormatConfig
|
|
14
12
|
}
|
|
15
13
|
|
|
16
|
-
interface
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
activate(): Promise<void>
|
|
22
|
-
append(input: AppendInput): Promise<number>
|
|
23
|
-
cancel(jobId: number): Promise<void>
|
|
24
|
-
pause(): Promise<void>
|
|
25
|
-
continue(): Promise<void>
|
|
26
|
-
status(): Promise<any>
|
|
27
|
-
loadWeights?(params: {
|
|
28
|
-
filename: string
|
|
29
|
-
contents?: Buffer
|
|
30
|
-
completed: boolean
|
|
31
|
-
}): Promise<void>
|
|
14
|
+
interface FFmpegDecoderConfig {
|
|
15
|
+
streamIndex?: number
|
|
16
|
+
inputBitrate?: number
|
|
17
|
+
audioFormat?: 's16le' | 'f32le'
|
|
18
|
+
sampleRate?: number
|
|
32
19
|
}
|
|
33
20
|
|
|
34
|
-
interface
|
|
35
|
-
config
|
|
21
|
+
interface FFmpegDecoderConstructorParams {
|
|
22
|
+
config?: FFmpegDecoderConfig
|
|
23
|
+
logger?: any
|
|
24
|
+
streamIndex?: number
|
|
25
|
+
inputBitrate?: number
|
|
26
|
+
audioFormat?: 's16le' | 'f32le'
|
|
36
27
|
[key: string]: any
|
|
37
28
|
}
|
|
38
29
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Creates an instance of GSTDecoder.
|
|
45
|
-
* @constructor
|
|
46
|
-
* @param {Object} config - environment-specific inference setup configuration
|
|
47
|
-
*/
|
|
48
|
-
constructor({ config, ...args }: GSTDecoderConstructorParams)
|
|
49
|
-
private config: DecoderConfig
|
|
50
|
-
private addon: Addon
|
|
51
|
-
load(): Promise<void>
|
|
52
|
-
createAddon(config: DecoderConfig): Addon
|
|
53
|
-
protected _runInternal(audioStream: AudioStream): Promise<QvacResponse>
|
|
54
|
-
getStatus(): Promise<any>
|
|
30
|
+
interface DecoderStatus {
|
|
31
|
+
loaded: boolean
|
|
32
|
+
active: boolean
|
|
33
|
+
paused: boolean
|
|
55
34
|
}
|
|
56
35
|
|
|
57
|
-
declare
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
36
|
+
declare class FFmpegDecoder extends BaseInference {
|
|
37
|
+
SUPPORTED_AUDIO_FORMATS: SupportedAudioFormats
|
|
38
|
+
OUTPUT_CHANNEL_LAYOUT: number | null
|
|
39
|
+
|
|
40
|
+
constructor(params: FFmpegDecoderConstructorParams)
|
|
62
41
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
42
|
+
load(): Promise<void>
|
|
43
|
+
unload(): Promise<void>
|
|
44
|
+
run(audioStream: AsyncIterable<Buffer>): Promise<QvacResponse>
|
|
45
|
+
pause(): Promise<void>
|
|
46
|
+
unpause(): Promise<void>
|
|
47
|
+
stop(): Promise<void>
|
|
48
|
+
status(): DecoderStatus
|
|
67
49
|
}
|
|
68
50
|
|
|
69
|
-
export
|
|
51
|
+
export { FFmpegDecoder }
|
package/index.js
CHANGED
|
@@ -1,119 +1,4 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const QvacResponse = require('@qvac/response')
|
|
4
|
-
const BaseInference = require('@qvac/infer-base/WeightsProvider/BaseInference')
|
|
5
|
-
const { GSTDecoderInterface } = require('./gstreamer')
|
|
6
|
-
const createStreamAccumulator = require('./utils/createStreamAccumulator')
|
|
7
|
-
const { FORMATS_NEEDING_DECODE, SUPPORTED_AUDIO_FORMATS } = require('./constants')
|
|
8
|
-
|
|
9
|
-
const END_OF_INPUT = 'end of job'
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* GSTDecoder client implementation for the Whisper transcription model
|
|
13
|
-
*/
|
|
14
|
-
class GSTDecoder extends BaseInference {
|
|
15
|
-
/**
|
|
16
|
-
* Creates an instance of GSTDecoder.
|
|
17
|
-
* @constructor
|
|
18
|
-
* @param {Object} options - Constructor options
|
|
19
|
-
* @param {Object} options.config - environment-specific inference setup configuration
|
|
20
|
-
* @param {*} [args] - Additional arguments passed to BaseInference
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
constructor ({ config, ...args }) {
|
|
24
|
-
super(args)
|
|
25
|
-
this.config = config
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async load () {
|
|
29
|
-
const config = {
|
|
30
|
-
audioFormat: this.config.audioFormat || 'encoded',
|
|
31
|
-
sampleRate: this.config.sampleRate || 16000
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
this.logger.info('Loading GSTDecoder with config:', config)
|
|
35
|
-
this.addon = this.createAddon(config)
|
|
36
|
-
|
|
37
|
-
await this.addon.activate()
|
|
38
|
-
this.logger.info('GSTDecoder activated successfully')
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async _runInternal (audioStream) {
|
|
42
|
-
this.logger.info('Starting new audio stream processing')
|
|
43
|
-
const response = new QvacResponse({
|
|
44
|
-
cancelHandler: () => this.addon.cancel(jobId),
|
|
45
|
-
pauseHandler: () => this.addon.pause(),
|
|
46
|
-
continueHandler: () => this.addon.continue()
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
const jobId = await this.addon.append({
|
|
50
|
-
type: 'audio',
|
|
51
|
-
input: new Uint8Array().buffer,
|
|
52
|
-
priority: 1
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
this.logger.info('Created new job with ID:', jobId)
|
|
56
|
-
this._saveJobToResponseMapping(jobId, response)
|
|
57
|
-
|
|
58
|
-
this._handleAudioStream(audioStream).catch(err => {
|
|
59
|
-
this.logger.error('Error processing audio stream:', err)
|
|
60
|
-
response.failed(err)
|
|
61
|
-
})
|
|
62
|
-
return response
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async _handleAudioStream (audioStream) {
|
|
66
|
-
this.logger.info('Starting audio stream handling')
|
|
67
|
-
const streamAccumulator = createStreamAccumulator({
|
|
68
|
-
onChunk: async chunk => {
|
|
69
|
-
this.logger.debug('Processing audio chunk of size:', chunk.byteLength)
|
|
70
|
-
await this.addon.append({
|
|
71
|
-
type: 'audio',
|
|
72
|
-
input: chunk.buffer,
|
|
73
|
-
priority: 1
|
|
74
|
-
})
|
|
75
|
-
},
|
|
76
|
-
onFinish: async () => {
|
|
77
|
-
this.logger.info('Audio stream finished, sending end of input')
|
|
78
|
-
await this.addon.append({ type: END_OF_INPUT })
|
|
79
|
-
}
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
for await (const chunk of audioStream) {
|
|
83
|
-
await streamAccumulator.processData(chunk)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
await streamAccumulator.finish()
|
|
87
|
-
this.logger.info('Audio stream handling completed')
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async getStatus () {
|
|
91
|
-
const status = await this.addon.status()
|
|
92
|
-
this.logger.debug('Current status:', status)
|
|
93
|
-
return status
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
async unload () {
|
|
97
|
-
if (this.addon) {
|
|
98
|
-
this.logger.info('Destroying GSTDecoder addon')
|
|
99
|
-
await this.addon.destroy()
|
|
100
|
-
this.addon = null
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
createAddon (config) {
|
|
105
|
-
this.logger.info('Creating new GSTDecoderInterface instance')
|
|
106
|
-
return new GSTDecoderInterface(
|
|
107
|
-
config,
|
|
108
|
-
this._outputCallback.bind(this),
|
|
109
|
-
this.logger.info.bind(this.logger)
|
|
110
|
-
)
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
3
|
const FFmpegDecoder = require('./lib/ffmpeg/ffmpeg-decoder')
|
|
115
|
-
|
|
116
|
-
module.exports = GSTDecoder
|
|
117
|
-
module.exports.FORMATS_NEEDING_DECODE = FORMATS_NEEDING_DECODE
|
|
118
|
-
module.exports.SUPPORTED_AUDIO_FORMATS = SUPPORTED_AUDIO_FORMATS
|
|
119
4
|
module.exports.FFmpegDecoder = FFmpegDecoder
|
|
@@ -312,6 +312,32 @@ class FFmpegDecoder extends BaseInference {
|
|
|
312
312
|
|
|
313
313
|
this.logger.debug(`[FFmpegDecoder] Read ${bytesToRead} bytes from buffer, offset now: ${bufferOffset}`)
|
|
314
314
|
return bytesToRead
|
|
315
|
+
},
|
|
316
|
+
onseek: (offset, whence) => {
|
|
317
|
+
const AVSEEK_SIZE = 0x10000
|
|
318
|
+
|
|
319
|
+
if (whence === AVSEEK_SIZE) {
|
|
320
|
+
return audioBuffer.length
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
let newOffset
|
|
324
|
+
if (whence === 0) {
|
|
325
|
+
newOffset = offset
|
|
326
|
+
} else if (whence === 1) {
|
|
327
|
+
newOffset = bufferOffset + offset
|
|
328
|
+
} else if (whence === 2) {
|
|
329
|
+
newOffset = audioBuffer.length + offset
|
|
330
|
+
} else {
|
|
331
|
+
return -1
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (newOffset < 0 || newOffset > audioBuffer.length) {
|
|
335
|
+
return -1
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
bufferOffset = newOffset
|
|
339
|
+
this.logger.debug(`[FFmpegDecoder] Seek to offset: ${bufferOffset}`)
|
|
340
|
+
return bufferOffset
|
|
315
341
|
}
|
|
316
342
|
})
|
|
317
343
|
|
package/package.json
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qvac/decoder-audio",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Tether",
|
|
7
7
|
"type": "commonjs",
|
|
8
8
|
"main": "index.js",
|
|
9
|
-
"addon": true,
|
|
10
9
|
"scripts": {
|
|
11
10
|
"test:dts": "tsc index.d.ts --noEmit --esModuleInterop --skipLibCheck",
|
|
12
11
|
"test:unit": "brittle-bare test/unit/*.test.js",
|
|
@@ -18,12 +17,9 @@
|
|
|
18
17
|
"test:integration": "brittle-bare test/integration/*.test.js"
|
|
19
18
|
},
|
|
20
19
|
"files": [
|
|
21
|
-
"binding.js",
|
|
22
20
|
"index.js",
|
|
23
|
-
"gstreamer.js",
|
|
24
21
|
"constants.js",
|
|
25
22
|
"constants.d.ts",
|
|
26
|
-
"prebuilds",
|
|
27
23
|
"utils",
|
|
28
24
|
"lib",
|
|
29
25
|
"index.d.ts",
|
|
@@ -38,8 +34,6 @@
|
|
|
38
34
|
"devDependencies": {
|
|
39
35
|
"@types/node": "^22.14.1",
|
|
40
36
|
"brittle": "^3.13.1",
|
|
41
|
-
"cmake-bare": "^1.7.5",
|
|
42
|
-
"cmake-vcpkg": "^1.1.0",
|
|
43
37
|
"istanbul": "^0.4.5",
|
|
44
38
|
"standard": "^17.1.2",
|
|
45
39
|
"typescript": "^5.3.0"
|
|
Binary file
|
package/binding.js
DELETED
package/gstreamer.js
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const binding = require('./binding')
|
|
4
|
-
const { QvacErrorDecoderAudio, ERR_CODES } = require('./utils/error')
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* An interface between Bare addon in C++ and JS runtime.
|
|
8
|
-
*/
|
|
9
|
-
class GSTDecoderInterface {
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
* @param {Object} configurationParams - all the required configuration for inference setup
|
|
13
|
-
* @param {Function} outputCb - to be called on any inference event ( started, new output, error, etc )
|
|
14
|
-
* @param {Function} transitionCb - to be called on addon state changes (LISTENING, IDLE, STOPPED, etc )
|
|
15
|
-
*/
|
|
16
|
-
constructor (configurationParams, outputCb, transitionCb = null) {
|
|
17
|
-
this._handle = binding.createInstance(this, configurationParams, outputCb, transitionCb)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
*
|
|
22
|
-
* @param {Object} weightsData
|
|
23
|
-
* @param {String} weightsData.filename
|
|
24
|
-
* @param {Uint8Array} weightsData.contents
|
|
25
|
-
* @param {Boolean} weightsData.completed
|
|
26
|
-
*/
|
|
27
|
-
async loadWeights (weightsData) {
|
|
28
|
-
try {
|
|
29
|
-
binding.loadWeights(this._handle, weightsData)
|
|
30
|
-
} catch (err) {
|
|
31
|
-
throw new QvacErrorDecoderAudio(
|
|
32
|
-
ERR_CODES.FAILED_TO_LOAD_WEIGHTS,
|
|
33
|
-
err.message
|
|
34
|
-
)
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Moves addon to the LISTENING state after all the initialization is done
|
|
40
|
-
*/
|
|
41
|
-
async activate () {
|
|
42
|
-
try {
|
|
43
|
-
binding.activate(this._handle)
|
|
44
|
-
} catch (err) {
|
|
45
|
-
throw new QvacErrorDecoderAudio(
|
|
46
|
-
ERR_CODES.FAILED_TO_ACTIVATE,
|
|
47
|
-
err.message
|
|
48
|
-
)
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Pauses current inference process
|
|
54
|
-
*/
|
|
55
|
-
async pause () {
|
|
56
|
-
try {
|
|
57
|
-
binding.pause(this._handle)
|
|
58
|
-
} catch (err) {
|
|
59
|
-
throw new QvacErrorDecoderAudio(
|
|
60
|
-
ERR_CODES.FAILED_TO_PAUSE,
|
|
61
|
-
err.message
|
|
62
|
-
)
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Cancel a inference process by jobId, if no jobId is provided it cancel the whole queue
|
|
68
|
-
*/
|
|
69
|
-
async cancel (jobId) {
|
|
70
|
-
try {
|
|
71
|
-
binding.cancel(this._handle, jobId)
|
|
72
|
-
} catch (err) {
|
|
73
|
-
throw new QvacErrorDecoderAudio(
|
|
74
|
-
ERR_CODES.FAILED_TO_CANCEL,
|
|
75
|
-
err.message
|
|
76
|
-
)
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Adds new input to the processing queue
|
|
82
|
-
* @param {Object} data
|
|
83
|
-
* @param {String} data.type
|
|
84
|
-
* @param {String} data.input
|
|
85
|
-
* @returns {Number} - job ID
|
|
86
|
-
*/
|
|
87
|
-
async append (data) {
|
|
88
|
-
try {
|
|
89
|
-
return binding.append(this._handle, data)
|
|
90
|
-
} catch (err) {
|
|
91
|
-
throw new QvacErrorDecoderAudio(
|
|
92
|
-
ERR_CODES.FAILED_TO_APPEND,
|
|
93
|
-
err.message
|
|
94
|
-
)
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Addon process status
|
|
100
|
-
* @returns {String}
|
|
101
|
-
*/
|
|
102
|
-
async status () {
|
|
103
|
-
try {
|
|
104
|
-
return binding.status(this._handle)
|
|
105
|
-
} catch (err) {
|
|
106
|
-
throw new QvacErrorDecoderAudio(
|
|
107
|
-
ERR_CODES.FAILED_TO_GET_STATUS,
|
|
108
|
-
err.message
|
|
109
|
-
)
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Stops addon process and clears resources (including memory).
|
|
115
|
-
*/
|
|
116
|
-
async destroy () {
|
|
117
|
-
try {
|
|
118
|
-
binding.destroyInstance(this._handle)
|
|
119
|
-
this._handle = null
|
|
120
|
-
} catch (err) {
|
|
121
|
-
throw new QvacErrorDecoderAudio(
|
|
122
|
-
ERR_CODES.FAILED_TO_DESTROY,
|
|
123
|
-
err.message
|
|
124
|
-
)
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
module.exports = {
|
|
130
|
-
GSTDecoderInterface
|
|
131
|
-
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|