Skip to content

Commit f776892

Browse files
authored
[speech-commands] Add versioning and release infra (#71)
Also in this PR: * Add make-version script for automatic edits to version.ts * Add unit test for exposed version string in the public API. * In demo, increase the default number of training epochs for transfer learning from 20 to 40 (based on empirical observation of the transfer-learning accuracy) * In the example in README.md, reflect the fact that @tensorflow/tfjs is a peer dependency.
1 parent b073413 commit f776892

14 files changed

Lines changed: 220 additions & 48 deletions

speech-commands/README.md

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,19 @@ To use the speech-command recognizer, first create a recognizer instance,
3737
then start the streaming recognition by calling its `startStreaming()` method.
3838

3939
```js
40-
import * as SpeechCommands from '@tensorflow-models/speech-commands';
40+
import * as tf from '@tensorflow/tfjs';
41+
import * as speechCommands from '@tensorflow-models/speech-commands';
4142

4243
// When calling `create()`, you must provide the type of the audio input.
4344
// The two available options are `BROWSER_FFT` and `SOFT_FFT`.
4445
// - BROWSER_FFT uses the browser's native Fourier transform.
4546
// - SOFT_FFT uses JavaScript implementations of Fourier transform
4647
// (not implemented yet).
47-
const recognizer = SpeechCommands.create('BROWSER_FFT');
48+
const recognizer = speechCommands.create('BROWSER_FFT');
49+
50+
// Make sure that the underlying model and metadata are loaded via HTTPS
51+
// requests.
52+
await recognizer.ensureModelLoaded();
4853

4954
// See the array of words that the recognizer is trained to recognize.
5055
console.log(recognizer.wordLabels());
@@ -72,6 +77,10 @@ setTimeout(() => recognizer.stopStreaming(), 10e3);
7277
As the example above shows, you can specify optional parameters when calling
7378
`startStreaming()`. The supported parameters are:
7479

80+
* `overlapFactor`: Controls how often the recognizer performs predicton on
81+
spectrograms. Must be a number between 0 and 1 (default: 0.5). For example,
82+
if each spectrogram is 1000 ms long and `overlapFactor` is set to 0.25,
83+
the prediction will happen every 250 ms.
7584
* `includeSpectrogram`: Let the callback function be invoked with the
7685
spectrogram data included in the argument. Default: `false`.
7786
* `probabilityThreshold`: The callback function will be invoked if and only if
@@ -93,9 +102,9 @@ E.g.,
93102

94103
```js
95104
import * as tf from '@tensorflow/tfjs';
96-
import * as SpeechCommands from '@tensorflow-models/speech-commands';
105+
import * as speechCommands from '@tensorflow-models/speech-commands';
97106

98-
const recognizer = SpeechCommands.create('BROWSER_FFT');
107+
const recognizer = speechCommands.create('BROWSER_FFT');
99108

100109
// Inspect the input shape of the recognizer's underlying tf.Model.
101110
console.log(recognizer.modelInputShape());
@@ -156,7 +165,7 @@ this type of transfer learning. The steps are listed in the example
156165
code snippet below
157166

158167
```js
159-
const baseRecognizer = SpeechCommands.create('BROWSER_FFT');
168+
const baseRecognizer = speechCommands.create('BROWSER_FFT');
160169
await baseRecognizer.ensureModelLoaded();
161170

162171
// Each instance of speech-command recognizer supports multiple

speech-commands/demo/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@
157157
<div id="collect-words"></div>
158158
<div class="settings">
159159
<span>Epochs:</span>
160-
<input class="settings" size="5" id="epochs" value="20">
160+
<input class="settings" size="5" id="epochs" value="40">
161161
<button id="start-transfer-learn" disabled="true">Start transfer learning</button>
162162
</div>
163163
<div id="plots">

speech-commands/demo/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"node": ">=8.9.0"
1010
},
1111
"dependencies": {
12-
"@tensorflow/tfjs": "^0.12.5",
12+
"@tensorflow/tfjs": "^0.12.7",
1313
"stats.js": "^0.17.0"
1414
},
1515
"scripts": {

speech-commands/demo/yarn.lock

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,33 +45,33 @@
4545
version "1.1.0"
4646
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
4747

48-
"@tensorflow/tfjs-converter@0.5.7":
49-
version "0.5.7"
50-
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-converter/-/tfjs-converter-0.5.7.tgz#b4b1a49cf90b5106a4351f1941c77c52f3f22ce9"
48+
"@tensorflow/tfjs-converter@0.5.9":
49+
version "0.5.9"
50+
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-converter/-/tfjs-converter-0.5.9.tgz#76913bd916bbd940b6435e9e3ec63f963c786b95"
5151
dependencies:
5252
"@types/long" "~3.0.32"
5353
protobufjs "~6.8.6"
5454

55-
"@tensorflow/tfjs-core@0.12.11":
56-
version "0.12.11"
57-
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-0.12.11.tgz#8da98fae720e58a484315d2e72d0c858991e4aee"
55+
"@tensorflow/tfjs-core@0.12.17":
56+
version "0.12.17"
57+
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-0.12.17.tgz#133fef53272e4dc0819890e79153c8ee094400b6"
5858
dependencies:
5959
"@types/seedrandom" "~2.4.27"
6060
"@types/webgl-ext" "~0.0.29"
6161
"@types/webgl2" "~0.0.4"
6262
seedrandom "~2.4.3"
6363

64-
"@tensorflow/tfjs-layers@0.7.4":
65-
version "0.7.4"
66-
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-layers/-/tfjs-layers-0.7.4.tgz#575a3bc2c895501c619b4b7102b4e17256c30835"
64+
"@tensorflow/tfjs-layers@0.7.5":
65+
version "0.7.5"
66+
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-layers/-/tfjs-layers-0.7.5.tgz#54241110e0a6e194eafbbd18babca0978788e930"
6767

68-
"@tensorflow/tfjs@^0.12.5":
69-
version "0.12.5"
70-
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs/-/tfjs-0.12.5.tgz#60d449457c99b661b4dce9e665e97f2476bc544c"
68+
"@tensorflow/tfjs@^0.12.7":
69+
version "0.12.7"
70+
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs/-/tfjs-0.12.7.tgz#2fb643f503dada14b7f0ca43d2a41082b626f92a"
7171
dependencies:
72-
"@tensorflow/tfjs-converter" "0.5.7"
73-
"@tensorflow/tfjs-core" "0.12.11"
74-
"@tensorflow/tfjs-layers" "0.7.4"
72+
"@tensorflow/tfjs-converter" "0.5.9"
73+
"@tensorflow/tfjs-core" "0.12.17"
74+
"@tensorflow/tfjs-layers" "0.7.5"
7575

7676
"@types/long@^4.0.0":
7777
version "4.0.0"

speech-commands/make-version

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env node
2+
// Copyright 2018 Google LLC. All Rights Reserved.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
// =============================================================================
16+
17+
// Run this script from the base directory (not the script directory):
18+
// ./scripts/make-version
19+
20+
const fs = require('fs');
21+
const version = JSON.parse(fs.readFileSync('package.json', 'utf8')).version;
22+
23+
const versionCode =
24+
`/** @license See the LICENSE file. */
25+
// This code is auto-generated, do not modify this file!
26+
const version = '${version}';
27+
export {version};
28+
`
29+
30+
fs.writeFile('src/version.ts', versionCode, err => {
31+
if (err) {
32+
throw new Error(`Could not save version file ${version} : $ { err }`);
33+
}
34+
console.log(`Version file for version ${version} saved sucessfully.`);
35+
});

speech-commands/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tensorflow-models/speech-commands",
3-
"version": "0.1.0",
3+
"version": "0.1.1",
44
"description": "Speech-command recognizer in TensorFlow.js",
55
"main": "dist/index.js",
66
"unpkg": "dist/speech-commands.min.js",
@@ -13,10 +13,10 @@
1313
"url": "https://github.com/tensorflow/tfjs-models.git"
1414
},
1515
"peerDependencies": {
16-
"@tensorflow/tfjs": "^0.12.5"
16+
"@tensorflow/tfjs": "^0.12.7"
1717
},
1818
"devDependencies": {
19-
"@tensorflow/tfjs": "^0.12.5",
19+
"@tensorflow/tfjs": "^0.12.7",
2020
"@types/jasmine": "~2.8.8",
2121
"babel-core": "~6.26.0",
2222
"babel-plugin-transform-runtime": "~6.23.0",
@@ -34,7 +34,7 @@
3434
"yalc": "~1.0.0-pre.21"
3535
},
3636
"scripts": {
37-
"build": "tsc",
37+
"build": "rimraf dist && tsc && rollup -c",
3838
"lint": "tslint -p . -t verbose",
3939
"publish-local": "yarn build && yalc push",
4040
"test": "yarn build && ts-node run_tests.ts"

speech-commands/rollup.config.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**
2+
* @license
3+
* Copyright 2018 Google Inc. All Rights Reserved.
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
* =============================================================================
16+
*/
17+
18+
import node from 'rollup-plugin-node-resolve';
19+
import typescript from 'rollup-plugin-typescript2';
20+
import uglify from 'rollup-plugin-uglify';
21+
22+
const PREAMBLE =
23+
`// @tensorflow/tfjs-models Copyright ${(new Date).getFullYear()} Google`;
24+
25+
function minify() {
26+
return uglify({
27+
output: {
28+
preamble: PREAMBLE
29+
}
30+
});
31+
}
32+
33+
function config({
34+
plugins = [],
35+
output = {}
36+
}) {
37+
return {
38+
input: 'src/index.ts',
39+
plugins: [
40+
typescript({
41+
tsconfigOverride: {
42+
compilerOptions: {
43+
module: 'ES2015'
44+
}
45+
}
46+
}),
47+
node(), ...plugins
48+
],
49+
output: {
50+
banner: PREAMBLE,
51+
globals: {
52+
'@tensorflow/tfjs': 'tf'
53+
},
54+
...output
55+
},
56+
external: ['@tensorflow/tfjs']
57+
};
58+
}
59+
60+
export default [
61+
config({
62+
output: {
63+
format: 'umd',
64+
name: 'SpeechCommands',
65+
file: 'dist/speech-commands.js'
66+
}
67+
}),
68+
config({
69+
plugins: [minify()],
70+
output: {
71+
format: 'umd',
72+
name: 'SpeechCommands',
73+
file: 'dist/speech-commands.min.js'
74+
}
75+
}),
76+
config({
77+
plugins: [minify()],
78+
output: {
79+
format: 'es',
80+
file: 'dist/speech-commands.esm.js'
81+
}
82+
})
83+
];

speech-commands/src/browser_fft_recognizer.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import * as tf from '@tensorflow/tfjs';
2121
import {BrowserFftFeatureExtractor, SpectrogramCallback} from './browser_fft_extractor';
2222
import {loadMetadataJson} from './browser_fft_utils';
2323
import {RecognizerCallback, RecognizerParams, SpectrogramData, SpeechCommandRecognizer, SpeechCommandRecognizerResult, StreamingRecognitionConfig, TransferLearnConfig, TransferSpeechCommandRecognizer} from './types';
24+
import {version} from './version';
2425

2526
// tslint:enable:max-line-length
2627

@@ -36,9 +37,9 @@ export class BrowserFftSpeechCommandRecognizer implements
3637
SpeechCommandRecognizer {
3738
// tslint:disable:max-line-length
3839
readonly DEFAULT_MODEL_JSON_URL =
39-
'https://storage.googleapis.com/tfjs-speech-commands-models/20w/model.json';
40+
`https://storage.googleapis.com/tfjs-speech-commands-models/v${version}/browser_fft/20w/model.json`;
4041
readonly DEFAULT_METADATA_JSON_URL =
41-
'https://storage.googleapis.com/tfjs-speech-commands-models/20w/metadata.json';
42+
`https://storage.googleapis.com/tfjs-speech-commands-models/v${version}/browser_fft/20w/metadata.json`;
4243
// tslint:enable:max-line-length
4344

4445
private readonly SAMPLE_RATE_HZ = 44100;

speech-commands/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,4 @@ export function create(fftType: FFT_TYPE): SpeechCommandRecognizer {
4141
// tslint:disable-next-line:max-line-length
4242
export {FFT_TYPE, RecognizerParams, SpectrogramData, SpeechCommandRecognizerResult, StreamingRecognitionConfig, TransferLearnConfig} from './types';
4343
export {BACKGROUND_NOISE_TAG, UNKNOWN_TAG} from './browser_fft_recognizer';
44+
export {version} from './version';

speech-commands/src/index_test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* @license
3+
* Copyright 2018 Google LLC. All Rights Reserved.
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
* =============================================================================
16+
*/
17+
18+
const packageJSON = require('../package.json');
19+
import * as speechCommands from './index';
20+
21+
describe('Public API', () => {
22+
it('version matches package.json', () => {
23+
expect(typeof speechCommands.version).toEqual('string');
24+
expect(speechCommands.version).toEqual(packageJSON.version);
25+
});
26+
});

0 commit comments

Comments
 (0)