Skip to content

Instantly share code, notes, and snippets.

@cimadai
Created January 31, 2016 06:17
Show Gist options
  • Save cimadai/7cd295f194f4ff231a8e to your computer and use it in GitHub Desktop.
Save cimadai/7cd295f194f4ff231a8e to your computer and use it in GitHub Desktop.
talktrans - client side
extends layout
block content
div(class="container-fluid")
div(class="row")
div(class="col-xs-12")
form
div(class="form-group")
label(for="input_text" class="step-message") Step1. 言語を選択
div(style="text-align:center;")
input(type="checkbox" id="lang_select" checked data-toggle="toggle" data-on="日本語から英語" data-off="English to Japanese" data-width="250px" data-onstyle="primary" data-offstyle="success")
div(class="form-group")
label(for="input_text" class="step-message") Step2. ボタンを押して話す
div(style="text-align:center;")
span(id="record" class="speech-button-wrapper")
img(src="/images/language.png" width="100px")
hr
div(class="form-group")
label(for="input_text" class="step-message") 音声認識した言葉
textarea(type="text" id="input_text" class="form-control" placeholder="Input or speak")
div(class="form-group")
label(for="result_text" class="step-message") 翻訳した言葉
textarea(type="text" id="result_text" class="form-control" placeholder="Translated message")
footer(class="footer")
div(class="container-fluid")
b talktrans 
span © 2016 cimadai. MIT License.
;$(function () {
"use strict";
var $inputTextArea = $("#input_text");
var $resultTextArea = $("#result_text");
var $langSelect = $("#lang_select");
var $record = $("#record");
var speech = new SpeechSynthesisUtterance();
window.SpeechRecognition = window.SpeechRecognition || webkitSpeechRecognition;
var recognition = new window.SpeechRecognition();
recognition.continuous = true;
var langMap = {ja: "ja-JP", en: "en-US"};
function translateLangToSpeechLang(translateLang) {
return langMap[translateLang] || "ja-JP";
}
var isTranslating = false;
function translateAndSpeech(text) {
if (!isTranslating) {
isTranslating = true;
$.ajax({
type: "GET",
url: "/translate",
dataType: "json",
data: {
text: text
},
success: function (ret) {
isTranslating = false;
$resultTextArea.val(ret.translated);
speechMessage(ret.translated, translateLangToSpeechLang(ret.to));
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
isTranslating = false;
$resultTextArea.val(textStatus);
}
});
}
}
$inputTextArea.on("change", function () {
var text = $inputTextArea.val();
if (text.length > 0) {
translateAndSpeech(text);
}
});
function speechMessage(text, lang) {
speech.text = text;
speech.lang = lang;
speechSynthesis.speak(speech);
}
var isRecording = false;
recognition.addEventListener('start', function(event) {
isRecording = true;
$record.addClass("on-record");
}, false);
//recognition.addEventListener('speechstart', function(event) {
//}, false);
recognition.addEventListener('end', function(event) {
isRecording = false;
$record.removeClass("on-record");
}, false);
// 録音終了時トリガー
recognition.addEventListener('result', function(event) {
var text = event.results.item(0).item(0).transcript;
translateAndSpeech(text);
$inputTextArea.val(text);
recognition.stop();
}, false);
function getRecordingLang() {
if ($langSelect.prop("checked")) {
return "ja-JP";
} else {
return "en-US";
}
}
$record.on("click", function (ev) {
ev.preventDefault();
if (isRecording) {
recordStop();
} else {
recordStart(getRecordingLang());
}
return false;
});
function recordStart(lang) {
recognition.lang = lang;
recognition.start();
}
function recordStop() {
recognition.stop();
}
});
doctype html
html
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1")
title= title
link(rel="shortcut icon" href="/images/favicon.png")
link(rel="stylesheet", href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css")
link(rel="stylesheet", href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css")
link(rel="stylesheet", href="https://gitcdn.github.io/bootstrap-toggle/2.2.0/css/bootstrap-toggle.min.css")
link(rel="stylesheet", href="/stylesheets/style.css")
script(src="https://code.jquery.com/jquery-2.1.4.min.js")
script(src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js")
script(src="https://gitcdn.github.io/bootstrap-toggle/2.2.0/js/bootstrap-toggle.min.js")
script(src="/javascripts/translate.js")
body
nav(class="navbar navbar-default navbar-fixed-top")
div(class="container")
div(class="navbar-header")
a(class="navbar-brand" href="#")
span talktrans
block content
body {
padding-top: 1em;
background-color: white;
}
.speech-button-wrapper {
/*border: 1px solid darkgrey;*/
display: inline-block;"
}
.step-message {
color: #777;
}
body > .container-fluid {
padding-top: 60px;
}
.navbar {
height: 32px !important;
min-height: 32px !important;
}
.navbar-brand {
background: url("/images/favicon.png") no-repeat left center;
background-size: contain;
height: 32px;
padding-top: 0;
}
.navbar-brand span {
padding-left: 32px;
line-height: 32px;
height: 32px;
display: inline-block;
}
#record {
cursor: pointer;
}
.on-record {
background: linear-gradient(3deg, #ffffff, #7eaeff);
background-size: 400% 400%;
-webkit-animation: recording 1s ease infinite;
-moz-animation: recording 1s ease infinite;
animation: recording 1s ease infinite;
}
@-webkit-keyframes recording {
0%{background-position:50% 0%}
50%{background-position:50% 100%}
100%{background-position:50% 0%}
}
@-moz-keyframes recording {
0%{background-position:50% 0%}
50%{background-position:50% 100%}
100%{background-position:50% 0%}
}
@keyframes recording {
0%{background-position:50% 0%}
50%{background-position:50% 100%}
100%{background-position:50% 0%}
}
/* Sticky footer styles
-------------------------------------------------- */
html {
position: relative;
min-height: 100%;
}
body {
/* Margin bottom by footer height */
margin-bottom: 30px;
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
/* Set the fixed height of the footer here */
height: 30px;
background-color: #f5f5f5;
vertical-align: bottom;
}
.footer div {
height: 30px;
line-height: 30px;
}
/* Custom page CSS
-------------------------------------------------- */
/* Not required for template or sticky footer method. */
body > .container {
padding: 30px 15px 0;
}
.container .text-muted {
margin: 20px 0;
}
.footer > .container {
padding-right: 15px;
padding-left: 15px;
}
code {
font-size: 80%;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment