diff --git a/.gitignore b/.gitignore index fe04f7c8..464c21dd 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ /native_client/python/model_wrap.cpp /native_client/python/utils_wrap.cpp /native_client/javascript/build +/native_client/javascript/client.js /native_client/javascript/deepspeech_wrap.cxx /doc/.build/ /doc/xml-c/ diff --git a/native_client/javascript/Makefile b/native_client/javascript/Makefile index 5c1db09a..e62c0659 100644 --- a/native_client/javascript/Makefile +++ b/native_client/javascript/Makefile @@ -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) 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) deepspeech_wrap.cxx: deepspeech.i diff --git a/native_client/javascript/client.js b/native_client/javascript/client.ts similarity index 59% rename from native_client/javascript/client.js rename to native_client/javascript/client.ts index 16dd19e8..e6000fe5 100644 --- a/native_client/javascript/client.js +++ b/native_client/javascript/client.ts @@ -1,48 +1,42 @@ #!/usr/bin/env node -'use strict'; -const Fs = require('fs'); -const Sox = require('sox-stream'); -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'); +// This is required for process.versions.electron below +/// -var VersionAction = function VersionAction(options) { - options = options || {}; - options.nargs = 0; - argparse.Action.call(this, options); -} -util.inherits(VersionAction, argparse.Action); +import Ds from "./index"; +import * as Fs from "fs"; +import Sox from "sox-stream"; +import * as argparse from "argparse"; -VersionAction.prototype.call = function(parser) { - console.log('DeepSpeech ' + Ds.Version()); - let runtime = 'Node'; - if (process.versions.electron) { - runtime = 'Electron'; +const MemoryStream = require("memory-stream"); +const Wav = require("node-wav"); +const Duplex = require("stream").Duplex; + +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(['--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(['--beam_width'], {help: 'Beam width for the CTC decoder', type: 'int'}); -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(['--version'], {action: VersionAction, nargs: 0, help: 'Print version and exits'}); 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); } -function candidateTranscriptToString(transcript) { +function candidateTranscriptToString(transcript: Ds.CandidateTranscript): string { var retval = "" for (var i = 0; i < transcript.tokens.length; ++i) { retval += transcript.tokens[i].text; @@ -52,7 +46,7 @@ function candidateTranscriptToString(transcript) { console.error('Loading model from file %s', args['model']); 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); console.error('Loaded model in %ds.', totalTime(model_load_end)); @@ -60,7 +54,7 @@ if (args['beam_width']) { model.setBeamWidth(args['beam_width']); } -var desired_sample_rate = model.sampleRate(); +let desired_sample_rate = model.sampleRate(); if (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); if (result.sampleRate < desired_sample_rate) { - console.error('Warning: original sample rate (' + result.sampleRate + ') ' + - 'is lower than ' + desired_sample_rate + 'Hz. ' + - 'Up-sampling might produce erratic speech recognition.'); + console.error(`Warning: original sample rate ( ${result.sampleRate})` + + `is lower than ${desired_sample_rate} Hz. ` + + `Up-sampling might produce erratic speech recognition.`); } -function bufferToStream(buffer) { +function bufferToStream(buffer: Buffer) { var stream = new Duplex(); stream.push(buffer); stream.push(null); return stream; } -var audioStream = new MemoryStream(); +let audioStream = new MemoryStream(); bufferToStream(buffer). pipe(Sox({ global: { 'no-dither': true, + 'replay-gain': 'off', }, output: { bits: 16, diff --git a/native_client/javascript/index.d.ts b/native_client/javascript/index.d.ts index c944876d..50564a02 100644 --- a/native_client/javascript/index.d.ts +++ b/native_client/javascript/index.d.ts @@ -1,4 +1,3 @@ -declare module 'deepspeech' { /** * 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. */ export function Version(): void; -} diff --git a/native_client/javascript/package.json.in b/native_client/javascript/package.json.in index bd80f438..8e9215a4 100644 --- a/native_client/javascript/package.json.in +++ b/native_client/javascript/package.json.in @@ -2,7 +2,8 @@ "name" : "$(PROJECT_NAME)", "version" : "$(PROJECT_VERSION)", "description" : "DeepSpeech NodeJS bindings", - "main" : "./index", + "main" : "./index.js", + "types": "./index.d.ts", "bin": { "deepspeech": "./client.js" }, @@ -13,6 +14,7 @@ "README.md", "client.js", "index.js", + "index.d.ts", "lib/*" ], "bugs": { @@ -37,6 +39,7 @@ "node-wav": "0.0.2" }, "devDependencies": { + "electron": "^1.7.9" }, "scripts": { "test": "node index.js" diff --git a/native_client/javascript/tsconfig.json b/native_client/javascript/tsconfig.json index 51b30f85..f67afbbd 100644 --- a/native_client/javascript/tsconfig.json +++ b/native_client/javascript/tsconfig.json @@ -13,6 +13,7 @@ "forceConsistentCasingInFileNames": true }, "files": [ - "index.d.ts" + "index.d.ts", + "client.ts" ] -} \ No newline at end of file +}