diff --git a/speech/.idea/inspectionProfiles/profiles_settings.xml b/speech/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 00000000000..c23ecacb3a2 --- /dev/null +++ b/speech/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/speech/.idea/misc.xml b/speech/.idea/misc.xml new file mode 100644 index 00000000000..b317e4e3aa6 --- /dev/null +++ b/speech/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/speech/.idea/modules.xml b/speech/.idea/modules.xml new file mode 100644 index 00000000000..3ec43b5d653 --- /dev/null +++ b/speech/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/speech/.idea/speech.iml b/speech/.idea/speech.iml new file mode 100644 index 00000000000..9bcf65eeed4 --- /dev/null +++ b/speech/.idea/speech.iml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/speech/.idea/workspace.xml b/speech/.idea/workspace.xml new file mode 100644 index 00000000000..47ebb16fb03 --- /dev/null +++ b/speech/.idea/workspace.xml @@ -0,0 +1,760 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + en-E + + + + + + + + + true + DEFINITION_ORDER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + project + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1489772607623 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/speech/grpc/chatdemo.py b/speech/grpc/chatdemo.py new file mode 100755 index 00000000000..f0e5246fcf7 --- /dev/null +++ b/speech/grpc/chatdemo.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +"""Simplified chat demo for websockets. + +Authentication, error handling, etc are left as an exercise for the reader :) +""" + +import logging +import tornado.escape +import tornado.ioloop +import tornado.options +import tornado.web +import tornado.websocket +import os.path +import uuid + +from tornado.options import define, options + +define("port", default=8888, help="run on the given port", type=int) + + +class Application(tornado.web.Application): + def __init__(self): + handlers = [ + (r"/", MainHandler), + (r"/test", TestHandler), + (r"/chatsocket", ChatSocketHandler), + ] + settings = dict( + cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__", + template_path=os.path.join(os.path.dirname(__file__), "templates"), + static_path=os.path.join(os.path.dirname(__file__), "static"), + xsrf_cookies=False, + ) + super(Application, self).__init__(handlers, **settings) + + +class MainHandler(tornado.web.RequestHandler): + def get(self): + self.render("index.html", messages=ChatSocketHandler.cache)\ + +class TestHandler(tornado.web.RequestHandler): + def post(self): + self.set_header("Content-Type", "text/plain") + self.write("You wrote " + self.get_body_argument("message")) + + # def post(self, message): + # # self.render("index.html", messages=ChatSocketHandler.cache) + # logging.info(message) + chat = {'body': u'{}'.format(self.get_body_argument("message")), + 'html': '
dasdasda
\n', + 'id': 'cf6aef33-cb77-4df5-91a4-852d560ef097'} + ChatSocketHandler.send_updates(chat) + +class ChatSocketHandler(tornado.websocket.WebSocketHandler): + waiters = set() + cache = [] + cache_size = 200 + + def get_compression_options(self): + # Non-None enables compression with default options. + return {} + + def open(self): + ChatSocketHandler.waiters.add(self) + + def on_close(self): + ChatSocketHandler.waiters.remove(self) + + @classmethod + def update_cache(cls, chat): + cls.cache.append(chat) + if len(cls.cache) > cls.cache_size: + cls.cache = cls.cache[-cls.cache_size:] + + @classmethod + def send_updates(cls, chat): + logging.info("sending message to %d waiters", len(cls.waiters)) + print(chat) + for waiter in cls.waiters: + try: + waiter.write_message(chat) + except: + logging.error("Error sending message", exc_info=True) + + def on_message(self, message): + logging.info("got message %r", message) + parsed = tornado.escape.json_decode(message) + chat = { + "id": str(uuid.uuid4()), + "body": parsed["body"], + } + chat["html"] = tornado.escape.to_basestring( + self.render_string("message.html", message=chat)) + + ChatSocketHandler.update_cache(chat) + ChatSocketHandler.send_updates(chat) + + +def main(): + tornado.options.parse_command_line() + app = Application() + app.listen(options.port) + tornado.ioloop.IOLoop.current().start() + + +if __name__ == "__main__": + main() diff --git a/speech/grpc/requirements.txt b/speech/grpc/requirements.txt index 13377b67c29..cd8f97b5fdd 100644 --- a/speech/grpc/requirements.txt +++ b/speech/grpc/requirements.txt @@ -1,6 +1,56 @@ +appdirs==1.4.3 +awscli==1.11.61 +awsebcli==3.10.0 +backports-abc==0.5 +backports.ssl-match-hostname==3.5.0.1 +beautifulsoup4==4.5.3 +biopython==1.68 +blessed==1.14.1 +boto3==1.4.3 +botocore==1.5.26 +bs4==0.0.1 +cement==2.8.2 +certifi==2017.1.23 +colorama==0.3.7 +docker-py==1.7.2 +dockerpty==0.4.1 +docopt==0.6.2 +docutils==0.13.1 +enum34==1.1.6 +futures==3.0.5 +google-auth==0.8.0 +googleapis-common-protos==1.5.2 grpcio==1.1.0 -PyAudio==0.2.10 +html5lib==0.999999999 +httplib2==0.10.3 +jmespath==0.9.2 +lxml==3.7.3 +mechanize==0.2.5 +numpy==1.12.0 +oauth2client==3.0.0 +packaging==16.8 +pandas==0.19.2 +pathspec==0.5.0 proto-google-cloud-speech-v1beta1==0.15.1 +protobuf==3.2.0 +pyasn1==0.2.3 +pyasn1-modules==0.0.8 +PyAudio==0.2.10 +PyExecJS==1.4.0 +pyparsing==2.2.0 +python-dateutil==2.6.0 +pytz==2016.10 +PyYAML==3.12 +requests==2.9.1 +rsa==3.4.2 +s3transfer==0.1.10 +selenium==3.3.1 +semantic-version==2.5.0 +singledispatch==3.4.0.3 six==1.10.0 -requests==2.13.0 -google-auth==0.8.0 +tabulate==0.7.5 +termcolor==1.1.0 +tornado==4.4.2 +wcwidth==0.1.7 +webencodings==0.5 +websocket-client==0.40.0 diff --git a/speech/grpc/static/chat.css b/speech/grpc/static/chat.css new file mode 100644 index 00000000000..a400c326057 --- /dev/null +++ b/speech/grpc/static/chat.css @@ -0,0 +1,56 @@ +/* + * Copyright 2009 FriendFeed + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +body { + background: white; + margin: 10px; +} + +body, +input { + font-family: sans-serif; + font-size: 10pt; + color: black; +} + +table { + border-collapse: collapse; + border: 0; +} + +td { + border: 0; + padding: 0; +} + +#body { + position: absolute; + bottom: 10px; + left: 10px; +} + +#input { + margin-top: 0.5em; +} + +#inbox .message { + padding-top: 0.25em; +} + +#nav { + float: right; + z-index: 99; +} diff --git a/speech/grpc/static/chat.js b/speech/grpc/static/chat.js new file mode 100644 index 00000000000..5c32761a453 --- /dev/null +++ b/speech/grpc/static/chat.js @@ -0,0 +1,71 @@ +// Copyright 2009 FriendFeed +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +$(document).ready(function() { + if (!window.console) window.console = {}; + if (!window.console.log) window.console.log = function() {}; + + $("#messageform").on("submit", function() { + newMessage($(this)); + return false; + }); + $("#messageform").on("keypress", function(e) { + if (e.keyCode == 13) { + newMessage($(this)); + return false; + } + }); + $("#message").select(); + updater.start(); +}); + +function newMessage(form) { + var message = form.formToDict(); + updater.socket.send(JSON.stringify(message)); + form.find("input[type=text]").val("").select(); +} + +jQuery.fn.formToDict = function() { + var fields = this.serializeArray(); + var json = {} + for (var i = 0; i < fields.length; i++) { + json[fields[i].name] = fields[i].value; + } + if (json.next) delete json.next; + return json; +}; + +var updater = { + socket: null, + + start: function() { + var url = "ws://192.168.85.196/chatsocket"; + console.log("received message"); + updater.socket = new WebSocket(url); + updater.socket.onmessage = function(event) { + updater.showMessage(JSON.parse(event.data)); + console.log("received message "+JSON.parse(event.data).body); + responsiveVoice.speak(JSON.parse(event.data).body, 'Thai Female'); + } + }, + + showMessage: function(message) { + var existing = $("#m" + message.id); + if (existing.length > 0) return; + var node = $(message.html); + node.hide(); + $("#inbox").append(node); + node.slideDown(); + } +}; diff --git a/speech/grpc/templates/chat.css b/speech/grpc/templates/chat.css new file mode 100644 index 00000000000..a400c326057 --- /dev/null +++ b/speech/grpc/templates/chat.css @@ -0,0 +1,56 @@ +/* + * Copyright 2009 FriendFeed + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +body { + background: white; + margin: 10px; +} + +body, +input { + font-family: sans-serif; + font-size: 10pt; + color: black; +} + +table { + border-collapse: collapse; + border: 0; +} + +td { + border: 0; + padding: 0; +} + +#body { + position: absolute; + bottom: 10px; + left: 10px; +} + +#input { + margin-top: 0.5em; +} + +#inbox .message { + padding-top: 0.25em; +} + +#nav { + float: right; + z-index: 99; +} diff --git a/speech/grpc/templates/chat.js b/speech/grpc/templates/chat.js new file mode 100644 index 00000000000..8cc89021c9b --- /dev/null +++ b/speech/grpc/templates/chat.js @@ -0,0 +1,73 @@ +// Copyright 2009 FriendFeed +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +$(document).ready(function() { + if (!window.console) window.console = {}; + if (!window.console.log) window.console.log = function() {}; + + $("#messageform").on("submit", function() { + newMessage($(this)); + return false; + }); + $("#messageform").on("keypress", function(e) { + if (e.keyCode == 13) { + newMessage($(this)); + return false; + } + }); + $("#message").select(); + updater.start(); +}); + +function newMessage(form) { + var message = form.formToDict(); + updater.socket.send(JSON.stringify(message)); + form.find("input[type=text]").val("").select(); +} + +jQuery.fn.formToDict = function() { + var fields = this.serializeArray(); + var json = {} + for (var i = 0; i < fields.length; i++) { + json[fields[i].name] = fields[i].value; + } + if (json.next) delete json.next; + return json; +}; + +var updater = { + socket: null, + + start: function() { + // var url = "ws://" + location.host + "/chatsocket"; + var url = "ws://192.168.85.196:8080/chatsocket"; + // var url = "ws://localhost/chatsocket"; + console.log("received message"); + updater.socket = new WebSocket(url); + updater.socket.onmessage = function(event) { + updater.showMessage(JSON.parse(event.data)); + console.log("received message "+JSON.parse(event.data).body); + responsiveVoice.speak(JSON.parse(event.data).body, 'Thai Female'); + } + }, + + showMessage: function(message) { + var existing = $("#m" + message.id); + if (existing.length > 0) return; + var node = $(message.html); + node.hide(); + $("#inbox").append(node); + node.slideDown(); + } +}; diff --git a/speech/grpc/templates/chatdemo.py b/speech/grpc/templates/chatdemo.py new file mode 100755 index 00000000000..f0e5246fcf7 --- /dev/null +++ b/speech/grpc/templates/chatdemo.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +"""Simplified chat demo for websockets. + +Authentication, error handling, etc are left as an exercise for the reader :) +""" + +import logging +import tornado.escape +import tornado.ioloop +import tornado.options +import tornado.web +import tornado.websocket +import os.path +import uuid + +from tornado.options import define, options + +define("port", default=8888, help="run on the given port", type=int) + + +class Application(tornado.web.Application): + def __init__(self): + handlers = [ + (r"/", MainHandler), + (r"/test", TestHandler), + (r"/chatsocket", ChatSocketHandler), + ] + settings = dict( + cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__", + template_path=os.path.join(os.path.dirname(__file__), "templates"), + static_path=os.path.join(os.path.dirname(__file__), "static"), + xsrf_cookies=False, + ) + super(Application, self).__init__(handlers, **settings) + + +class MainHandler(tornado.web.RequestHandler): + def get(self): + self.render("index.html", messages=ChatSocketHandler.cache)\ + +class TestHandler(tornado.web.RequestHandler): + def post(self): + self.set_header("Content-Type", "text/plain") + self.write("You wrote " + self.get_body_argument("message")) + + # def post(self, message): + # # self.render("index.html", messages=ChatSocketHandler.cache) + # logging.info(message) + chat = {'body': u'{}'.format(self.get_body_argument("message")), + 'html': '
dasdasda
\n', + 'id': 'cf6aef33-cb77-4df5-91a4-852d560ef097'} + ChatSocketHandler.send_updates(chat) + +class ChatSocketHandler(tornado.websocket.WebSocketHandler): + waiters = set() + cache = [] + cache_size = 200 + + def get_compression_options(self): + # Non-None enables compression with default options. + return {} + + def open(self): + ChatSocketHandler.waiters.add(self) + + def on_close(self): + ChatSocketHandler.waiters.remove(self) + + @classmethod + def update_cache(cls, chat): + cls.cache.append(chat) + if len(cls.cache) > cls.cache_size: + cls.cache = cls.cache[-cls.cache_size:] + + @classmethod + def send_updates(cls, chat): + logging.info("sending message to %d waiters", len(cls.waiters)) + print(chat) + for waiter in cls.waiters: + try: + waiter.write_message(chat) + except: + logging.error("Error sending message", exc_info=True) + + def on_message(self, message): + logging.info("got message %r", message) + parsed = tornado.escape.json_decode(message) + chat = { + "id": str(uuid.uuid4()), + "body": parsed["body"], + } + chat["html"] = tornado.escape.to_basestring( + self.render_string("message.html", message=chat)) + + ChatSocketHandler.update_cache(chat) + ChatSocketHandler.send_updates(chat) + + +def main(): + tornado.options.parse_command_line() + app = Application() + app.listen(options.port) + tornado.ioloop.IOLoop.current().start() + + +if __name__ == "__main__": + main() diff --git a/speech/grpc/templates/index.html b/speech/grpc/templates/index.html new file mode 100644 index 00000000000..277bde0742a --- /dev/null +++ b/speech/grpc/templates/index.html @@ -0,0 +1,34 @@ + + + + + Tornado Chat Demo + + + + +
+
+ {% for message in messages %} + {% include "message.html" %} + {% end %} +
+
+
+ + + + + +
+ + + {% module xsrf_form_html() %} +
+
+
+
+ + + + diff --git a/speech/grpc/templates/index2.html b/speech/grpc/templates/index2.html new file mode 100644 index 00000000000..277bde0742a --- /dev/null +++ b/speech/grpc/templates/index2.html @@ -0,0 +1,34 @@ + + + + + Tornado Chat Demo + + + + +
+
+ {% for message in messages %} + {% include "message.html" %} + {% end %} +
+
+
+ + + + + +
+ + + {% module xsrf_form_html() %} +
+
+
+
+ + + + diff --git a/speech/grpc/templates/message.html b/speech/grpc/templates/message.html new file mode 100644 index 00000000000..d68cc1d8d8b --- /dev/null +++ b/speech/grpc/templates/message.html @@ -0,0 +1 @@ +
{% module linkify(message["body"]) %}
diff --git a/speech/grpc/transcribe_streaming.py b/speech/grpc/transcribe_streaming.py index 33f3991638d..85815fdfe71 100644 --- a/speech/grpc/transcribe_streaming.py +++ b/speech/grpc/transcribe_streaming.py @@ -1,4 +1,6 @@ #!/usr/bin/python +# -- coding: utf-8 -- + # Copyright (C) 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,6 +34,85 @@ import pyaudio from six.moves import queue +import requests +import json +import time + +import logging +import tornado.escape +import tornado.ioloop +import tornado.options +import tornado.web +import tornado.websocket +import os.path +import uuid + +from tornado.options import define, options + +define("port", default=8888, help="run on the given port", type=int) + +class Application(tornado.web.Application): + def __init__(self): + handlers = [ + (r"/", MainHandler), + (r"/chatsocket", ChatSocketHandler), + ] + settings = dict( + cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__", + template_path=os.path.join(os.path.dirname(__file__), "templates"), + static_path=os.path.join(os.path.dirname(__file__), "static"), + xsrf_cookies=True, + ) + super(Application, self).__init__(handlers, **settings) + +class MainHandler(tornado.web.RequestHandler): + def get(self): + self.render("index.html", messages=ChatSocketHandler.cache) + +class ChatSocketHandler(tornado.websocket.WebSocketHandler): + waiters = set() + cache = [] + cache_size = 200 + + def get_compression_options(self): + # Non-None enables compression with default options. + return {} + + def open(self): + ChatSocketHandler.waiters.add(self) + + def on_close(self): + ChatSocketHandler.waiters.remove(self) + + @classmethod + def update_cache(cls, chat): + cls.cache.append(chat) + if len(cls.cache) > cls.cache_size: + cls.cache = cls.cache[-cls.cache_size:] + + @classmethod + def send_updates(cls, chat): + print("sending updates") + logging.info("sending message to %d waiters", len(cls.waiters)) + for waiter in cls.waiters: + try: + waiter.write_message(chat) + except: + logging.error("Error sending message", exc_info=True) + + def on_message(self, message): + logging.info("got message %r", message) + parsed = tornado.escape.json_decode(message) + chat = { + "id": str(uuid.uuid4()), + "body": parsed["body"], + } + chat["html"] = tornado.escape.to_basestring( + self.render_string("message.html", message=chat)) + + ChatSocketHandler.update_cache(chat) + ChatSocketHandler.send_updates(chat) + # Audio recording parameters RATE = 16000 CHUNK = int(RATE / 10) # 100ms @@ -43,7 +124,6 @@ DEADLINE_SECS = 60 * 3 + 5 SPEECH_SCOPE = 'https://www.googleapis.com/auth/cloud-platform' - def make_channel(host, port): """Creates a secure channel with auth credentials from the environment.""" # Grab application default credentials from the environment @@ -56,7 +136,6 @@ def make_channel(host, port): return google.auth.transport.grpc.secure_authorized_channel( credentials, http_request, target) - def _audio_data_generator(buff): """A generator that yields all available data in the given buffer. @@ -86,13 +165,11 @@ def _audio_data_generator(buff): yield b''.join(data) - def _fill_buffer(buff, in_data, frame_count, time_info, status_flags): """Continuously collect data from the audio stream, into the buffer.""" buff.put(in_data) return None, pyaudio.paContinue - # [START audio_stream] @contextlib.contextmanager def record_audio(rate, chunk): @@ -122,7 +199,6 @@ def record_audio(rate, chunk): audio_interface.terminate() # [END audio_stream] - def request_stream(data_stream, rate, interim_results=True): """Yields `StreamingRecognizeRequest`s constructed from a recording audio stream. @@ -142,7 +218,8 @@ def request_stream(data_stream, rate, interim_results=True): sample_rate=rate, # the rate in hertz # See http://g.co/cloud/speech/docs/languages # for a list of supported languages. - language_code='en-US', # a BCP-47 language tag + language_code='th-TH', # a BCP-47 language tag + # language_code='en-EN', # a BCP-47 language tag ) streaming_config = cloud_speech_pb2.StreamingRecognitionConfig( interim_results=interim_results, @@ -156,7 +233,6 @@ def request_stream(data_stream, rate, interim_results=True): # Subsequent requests can all just have the content yield cloud_speech_pb2.StreamingRecognizeRequest(audio_content=data) - def listen_print_loop(recognize_stream): """Iterates through server responses and prints them. @@ -169,41 +245,279 @@ def listen_print_loop(recognize_stream): final one, print a newline to preserve the finalized transcription. """ num_chars_printed = 0 - for resp in recognize_stream: - if resp.error.code != code_pb2.OK: - raise RuntimeError('Server error: ' + resp.error.message) - - if not resp.results: - continue - - # Display the top transcription - result = resp.results[0] - transcript = result.alternatives[0].transcript - - # Display interim results, but with a carriage return at the end of the - # line, so subsequent lines will overwrite them. - # - # If the previous result was longer than this one, we need to print - # some extra spaces to overwrite the previous result - overwrite_chars = ' ' * max(0, num_chars_printed - len(transcript)) - - if not result.is_final: - sys.stdout.write(transcript + overwrite_chars + '\r') - sys.stdout.flush() - - num_chars_printed = len(transcript) - - else: - print(transcript + overwrite_chars) - - # Exit recognition if any of the transcribed phrases could be - # one of our keywords. - if re.search(r'\b(exit|quit)\b', transcript, re.I): - print('Exiting..') - break + try: + for resp in recognize_stream: + if resp.error.code != code_pb2.OK: + raise RuntimeError('Server error: ' + resp.error.message) + + if not resp.results: + continue + + # Display the top transcription + result = resp.results[0] + transcript = result.alternatives[0].transcript + + # Display interim results, but with a carriage return at the end of the + # line, so subsequent lines will overwrite them. + # + # If the previous result was longer than this one, we need to print + # some extra spaces to overwrite the previous result + overwrite_chars = ' ' * max(0, num_chars_printed - len(transcript)) + if not result.is_final: + sys.stdout.write(transcript + overwrite_chars + '\r') + sys.stdout.flush() + + num_chars_printed = len(transcript) + print(transcript) + else: + print(transcript + overwrite_chars) + + # Exit recognition if any of the transcribed phrases could be + # one of our keywords. + if re.search(r'\b(exit|quit)\b', transcript, re.I): + print('Exiting..') + break + elif re.search(r'\b(ออก)\b', transcript, re.I): + print('Exiting..') + break + # elif transcript == u'ออโต้ เปิดไฟ ' or transcript == u'เอาโต เปิดไฟ ' or transcript == u'oppo เปิดไฟ ' \ + # or transcript == u'auto เปิดไฟ ' or transcript == u' auto เปิดไฟ ' or transcript == u' oppo เปิดไฟ ': + # print('turning on light') + # elif transcript == u'ออโต้ ช่วยด้วย ' or transcript == u'เอาโต ช่วยด้วย ' or transcript == u'oppo ช่วยด้วย ' \ + # or transcript == u'auto ช่วยด้วย ' or transcript == u' auto ช่วยด้วย ' or transcript == u'เอาตัวช่วยด้วย ' \ + # or transcript == u'auto ชื่อด้วย ' or transcript == u'auto ชื่อด้วย ' or transcript == u' oppo ช่วยด้วย ': + # print(u'พร้อมมาช่วยแล้วครับ') + # elif transcript == u'ออโต้ เรียกตำรวจ ' or transcript == u'เอาโต เรียกตำรวจ ' or transcript == u'oppo เรียกตำรวจ ' \ + # or transcript == u'auto เรียกตำรวจ ' or transcript == u' auto เรียกตำรวจ ' or transcript == u'เอาตัวเรียกตำรวจ ' \ + # or transcript == u'auto เรียนตำรวจ ' or transcript == u'auto ตำรวจ ' or transcript == u'ขอโทษตำรวจ ' \ + # or transcript == u'เอาตูดตำรวจ ' or transcript == u' auto ตำรวจ ' or transcript == u'auto ตำรวจ ': + # print(u'ตำรวจอยู่ระหว่างทางกำลังมา') + # elif transcript == u'ออโต้ โรงพยาบาล ' or transcript == u'อัลโตโรงพยาบาล ' or transcript == u'oppo โรงพยาบาล ' \ + # or transcript == u'auto โรงพยาบาล ' or transcript == u' auto โรงพยาบาล ' or transcript == u'เอาตัวโรงพยาบาล ' \ + # or transcript == u'เอาตูดโรงพยาบาล ' or transcript == u'also โรงพยาบาล ': + # print(u'โรงพยาบาลกำลังมาช่วยเหลือครับ ') + # elif transcript == u'ออโต้ เปิดแอร์ ' or transcript == u'เอาโต เปิดแอร์ ' or transcript == u'oppo เปิดแอร์ ' \ + # or transcript == u'auto เปิดแอร์ ' or transcript == u' auto เปิดแอร์ ' or transcript == u'อัลโต้เปิดแอร์ ': + # print('turning on AC') + # elif transcript == u'ออโต้ ไฟใหม้ ' or transcript == u'เอาโต ไฟไหม้ ' or transcript == u'oppo ไฟไหม้' \ + # or transcript == u'auto ไฟไหม้ ' or transcript == u' auto ไฟไหม้ ' or transcript == u'รถตู้ไฟไหม้ '\ + # or transcript == u'oppo find ไม่ ' or transcript == u'เอาตู้ไฟไหม้ ': + # print('ตำรวจดับเพลิงกำลังมาครับ') + # elif transcript == u'ออโต้ เปิดทีวี ' or transcript == u'เอาโต เปิดทีวี ' or transcript == u'oppo เปิดทีวี ' \ + # or transcript == u'auto เปิดทีวี ' or transcript == u' auto เปิดทีวี ': + # print('turning on TV') + + elif u'เปิดไฟ' in transcript: + turn_on_light() + print('turning on light') + time.sleep(2) + text_to_speech(u'อัลโต้ได้ทำการเปิดไฟให้แล้วค่ะ ') + elif u'ปิดไฟ' in transcript: + turn_off_light() + print('turning off light') + time.sleep(2) + text_to_speech(u'อัลโต้ได้ทำการปิดไฟให้แล้วค่ะ ') + elif u'ช่วยด้วย' in transcript: + print(u'พร้อมมาช่วยแล้วครับ') + text_to_speech(u'อัลโต้ได้ส่งข้อความและโทรเรียกคนในบ้านให้แล้วค่ะ ') + elif u'เรียกตำรวจ' in transcript or u'ตำรวจ' in transcript: + print(u'ตำรวจอยู่ระหว่างทางกำลังมา') + time.sleep(2) + text_to_speech(u'อัลโต้ได้เรียกตำรวจให้แล้วนะค่ะ อยู่ระหว่างทางค่ะ ') + elif u'โรงพยาบาล' in transcript: + print(u'โรงพยาบาลกำลังมาช่วยเหลือครับ') + time.sleep(2) + text_to_speech(u'อัลโต้ได้เรียกรถพยาบาลให้แล้วนะค่ะ อยู่ระหว่างทางค่ะ ') + elif u'เปิดแอร์' in transcript: + turn_on_ac() + time.sleep(2) + text_to_speech(u'อัลโต้ได้ทำการเปิดแอร์ให้แล้วค่ะ รอสักพักนะค่ะ ') + print('turning on AC') + elif u'ปิดแอร์' in transcript: + turn_off_ac() + print('turning off AC') + time.sleep(2) + text_to_speech(u'อัลโต้ได้ทำการปิดแอร์ให้แล้วค่ะ สบายใจได้หายห่วง ') + elif u'ไฟไหม้' in transcript: + print('ตำรวจดับเพลิงกำลังมาครับ') + time.sleep(2) + text_to_speech(u'อัลโต้ได้เรียกรถดับเพลิงให้อย่างเร่งด่วนแล้วค่ะ รอสักแป๊ปนะค่ะ ') + elif u'เปิดทีวี' in transcript: + turn_on_tv() + print('turning on TV') + time.sleep(2) + text_to_speech(u'อัลโต้ได้ทำการเปิดทีวีให้แล้วค่ะ คอยติดตามชมนะค่ะ ') + elif u'ปิดทีวี' in transcript: + turn_off_tv() + print('turning off TV') + time.sleep(2) + text_to_speech(u'อัลโต้ได้ทำการปิดทีวีให้แล้วค่ะ คอยติดตามชมนะค่ะ ') + elif u'ออก' in transcript: + print('Exiting..') + break + else: + print("text not matched transcript") + print(transcript) num_chars_printed = 0 - + except: + print("error in listen_print_loop") + +def turn_on_ac(): + # My API + # PUT https://graph.api.smartthings.com/api/smartapps/installations/a0304624-dc42-4d93-b84f-421ff52167ca/switches/9b86fd56-4de8-4b1d-b2de-98c3f5243e27 + print("sending turning on AC command") + try: + response = requests.put( + url="https://graph.api.smartthings.com/api/smartapps/installations/a0304624-dc42-4d93-b84f-421ff52167ca/switches/9b86fd56-4de8-4b1d-b2de-98c3f5243e27", + headers={ + "Authorization": "Bearer 9e450b2e-3acf-4494-8183-c01806684bd2", + "Content-Type": "application/json; charset=utf-8", + }, + data=json.dumps({ + "command": "on" + }) + ) + print('Response HTTP Status Code: {status_code}'.format( + status_code=response.status_code)) + print('Response HTTP Response Body: {content}'.format( + content=response.content)) + except requests.exceptions.RequestException: + print('HTTP Request failed') + +def turn_off_ac(): + # My API + # PUT https://graph.api.smartthings.com/api/smartapps/installations/a0304624-dc42-4d93-b84f-421ff52167ca/switches/9b86fd56-4de8-4b1d-b2de-98c3f5243e27 + print("sending turning off AC command") + try: + response = requests.put( + url="https://graph.api.smartthings.com/api/smartapps/installations/a0304624-dc42-4d93-b84f-421ff52167ca/switches/9b86fd56-4de8-4b1d-b2de-98c3f5243e27", + headers={ + "Authorization": "Bearer 9e450b2e-3acf-4494-8183-c01806684bd2", + "Content-Type": "application/json; charset=utf-8", + }, + data=json.dumps({ + "command": "off" + }) + ) + print('Response HTTP Status Code: {status_code}'.format( + status_code=response.status_code)) + print('Response HTTP Response Body: {content}'.format( + content=response.content)) + except requests.exceptions.RequestException: + print('HTTP Request failed') + +def turn_on_light(): + # front lifx + # PUT https://graph.api.smartthings.com/api/smartapps/installations/a0304624-dc42-4d93-b84f-421ff52167ca/switches/08e75403-af24-4dcf-b1d6-ce253008858a + print("sending turning on Light command") + try: + response = requests.put( + url="https://graph.api.smartthings.com/api/smartapps/installations/a0304624-dc42-4d93-b84f-421ff52167ca/switches/08e75403-af24-4dcf-b1d6-ce253008858a", + headers={ + "Authorization": "Bearer 9e450b2e-3acf-4494-8183-c01806684bd2", + "Content-Type": "application/json; charset=utf-8", + }, + data=json.dumps({ + "command": "on" + }) + ) + print('Response HTTP Status Code: {status_code}'.format( + status_code=response.status_code)) + print('Response HTTP Response Body: {content}'.format( + content=response.content)) + except requests.exceptions.RequestException: + print('HTTP Request failed') + +def turn_off_light(): + # front lifx + # PUT https://graph.api.smartthings.com/api/smartapps/installations/a0304624-dc42-4d93-b84f-421ff52167ca/switches/08e75403-af24-4dcf-b1d6-ce253008858a + print("sending turning off Light command") + try: + response = requests.put( + url="https://graph.api.smartthings.com/api/smartapps/installations/a0304624-dc42-4d93-b84f-421ff52167ca/switches/08e75403-af24-4dcf-b1d6-ce253008858a", + headers={ + "Authorization": "Bearer 9e450b2e-3acf-4494-8183-c01806684bd2", + "Content-Type": "application/json; charset=utf-8", + }, + data=json.dumps({ + "command": "off" + }) + ) + print('Response HTTP Status Code: {status_code}'.format( + status_code=response.status_code)) + print('Response HTTP Response Body: {content}'.format( + content=response.content)) + except requests.exceptions.RequestException: + print('HTTP Request failed') + +def turn_on_tv(): + # TV + # PUT https://graph.api.smartthings.com/api/smartapps/installations/a0304624-dc42-4d93-b84f-421ff52167ca/switches/b64f5e3a-d447-48f8-8d86-050de41cec7a + print("sending turning on TV command") + try: + response = requests.put( + url="https://graph.api.smartthings.com/api/smartapps/installations/a0304624-dc42-4d93-b84f-421ff52167ca/switches/b64f5e3a-d447-48f8-8d86-050de41cec7a", + headers={ + "Cookie": "JSESSIONID=FCCFD41E2393191D2AA158F251B09CDF-n2", + "Authorization": "Bearer 9e450b2e-3acf-4494-8183-c01806684bd2", + "Content-Type": "application/json; charset=utf-8", + }, + data=json.dumps({ + "command": "on" + }) + ) + print('Response HTTP Status Code: {status_code}'.format( + status_code=response.status_code)) + print('Response HTTP Response Body: {content}'.format( + content=response.content)) + except requests.exceptions.RequestException: + print('HTTP Request failed') + +def turn_off_tv(): + # TV + # PUT https://graph.api.smartthings.com/api/smartapps/installations/a0304624-dc42-4d93-b84f-421ff52167ca/switches/b64f5e3a-d447-48f8-8d86-050de41cec7a + print("sending turning off TV command") + try: + response = requests.put( + url="https://graph.api.smartthings.com/api/smartapps/installations/a0304624-dc42-4d93-b84f-421ff52167ca/switches/b64f5e3a-d447-48f8-8d86-050de41cec7a", + headers={ + "Cookie": "JSESSIONID=FCCFD41E2393191D2AA158F251B09CDF-n2", + "Authorization": "Bearer 9e450b2e-3acf-4494-8183-c01806684bd2", + "Content-Type": "application/json; charset=utf-8", + }, + data=json.dumps({ + "command": "off" + }) + ) + print('Response HTTP Status Code: {status_code}'.format( + status_code=response.status_code)) + print('Response HTTP Response Body: {content}'.format( + content=response.content)) + except requests.exceptions.RequestException: + print('HTTP Request failed') + +def text_to_speech(msg): + # Request (4) + # POST http://localhost:8888/test + + try: + response = requests.get( + url="http://localhost:8080/websocket", + # headers={ + # "Cookie": "_xsrf=2|944ae2e2|73e716843e1dd25abd7365e04aec06e7|1490541278", + # "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", + # }, + # data={ + # "message": msg, + # }, + ) + print('Response HTTP Status Code: {status_code}'.format( + status_code=response.status_code)) + print('Response HTTP Response Body: {content}'.format( + content=response.content)) + except requests.exceptions.RequestException: + print('HTTP Request failed') def main(): service = cloud_speech_pb2.SpeechStub( @@ -224,7 +538,6 @@ def main(): # Now, put the transcription responses to use. try: listen_print_loop(recognize_stream) - recognize_stream.cancel() except grpc.RpcError as e: code = e.code() @@ -232,6 +545,10 @@ def main(): if code is not code.CANCELLED: raise + # tornado.options.parse_command_line() + # app = Application() + # app.listen(options.port) + # tornado.ioloop.IOLoop.current().start() if __name__ == '__main__': main() diff --git a/speech/responsivevoic.html b/speech/responsivevoic.html new file mode 100644 index 00000000000..da7ea387d5b --- /dev/null +++ b/speech/responsivevoic.html @@ -0,0 +1,15 @@ + + + + + Title + + + + + + + + + + \ No newline at end of file diff --git a/speech/tornado b/speech/tornado new file mode 160000 index 00000000000..8ea13db107f --- /dev/null +++ b/speech/tornado @@ -0,0 +1 @@ +Subproject commit 8ea13db107f4d44fadd24578e693f2838012caa7 diff --git a/speech/tornadowebserver.py b/speech/tornadowebserver.py new file mode 100644 index 00000000000..3186aedb1cc --- /dev/null +++ b/speech/tornadowebserver.py @@ -0,0 +1,16 @@ +import tornado.ioloop +import tornado.web + +class MainHandler(tornado.web.RequestHandler): + def get(self): + self.write("Hello, world") + +def make_app(): + return tornado.web.Application([ + (r"/", MainHandler), + ]) + +if __name__ == "__main__": + app = make_app() + app.listen(8888) + tornado.ioloop.IOLoop.current().start() \ No newline at end of file