Initial commit

James Peret 8 years ago
commit
aa208ce676
5 changed files with 230 additions and 0 deletions
  1. 4 0
      .gitignore
  2. BIN
      computerbeep_15.mp3
  3. 77 0
      index.js
  4. 131 0
      node-speakable.js
  5. 18 0
      package.json

+ 4 - 0
.gitignore

@@ -0,0 +1,4 @@
1
+/node_modules
2
+/lib
3
+.DS_Store
4
+sample.wav

BIN
computerbeep_15.mp3


+ 77 - 0
index.js

@@ -0,0 +1,77 @@
1
+var Speakable = require('./node_modules/speakable');
2
+var speakable = new Speakable({key: 'AIzaSyBOti4mM-6x9WDnZIjIeyEU21OpBXqWBgw'}, {lang: 'en-US'});
3
+
4
+var say = require('say');
5
+
6
+var play = require('./node_modules/play');
7
+
8
+var io = require('socket.io-client');
9
+var socket = io.connect('http://localhost:9090');
10
+
11
+var dialogue_messages = [];
12
+var talking = false;
13
+
14
+socket.on('connect', function(){
15
+  console.log('Connected to server')
16
+  speakable.recordVoice();
17
+});
18
+
19
+socket.on('message', function(data){
20
+  dialogue_messages.push(data)
21
+  if(!talking){
22
+    talking = true
23
+    speak();
24
+  }
25
+
26
+});
27
+
28
+socket.on('disconnect', function(){
29
+  speakable.resetVoice();
30
+});
31
+
32
+
33
+
34
+speakable.on('speechStart', function() {
35
+  console.log('onSpeechStart');
36
+});
37
+
38
+speakable.on('speechStop', function() {
39
+  console.log('onSpeechStop');
40
+  play.sound('./computerbeep_15.mp3');
41
+});
42
+
43
+speakable.on('speechReady', function() {
44
+  console.log('onSpeechReady');
45
+});
46
+
47
+speakable.on('error', function(err) {
48
+  console.log('onError:');
49
+  console.log(err);
50
+  speakable.recordVoice();
51
+});
52
+
53
+speakable.on('speechResult', function(recognizedWords) {
54
+  console.log('onSpeechResult:')
55
+  console.log(recognizedWords);
56
+  if(recognizedWords != ""){
57
+    socket.emit('message', recognizedWords);
58
+  } else {
59
+    speakable.recordVoice();
60
+  }
61
+});
62
+
63
+var speak = function() {
64
+  say.speak(dialogue_messages[0], 'Alex', 1.0, function(err){
65
+    if (err) {
66
+      return console.error(err);
67
+    }
68
+    dialogue_messages.shift();
69
+    if(dialogue_messages.length > 0) {
70
+      speak();
71
+    } else {
72
+      talking = false;
73
+      speakable.resetVoice();
74
+      speakable.recordVoice();
75
+    }
76
+  });
77
+}

+ 131 - 0
node-speakable.js

@@ -0,0 +1,131 @@
1
+// Wit.ai API
2
+
3
+var EventEmitter = require('events').EventEmitter,
4
+    util = require('util'),
5
+    spawn = require('child_process').spawn,
6
+    http = require('follow-redirects').http;
7
+    https = require('follow-redirects').https;
8
+
9
+var Speakable = function Speakable(credentials, options) {
10
+  EventEmitter.call(this);
11
+
12
+  options = options || {}
13
+
14
+  this.recBuffer = [];
15
+  this.recRunning = false;
16
+  this.apiResult = {};
17
+  this.apiLang = options.lang || "en-US";
18
+  this.apiKey = credentials.key
19
+  this.cmd = (options.sox_path) || 'sox';
20
+  this.cmdArgs = [
21
+    '-q',
22
+    '-v', '0.98',
23
+    '-b','16',
24
+    '-d','-t','mp3','-',
25
+    'rate','8000','channels','1',
26
+    'silence','1','0.1',(options.threshold || '0.1')+'%2','1','1.0',(options.threshold || '0.1')+'%2'
27
+  ];
28
+};
29
+
30
+util.inherits(Speakable, EventEmitter);
31
+module.exports = Speakable;
32
+
33
+Speakable.prototype.postVoiceData = function() {
34
+  var self = this;
35
+
36
+  var options = {
37
+    hostname: 'api.wit.ai',
38
+    path: '/speech',
39
+    maxRedirects: 10,
40
+    method: 'POST',
41
+    headers: {
42
+      "Authorization": "Bearer Q6NTRBF6CVKOGJUQFZGHASQSLKRAX4SX",
43
+      'Content-Type': 'audio/mpeg3'
44
+    }
45
+  };
46
+
47
+  var req = https.request(options, function(res) {
48
+    self.recBuffer = [];
49
+    res.setEncoding('utf8');
50
+    res.on('data', function (chunk) {
51
+      console.log(chunk);
52
+      self.apiResult = JSON.parse(chunk);
53
+    });
54
+
55
+    if(res.statusCode !== 200) {
56
+      return self.emit(
57
+        'error',
58
+        'Non-200 answer from Wit.ai Speech API (' + res.statusCode + ') \n' + JSON.stringify(res.headers)
59
+      );
60
+    }
61
+    res.on('end', function() {
62
+      self.parseResult();
63
+    });
64
+  });
65
+
66
+  req.on('error', function(e) {
67
+    self.emit('error', e);
68
+  });
69
+
70
+  // write data to request body
71
+  console.log('Posting voice data...');
72
+  for(var i in self.recBuffer) {
73
+    if(self.recBuffer.hasOwnProperty(i)) {
74
+      req.write(new Buffer(self.recBuffer[i],'binary'));
75
+      console.log(new Buffer(self.recBuffer[i],'binary'))
76
+    }
77
+  }
78
+  req.end();
79
+};
80
+
81
+Speakable.prototype.recordVoice = function() {
82
+  var self = this;
83
+
84
+  var rec = spawn(self.cmd, self.cmdArgs, { stdio: 'pipe' });
85
+
86
+  // Process stdout
87
+
88
+  rec.stdout.on('readable', function() {
89
+    self.emit('speechReady');
90
+  });
91
+
92
+  rec.stdout.setEncoding('binary');
93
+  rec.stdout.on('data', function(data) {
94
+    if(! self.recRunning) {
95
+      self.emit('speechStart');
96
+      self.recRunning = true;
97
+    }
98
+    self.recBuffer.push(data);
99
+  });
100
+
101
+  // Process stdin
102
+
103
+  rec.stderr.setEncoding('utf8');
104
+  rec.stderr.on('data', function(data) {
105
+    console.log(data)
106
+  });
107
+
108
+  rec.on('close', function(code) {
109
+    self.recRunning = false;
110
+    if(code) {
111
+      self.emit('error', 'sox exited with code ' + code);
112
+    }
113
+    self.emit('speechStop');
114
+    self.postVoiceData();
115
+  });
116
+};
117
+
118
+Speakable.prototype.resetVoice = function() {
119
+  var self = this;
120
+  self.recBuffer = [];
121
+}
122
+
123
+Speakable.prototype.parseResult = function() {
124
+  var recognizedWords = [], apiResult = this.apiResult.result;
125
+  if(apiResult && apiResult.length > 0 && apiResult[0].alternative && apiResult[0].alternative[0]) {
126
+    recognizedWords = apiResult[0].alternative[0].transcript.split(' ');
127
+    this.emit('speechResult', recognizedWords);
128
+  } else {
129
+    this.emit('speechResult', []);
130
+  }
131
+}

+ 18 - 0
package.json

@@ -0,0 +1,18 @@
1
+{
2
+  "name": "speakable-test",
3
+  "version": "1.0.0",
4
+  "description": "",
5
+  "main": "index.js",
6
+  "scripts": {
7
+    "test": "echo \"Error: no test specified\" && exit 1"
8
+  },
9
+  "author": "James Peret",
10
+  "license": "ISC",
11
+  "dependencies": {
12
+    "follow-redirects": "0.0.7",
13
+    "play": "^0.5.0",
14
+    "say": "^0.9.0",
15
+    "socket.io-client": "^1.4.5",
16
+    "speakable": "^0.3.0"
17
+  }
18
+}