From 7bd16191206b95e3c1d70bcbd76fea0e5c1ef2c4 Mon Sep 17 00:00:00 2001 From: Alexandre Lissy Date: Wed, 10 Apr 2019 10:03:54 +0200 Subject: [PATCH] Build for ElectronJS Fixes #2032 --- native_client/javascript/Makefile | 4 +- native_client/javascript/client.js | 10 +++- taskcluster/.shared.yml | 3 + .../test-electronjs_v3.1-darwin-amd64-opt.yml | 13 ++++ .../test-electronjs_v3.1-linux-amd64-opt.yml | 14 +++++ .../test-electronjs_v3.1-win-amd64-opt.yml | 13 ++++ .../test-electronjs_v4.0-darwin-amd64-opt.yml | 13 ++++ .../test-electronjs_v4.0-linux-amd64-opt.yml | 14 +++++ .../test-electronjs_v4.0-win-amd64-opt.yml | 13 ++++ .../test-electronjs_v4.1-darwin-amd64-opt.yml | 13 ++++ .../test-electronjs_v4.1-linux-amd64-opt.yml | 14 +++++ .../test-electronjs_v4.1-win-amd64-opt.yml | 13 ++++ tc-electron-tests.sh | 59 +++++++++++++++++++ tc-node-tests-prod.sh | 2 + tc-node-tests.sh | 2 + tc-tests-utils.sh | 51 ++++++++++++++++ 16 files changed, 248 insertions(+), 3 deletions(-) create mode 100644 taskcluster/test-electronjs_v3.1-darwin-amd64-opt.yml create mode 100644 taskcluster/test-electronjs_v3.1-linux-amd64-opt.yml create mode 100644 taskcluster/test-electronjs_v3.1-win-amd64-opt.yml create mode 100644 taskcluster/test-electronjs_v4.0-darwin-amd64-opt.yml create mode 100644 taskcluster/test-electronjs_v4.0-linux-amd64-opt.yml create mode 100644 taskcluster/test-electronjs_v4.0-win-amd64-opt.yml create mode 100644 taskcluster/test-electronjs_v4.1-darwin-amd64-opt.yml create mode 100644 taskcluster/test-electronjs_v4.1-linux-amd64-opt.yml create mode 100644 taskcluster/test-electronjs_v4.1-win-amd64-opt.yml create mode 100755 tc-electron-tests.sh diff --git a/native_client/javascript/Makefile b/native_client/javascript/Makefile index 54e39d90..e0bba0cf 100644 --- a/native_client/javascript/Makefile +++ b/native_client/javascript/Makefile @@ -36,13 +36,13 @@ configure: deepspeech_wrap.cxx package.json $(NODE_BUILD_TOOL) configure $(NODE_BUILD_VERBOSE) build: configure deepspeech_wrap.cxx - AS=$(AS) CC=$(CC) CXX=$(CXX) LD=$(LD) CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(RPATH_NODEJS) $(LDFLAGS)" LIBS=$(LIBS) $(NODE_BUILD_TOOL) $(NODE_PLATFORM_TARGET) $(NODE_ABI_TARGET) rebuild $(NODE_BUILD_VERBOSE) + AS=$(AS) CC=$(CC) CXX=$(CXX) LD=$(LD) CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(RPATH_NODEJS) $(LDFLAGS)" LIBS=$(LIBS) $(NODE_BUILD_TOOL) $(NODE_PLATFORM_TARGET) $(NODE_RUNTIME) $(NODE_ABI_TARGET) $(NODE_DIST_URL) rebuild $(NODE_BUILD_VERBOSE) copy-deps: build $(call copy_missing_libs,lib/binding/*/*/*/deepspeech.node,lib/binding/*/*/) node-wrapper: copy-deps build - $(NODE_BUILD_TOOL) $(NODE_PLATFORM_TARGET) $(NODE_ABI_TARGET) 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 README.md index.js npm install node-pre-gyp@0.12.x diff --git a/native_client/javascript/client.js b/native_client/javascript/client.js index a7a72de3..cda00935 100644 --- a/native_client/javascript/client.js +++ b/native_client/javascript/client.js @@ -1,5 +1,7 @@ #!/usr/bin/env node +'use strict'; + const Fs = require('fs'); const Sox = require('sox-stream'); const Ds = require('./index.js'); @@ -40,6 +42,11 @@ util.inherits(VersionAction, argparse.Action); VersionAction.prototype.call = function(parser) { Ds.printVersions(); + let runtime = 'Node'; + if (process.versions.electron) { + runtime = 'Electron'; + } + console.error('Runtime: ' + runtime); process.exit(0); } @@ -89,7 +96,7 @@ bufferToStream(buffer). pipe(audioStream); audioStream.on('finish', () => { - audioBuffer = audioStream.toBuffer(); + let audioBuffer = audioStream.toBuffer(); console.error('Loading model from file %s', args['model']); const model_load_start = process.hrtime(); @@ -115,4 +122,5 @@ audioStream.on('finish', () => { console.log(model.stt(audioBuffer.slice(0, audioBuffer.length / 2), 16000)); const inference_stop = process.hrtime(inference_start); console.error('Inference took %ds for %ds audio file.', totalTime(inference_stop), audioLength.toPrecision(4)); + process.exit(0); }); diff --git a/taskcluster/.shared.yml b/taskcluster/.shared.yml index 1ec0a73c..a9cdfe0e 100644 --- a/taskcluster/.shared.yml +++ b/taskcluster/.shared.yml @@ -6,6 +6,9 @@ python: brew: setup: 'install_local_homebrew "python-ds-test" && install_pkg_local_homebrew "sox" && install_pkg_local_homebrew "readline" && install_pkg_local_homebrew "openssl" && install_pkg_local_homebrew "pkg-config"' env: 'export EXTRA_ENV="PATH=$TASKCLUSTER_TASK_DIR/python-ds-test.brew/bin/:$PATH"' +electronjs: + packages_xenial: + apt: 'libatk1.0-0 libatk-bridge2.0-0 libcairo2 libcups2 libdbus-1-3 libgdk-pixbuf2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 libx11-xcb1 libxcomposite1 libxcursor1 libxdamage1 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 xvfb' nodejs: packages_trusty: apt: 'nodejs sox' diff --git a/taskcluster/test-electronjs_v3.1-darwin-amd64-opt.yml b/taskcluster/test-electronjs_v3.1-darwin-amd64-opt.yml new file mode 100644 index 00000000..b8589b79 --- /dev/null +++ b/taskcluster/test-electronjs_v3.1-darwin-amd64-opt.yml @@ -0,0 +1,13 @@ +build: + template_file: test-darwin-opt-base.tyml + dependencies: + - "node-package-cpu" + - "test-training_upstream-linux-amd64-py27mu-opt" + system_setup: + > + ${nodejs.brew.setup} && ${nodejs.brew.prep_10} && ${nodejs.brew.env} + args: + tests_cmdline: "$TASKCLUSTER_TASK_DIR/DeepSpeech/ds/tc-electron-tests.sh 10.x 3.1.8" + metadata: + name: "DeepSpeech OSX AMD64 CPU ElectronJS v3.1 tests" + description: "Testing DeepSpeech for OSX/AMD64 on ElectronJS v3.1, CPU only, optimized version" diff --git a/taskcluster/test-electronjs_v3.1-linux-amd64-opt.yml b/taskcluster/test-electronjs_v3.1-linux-amd64-opt.yml new file mode 100644 index 00000000..86c364a2 --- /dev/null +++ b/taskcluster/test-electronjs_v3.1-linux-amd64-opt.yml @@ -0,0 +1,14 @@ +build: + template_file: test-linux-opt-base.tyml + docker_image: "ubuntu:16.04" + dependencies: + - "node-package-cpu" + - "test-training_upstream-linux-amd64-py27mu-opt" + system_setup: + > + ${nodejs.packages_xenial.prep_10} && ${nodejs.packages_xenial.apt_pinning} && apt-get -qq update && apt-get -qq -y install ${nodejs.packages_xenial.apt} ${electronjs.packages_xenial.apt} + args: + tests_cmdline: "${system.homedir.linux}/DeepSpeech/ds/tc-electron-tests.sh 10.x 3.1.8" + metadata: + name: "DeepSpeech Linux AMD64 CPU ElectronJS v3.1 tests" + description: "Testing DeepSpeech for Linux/AMD64 on ElectronJS v3.1, CPU only, optimized version" diff --git a/taskcluster/test-electronjs_v3.1-win-amd64-opt.yml b/taskcluster/test-electronjs_v3.1-win-amd64-opt.yml new file mode 100644 index 00000000..453adb40 --- /dev/null +++ b/taskcluster/test-electronjs_v3.1-win-amd64-opt.yml @@ -0,0 +1,13 @@ +build: + template_file: test-win-opt-base.tyml + dependencies: + - "node-package-cpu" + - "test-training_upstream-linux-amd64-py27mu-opt" + system_setup: + > + ${system.sox_win} && ${nodejs.win.prep_10} + args: + tests_cmdline: "${system.homedir.win}/DeepSpeech/ds/tc-electron-tests.sh 10.x 3.1.8" + metadata: + name: "DeepSpeech Windows AMD64 CPU ElectronJS v3.1 tests" + description: "Testing DeepSpeech for Windows/AMD64 on ElectronJS v3.1, CPU only, optimized version" diff --git a/taskcluster/test-electronjs_v4.0-darwin-amd64-opt.yml b/taskcluster/test-electronjs_v4.0-darwin-amd64-opt.yml new file mode 100644 index 00000000..cfe4e646 --- /dev/null +++ b/taskcluster/test-electronjs_v4.0-darwin-amd64-opt.yml @@ -0,0 +1,13 @@ +build: + template_file: test-darwin-opt-base.tyml + dependencies: + - "node-package-cpu" + - "test-training_upstream-linux-amd64-py27mu-opt" + system_setup: + > + ${nodejs.brew.setup} && ${nodejs.brew.prep_10} && ${nodejs.brew.env} + args: + tests_cmdline: "$TASKCLUSTER_TASK_DIR/DeepSpeech/ds/tc-electron-tests.sh 10.x 4.0.3" + metadata: + name: "DeepSpeech OSX AMD64 CPU ElectronJS v4.0 tests" + description: "Testing DeepSpeech for OSX/AMD64 on ElectronJS v4.0, CPU only, optimized version" diff --git a/taskcluster/test-electronjs_v4.0-linux-amd64-opt.yml b/taskcluster/test-electronjs_v4.0-linux-amd64-opt.yml new file mode 100644 index 00000000..a49047f6 --- /dev/null +++ b/taskcluster/test-electronjs_v4.0-linux-amd64-opt.yml @@ -0,0 +1,14 @@ +build: + template_file: test-linux-opt-base.tyml + docker_image: "ubuntu:16.04" + dependencies: + - "node-package-cpu" + - "test-training_upstream-linux-amd64-py27mu-opt" + system_setup: + > + ${nodejs.packages_xenial.prep_10} && ${nodejs.packages_xenial.apt_pinning} && apt-get -qq update && apt-get -qq -y install ${nodejs.packages_xenial.apt} ${electronjs.packages_xenial.apt} + args: + tests_cmdline: "${system.homedir.linux}/DeepSpeech/ds/tc-electron-tests.sh 10.x 4.0.3" + metadata: + name: "DeepSpeech Linux AMD64 CPU ElectronJS v4.0 tests" + description: "Testing DeepSpeech for Linux/AMD64 on ElectronJS v4.0, CPU only, optimized version" diff --git a/taskcluster/test-electronjs_v4.0-win-amd64-opt.yml b/taskcluster/test-electronjs_v4.0-win-amd64-opt.yml new file mode 100644 index 00000000..e70b3a30 --- /dev/null +++ b/taskcluster/test-electronjs_v4.0-win-amd64-opt.yml @@ -0,0 +1,13 @@ +build: + template_file: test-win-opt-base.tyml + dependencies: + - "node-package-cpu" + - "test-training_upstream-linux-amd64-py27mu-opt" + system_setup: + > + ${system.sox_win} && ${nodejs.win.prep_10} + args: + tests_cmdline: "${system.homedir.win}/DeepSpeech/ds/tc-electron-tests.sh 10.x 4.0.3" + metadata: + name: "DeepSpeech Windows AMD64 CPU ElectronJS v4.0 tests" + description: "Testing DeepSpeech for Windows/AMD64 on ElectronJS v4.0, CPU only, optimized version" diff --git a/taskcluster/test-electronjs_v4.1-darwin-amd64-opt.yml b/taskcluster/test-electronjs_v4.1-darwin-amd64-opt.yml new file mode 100644 index 00000000..192d077a --- /dev/null +++ b/taskcluster/test-electronjs_v4.1-darwin-amd64-opt.yml @@ -0,0 +1,13 @@ +build: + template_file: test-darwin-opt-base.tyml + dependencies: + - "node-package-cpu" + - "test-training_upstream-linux-amd64-py27mu-opt" + system_setup: + > + ${nodejs.brew.setup} && ${nodejs.brew.prep_10} && ${nodejs.brew.env} + args: + tests_cmdline: "$TASKCLUSTER_TASK_DIR/DeepSpeech/ds/tc-electron-tests.sh 10.x 4.1.1" + metadata: + name: "DeepSpeech OSX AMD64 CPU ElectronJS v4.1 tests" + description: "Testing DeepSpeech for OSX/AMD64 on ElectronJS v4.1, CPU only, optimized version" diff --git a/taskcluster/test-electronjs_v4.1-linux-amd64-opt.yml b/taskcluster/test-electronjs_v4.1-linux-amd64-opt.yml new file mode 100644 index 00000000..9ed2f1a5 --- /dev/null +++ b/taskcluster/test-electronjs_v4.1-linux-amd64-opt.yml @@ -0,0 +1,14 @@ +build: + template_file: test-linux-opt-base.tyml + docker_image: "ubuntu:16.04" + dependencies: + - "node-package-cpu" + - "test-training_upstream-linux-amd64-py27mu-opt" + system_setup: + > + ${nodejs.packages_xenial.prep_10} && ${nodejs.packages_xenial.apt_pinning} && apt-get -qq update && apt-get -qq -y install ${nodejs.packages_xenial.apt} ${electronjs.packages_xenial.apt} + args: + tests_cmdline: "${system.homedir.linux}/DeepSpeech/ds/tc-electron-tests.sh 10.x 4.1.1" + metadata: + name: "DeepSpeech Linux AMD64 CPU ElectronJS v4.1 tests" + description: "Testing DeepSpeech for Linux/AMD64 on ElectronJS v4.1, CPU only, optimized version" diff --git a/taskcluster/test-electronjs_v4.1-win-amd64-opt.yml b/taskcluster/test-electronjs_v4.1-win-amd64-opt.yml new file mode 100644 index 00000000..95d5423a --- /dev/null +++ b/taskcluster/test-electronjs_v4.1-win-amd64-opt.yml @@ -0,0 +1,13 @@ +build: + template_file: test-win-opt-base.tyml + dependencies: + - "node-package-cpu" + - "test-training_upstream-linux-amd64-py27mu-opt" + system_setup: + > + ${system.sox_win} && ${nodejs.win.prep_10} + args: + tests_cmdline: "${system.homedir.win}/DeepSpeech/ds/tc-electron-tests.sh 10.x 4.1.1" + metadata: + name: "DeepSpeech Windows AMD64 CPU ElectronJS v4.1 tests" + description: "Testing DeepSpeech for Windows/AMD64 on ElectronJS v4.1, CPU only, optimized version" diff --git a/tc-electron-tests.sh b/tc-electron-tests.sh new file mode 100755 index 00000000..12236d22 --- /dev/null +++ b/tc-electron-tests.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +set -xe + +source $(dirname "$0")/tc-tests-utils.sh + +nodever=$1 +electronver=$2 + +if [ -z "${nodever}" ]; then + echo "No node version given, aborting." + exit 1 +fi; + +if [ -z "${electronver}" ]; then + echo "No electron version given, aborting." + exit 1 +fi; + +download_data + +node --version +npm --version + +NODE_ROOT="${DS_ROOT_TASK}/ds-test/" +export NODE_PATH="${NODE_ROOT}/node_modules/" +export PATH="${NODE_ROOT}:${NODE_PATH}/.bin/:${NODE_PATH}/electron/dist/:$PATH" + +npm install --prefix ${NODE_ROOT} electron@${electronver} + +npm install --prefix ${NODE_ROOT} ${DEEPSPEECH_NODEJS}/deepspeech-${DS_VERSION}.tgz + +if [ "${OS}" = "Darwin" ]; then + ln -s Electron.app/Contents/MacOS/Electron "${NODE_ROOT}/node_modules/electron/dist/node" +else + ln -s electron "${NODE_ROOT}/node_modules/electron/dist/node" +fi + +find ${NODE_ROOT}/node_modules/electron/dist/ + +which electron +which node + +if [ "${OS}" = "Linux" ]; then + export DISPLAY=':99.0' + Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & + xvfb_process=$! +fi + +node --version + +check_runtime_electronjs + +run_electronjs_inference_tests + +if [ "${OS}" = "Linux" ]; then + sleep 1 + kill -9 ${xvfb_process} || true +fi diff --git a/tc-node-tests-prod.sh b/tc-node-tests-prod.sh index 167b4ff0..6f55810b 100644 --- a/tc-node-tests-prod.sh +++ b/tc-node-tests-prod.sh @@ -25,4 +25,6 @@ npm install ${DEEPSPEECH_NODEJS}/deepspeech-${DS_VERSION}.tgz export PATH=$HOME/node_modules/.bin/:$PATH +check_runtime_nodejs + run_prod_inference_tests diff --git a/tc-node-tests.sh b/tc-node-tests.sh index 7578be8f..4504b1ef 100644 --- a/tc-node-tests.sh +++ b/tc-node-tests.sh @@ -22,4 +22,6 @@ export PATH="${NODE_ROOT}:${NODE_PATH}/.bin/:$PATH" npm install --prefix ${NODE_ROOT} ${DEEPSPEECH_NODEJS}/deepspeech-${DS_VERSION}.tgz +check_runtime_nodejs + run_all_inference_tests diff --git a/tc-tests-utils.sh b/tc-tests-utils.sh index 9f393001..b5a2f22c 100755 --- a/tc-tests-utils.sh +++ b/tc-tests-utils.sh @@ -57,6 +57,7 @@ model_source_mmap="$(dirname "${model_source}")/${model_name_mmap}" SUPPORTED_PYTHON_VERSIONS=${SUPPORTED_PYTHON_VERSIONS:-2.7.15:ucs2 2.7.15:ucs4 3.4.9:ucs4 3.5.6:ucs4 3.6.7:ucs4 3.7.1:ucs4} SUPPORTED_NODEJS_VERSIONS=${SUPPORTED_NODEJS_VERSIONS:-4.9.1 5.12.0 6.14.4 7.10.1 8.12.0 9.11.2 10.12.0 11.0.0} +SUPPORTED_ELECTRONJS_VERSIONS=${SUPPORTED_ELECTRONJS_VERSIONS:-1.6.18 1.7.16 1.8.8 2.0.18 3.0.16 3.1.8 4.0.3 4.1.4} strip() { echo "$(echo $1 | sed -e 's/^[[:space:]]+//' -e 's/[[:space:]]+$//')" @@ -284,6 +285,27 @@ check_tensorflow_version() assert_deepspeech_version "${ds_help}" } +assert_deepspeech_runtime() +{ + local expected_runtime=$1 + + set +e + local ds_version=$(${DS_BINARY_PREFIX}deepspeech --version 2>&1) + set -e + + assert_shows_something "${ds_version}" "${expected_runtime}" +} + +check_runtime_nodejs() +{ + assert_deepspeech_runtime "Runtime: Node" +} + +check_runtime_electronjs() +{ + assert_deepspeech_runtime "Runtime: Electron" +} + run_tflite_basic_inference_tests() { set +e @@ -310,6 +332,24 @@ run_netframework_inference_tests() assert_working_ldc93s1_lm "${phrase_pbmodel_withlm}" "$?" } +run_electronjs_inference_tests() +{ + set +e + phrase_pbmodel_nolm=$(deepspeech --model ${TASKCLUSTER_TMP_DIR}/${model_name} --alphabet ${TASKCLUSTER_TMP_DIR}/alphabet.txt --audio ${TASKCLUSTER_TMP_DIR}/LDC93S1.wav 2>${TASKCLUSTER_TMP_DIR}/stderr) + set -e + assert_working_ldc93s1 "${phrase_pbmodel_nolm}" "$?" + + set +e + phrase_pbmodel_nolm=$(deepspeech --model ${TASKCLUSTER_TMP_DIR}/${model_name_mmap} --alphabet ${TASKCLUSTER_TMP_DIR}/alphabet.txt --audio ${TASKCLUSTER_TMP_DIR}/LDC93S1.wav 2>${TASKCLUSTER_TMP_DIR}/stderr) + set -e + assert_working_ldc93s1 "${phrase_pbmodel_nolm}" "$?" + + set +e + phrase_pbmodel_withlm=$(deepspeech --model ${TASKCLUSTER_TMP_DIR}/${model_name_mmap} --alphabet ${TASKCLUSTER_TMP_DIR}/alphabet.txt --lm ${TASKCLUSTER_TMP_DIR}/lm.binary --trie ${TASKCLUSTER_TMP_DIR}/trie --audio ${TASKCLUSTER_TMP_DIR}/LDC93S1.wav 2>${TASKCLUSTER_TMP_DIR}/stderr) + set -e + assert_working_ldc93s1_lm "${phrase_pbmodel_withlm}" "$?" +} + run_basic_inference_tests() { set +e @@ -1110,6 +1150,17 @@ do_deepspeech_nodejs_build() clean node-wrapper done; + for electron in ${SUPPORTED_ELECTRONJS_VERSIONS}; do + EXTRA_CFLAGS="${EXTRA_LOCAL_CFLAGS}" EXTRA_LDFLAGS="${EXTRA_LOCAL_LDFLAGS}" EXTRA_LIBS="${EXTRA_LOCAL_LIBS}" make -C native_client/javascript \ + TARGET=${SYSTEM_TARGET} \ + RASPBIAN=${SYSTEM_RASPBIAN} \ + TFDIR=${DS_TFDIR} \ + NODE_ABI_TARGET=--target=$electron \ + NODE_DIST_URL=--disturl=https://atom.io/download/electron \ + NODE_RUNTIME=--runtime=electron \ + clean node-wrapper + done; + if [ "${rename_to_gpu}" ]; then make -C native_client/javascript clean npm-pack PROJECT_NAME=deepspeech-gpu else