Package and expose TypeScript for JS interface

This commit is contained in:
Alexandre Lissy 2020-04-02 14:45:45 +02:00
parent 510d71353f
commit 567595aa5a
6 changed files with 42 additions and 43 deletions

1
.gitignore vendored
View File

@ -19,6 +19,7 @@
/native_client/python/model_wrap.cpp /native_client/python/model_wrap.cpp
/native_client/python/utils_wrap.cpp /native_client/python/utils_wrap.cpp
/native_client/javascript/build /native_client/javascript/build
/native_client/javascript/client.js
/native_client/javascript/deepspeech_wrap.cxx /native_client/javascript/deepspeech_wrap.cxx
/doc/.build/ /doc/.build/
/doc/xml-c/ /doc/xml-c/

View File

@ -42,7 +42,8 @@ node-wrapper: copy-deps build
$(NODE_BUILD_TOOL) $(NODE_PLATFORM_TARGET) $(NODE_RUNTIME) $(NODE_ABI_TARGET) $(NODE_DIST_URL) package $(NODE_BUILD_VERBOSE) $(NODE_BUILD_TOOL) $(NODE_PLATFORM_TARGET) $(NODE_RUNTIME) $(NODE_ABI_TARGET) $(NODE_DIST_URL) package $(NODE_BUILD_VERBOSE)
npm-pack: clean package.json index.js npm-pack: clean package.json index.js
npm install node-pre-gyp@0.14.x npm install --prefix=${NPM_ROOT} node-pre-gyp@0.14.x typescript@3.6.2 @types/argparse@1.0.38
${NPM_ROOT}/.bin/tsc --outDir dist/ client.ts || true
npm pack $(NODE_BUILD_VERBOSE) npm pack $(NODE_BUILD_VERBOSE)
deepspeech_wrap.cxx: deepspeech.i deepspeech_wrap.cxx: deepspeech.i

View File

@ -1,48 +1,42 @@
#!/usr/bin/env node #!/usr/bin/env node
'use strict';
const Fs = require('fs'); // This is required for process.versions.electron below
const Sox = require('sox-stream'); /// <reference types="electron" />
const Ds = require('./index.js');
const argparse = require('argparse');
const MemoryStream = require('memory-stream');
const Wav = require('node-wav');
const Duplex = require('stream').Duplex;
const util = require('util');
var VersionAction = function VersionAction(options) { import Ds from "./index";
options = options || {}; import * as Fs from "fs";
options.nargs = 0; import Sox from "sox-stream";
argparse.Action.call(this, options); import * as argparse from "argparse";
}
util.inherits(VersionAction, argparse.Action);
VersionAction.prototype.call = function(parser) { const MemoryStream = require("memory-stream");
console.log('DeepSpeech ' + Ds.Version()); const Wav = require("node-wav");
let runtime = 'Node'; const Duplex = require("stream").Duplex;
if (process.versions.electron) {
runtime = 'Electron'; class VersionAction extends argparse.Action {
call(parser: argparse.ArgumentParser, namespace: argparse.Namespace, values: string | string[], optionString: string | null) {
console.log('DeepSpeech ' + Ds.Version());
let runtime = 'Node';
if (process.versions.electron) {
runtime = 'Electron';
}
console.error('Runtime: ' + runtime);
process.exit(0);
} }
console.error('Runtime: ' + runtime);
process.exit(0);
} }
var parser = new argparse.ArgumentParser({addHelp: true, description: 'Running DeepSpeech inference.'}); let parser = new argparse.ArgumentParser({addHelp: true, description: 'Running DeepSpeech inference.'});
parser.addArgument(['--model'], {required: true, help: 'Path to the model (protocol buffer binary file)'}); parser.addArgument(['--model'], {required: true, help: 'Path to the model (protocol buffer binary file)'});
parser.addArgument(['--scorer'], {help: 'Path to the external scorer file'}); parser.addArgument(['--scorer'], {help: 'Path to the external scorer file'});
parser.addArgument(['--audio'], {required: true, help: 'Path to the audio file to run (WAV format)'}); parser.addArgument(['--audio'], {required: true, help: 'Path to the audio file to run (WAV format)'});
parser.addArgument(['--beam_width'], {help: 'Beam width for the CTC decoder', type: 'int'}); parser.addArgument(['--version'], {action: VersionAction, nargs: 0, help: 'Print version and exits'});
parser.addArgument(['--lm_alpha'], {help: 'Language model weight (lm_alpha). If not specified, use default from the scorer package.', type: 'float'});
parser.addArgument(['--lm_beta'], {help: 'Word insertion bonus (lm_beta). If not specified, use default from the scorer package.', type: 'float'});
parser.addArgument(['--version'], {action: VersionAction, help: 'Print version and exits'});
parser.addArgument(['--extended'], {action: 'storeTrue', help: 'Output string from extended metadata'}); parser.addArgument(['--extended'], {action: 'storeTrue', help: 'Output string from extended metadata'});
var args = parser.parseArgs(); let args = parser.parseArgs();
function totalTime(hrtimeValue) { function totalTime(hrtimeValue: number[]): string {
return (hrtimeValue[0] + hrtimeValue[1] / 1000000000).toPrecision(4); return (hrtimeValue[0] + hrtimeValue[1] / 1000000000).toPrecision(4);
} }
function candidateTranscriptToString(transcript) { function candidateTranscriptToString(transcript: Ds.CandidateTranscript): string {
var retval = "" var retval = ""
for (var i = 0; i < transcript.tokens.length; ++i) { for (var i = 0; i < transcript.tokens.length; ++i) {
retval += transcript.tokens[i].text; retval += transcript.tokens[i].text;
@ -52,7 +46,7 @@ function candidateTranscriptToString(transcript) {
console.error('Loading model from file %s', args['model']); console.error('Loading model from file %s', args['model']);
const model_load_start = process.hrtime(); const model_load_start = process.hrtime();
var model = new Ds.Model(args['model']); let model = new Ds.Model(args['model']);
const model_load_end = process.hrtime(model_load_start); const model_load_end = process.hrtime(model_load_start);
console.error('Loaded model in %ds.', totalTime(model_load_end)); console.error('Loaded model in %ds.', totalTime(model_load_end));
@ -60,7 +54,7 @@ if (args['beam_width']) {
model.setBeamWidth(args['beam_width']); model.setBeamWidth(args['beam_width']);
} }
var desired_sample_rate = model.sampleRate(); let desired_sample_rate = model.sampleRate();
if (args['scorer']) { if (args['scorer']) {
console.error('Loading scorer from file %s', args['scorer']); console.error('Loading scorer from file %s', args['scorer']);
@ -78,23 +72,24 @@ const buffer = Fs.readFileSync(args['audio']);
const result = Wav.decode(buffer); const result = Wav.decode(buffer);
if (result.sampleRate < desired_sample_rate) { if (result.sampleRate < desired_sample_rate) {
console.error('Warning: original sample rate (' + result.sampleRate + ') ' + console.error(`Warning: original sample rate ( ${result.sampleRate})` +
'is lower than ' + desired_sample_rate + 'Hz. ' + `is lower than ${desired_sample_rate} Hz. ` +
'Up-sampling might produce erratic speech recognition.'); `Up-sampling might produce erratic speech recognition.`);
} }
function bufferToStream(buffer) { function bufferToStream(buffer: Buffer) {
var stream = new Duplex(); var stream = new Duplex();
stream.push(buffer); stream.push(buffer);
stream.push(null); stream.push(null);
return stream; return stream;
} }
var audioStream = new MemoryStream(); let audioStream = new MemoryStream();
bufferToStream(buffer). bufferToStream(buffer).
pipe(Sox({ pipe(Sox({
global: { global: {
'no-dither': true, 'no-dither': true,
'replay-gain': 'off',
}, },
output: { output: {
bits: 16, bits: 16,

View File

@ -1,4 +1,3 @@
declare module 'deepspeech' {
/** /**
* Stores text of an individual token, along with its timing information * Stores text of an individual token, along with its timing information
*/ */
@ -195,4 +194,3 @@ export function FreeStream(stream: object): void;
* Print version of this library and of the linked TensorFlow library on standard output. * Print version of this library and of the linked TensorFlow library on standard output.
*/ */
export function Version(): void; export function Version(): void;
}

View File

@ -2,7 +2,8 @@
"name" : "$(PROJECT_NAME)", "name" : "$(PROJECT_NAME)",
"version" : "$(PROJECT_VERSION)", "version" : "$(PROJECT_VERSION)",
"description" : "DeepSpeech NodeJS bindings", "description" : "DeepSpeech NodeJS bindings",
"main" : "./index", "main" : "./index.js",
"types": "./index.d.ts",
"bin": { "bin": {
"deepspeech": "./client.js" "deepspeech": "./client.js"
}, },
@ -13,6 +14,7 @@
"README.md", "README.md",
"client.js", "client.js",
"index.js", "index.js",
"index.d.ts",
"lib/*" "lib/*"
], ],
"bugs": { "bugs": {
@ -37,6 +39,7 @@
"node-wav": "0.0.2" "node-wav": "0.0.2"
}, },
"devDependencies": { "devDependencies": {
"electron": "^1.7.9"
}, },
"scripts": { "scripts": {
"test": "node index.js" "test": "node index.js"

View File

@ -13,6 +13,7 @@
"forceConsistentCasingInFileNames": true "forceConsistentCasingInFileNames": true
}, },
"files": [ "files": [
"index.d.ts" "index.d.ts",
"client.ts"
] ]
} }