Skip to content

Commit

Permalink
add basic say/listen flow
Browse files Browse the repository at this point in the history
  • Loading branch information
wangchou committed Jun 17, 2019
1 parent 46b6625 commit 4c8b5fa
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 126 deletions.
117 changes: 0 additions & 117 deletions src/client/Messenger.svelte

This file was deleted.

23 changes: 23 additions & 0 deletions src/client/gameFlow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { PlaySpeed, Voices } from './model/constants.js'
import { say, listen } from './speechEngine.js'
import { comments } from './model/store.js'

const sentences = [
{ text: 'こんにちは、ともさん', speed: PlaySpeed.slow, voice: Voices.jaM1 },
{ text: '今日はいい天気ですね', speed: PlaySpeed.slow, voice: Voices.jaF1 },
{ text: 'そうですね。', speed: PlaySpeed.slow, voice: Voices.jaM1 },
{ text: 'じゃあ、またね。', speed: PlaySpeed.slow, voice: Voices.jaF1 },
]

export const playGame = async () => {
for (let i in sentences) {
let sentence = sentences[i]
comments.update(x => [...x, { author: 'teacher', text: sentence.text }])

let duration = await say(sentence.text, sentence.speed, sentence.voice)

// plus 600 ms
let recognizedText = await listen(duration + 600)
comments.update(x => [...x, { author: 'student', text: recognizedText }])
}
}
2 changes: 1 addition & 1 deletion src/client/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import App from './App.svelte'
import App from './ui/App.svelte'

const app = new App({
target: document.body,
Expand Down
12 changes: 12 additions & 0 deletions src/client/model/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export let PlaySpeed = {
normal: 1.0,
slow: 0.85,
verySlow: 0.7
}

export let Voices = {
jaF1: 'jaF1',
jaF2: 'jaF2',
jaM1: 'jaM1',
jaM2: 'jaM2',
}
3 changes: 3 additions & 0 deletions src/client/model/store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { writable } from 'svelte/store';

export const comments = writable([])
43 changes: 43 additions & 0 deletions src/client/speechEngine.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
var recognition = new webkitSpeechRecognition()
recognition.continuous = true
recognition.interimResults = false

export let listen = (duration) => {
recognition.start();
setTimeout(() => { recognition.stop() }, duration)


let promise = new Promise((resolve, reject) => {
recognition.onresult = (event) => {
for (var i = event.resultIndex; i < event.results.length; ++i) {
resolve(event.results[i][0].transcript)
}
}
recognition.onerror = () => {
resolve("error")
}
})
return promise
}

function getMS() {
return new Date().getTime()
}

export let say = async (text, speed, voice) => {
var startMS = getMS()
var response = await fetch(`/tts?text=${text}&voice=${voice}`)
.then(res =>
res.text()
)

const audio = new Audio('data:audio/wav;base64,' + response)
let promise = new Promise(function (resolve, reject) {
audio.onended = () => {
resolve(getMS() - startMS)
}
})
audio.play()
audio.playbackRate = speed
return promise
}
7 changes: 7 additions & 0 deletions src/client/App.svelte → src/client/ui/App.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script>
import Messenger from './Messenger.svelte'
import { playGame } from '../gameFlow.js'
</script>

<style>
Expand All @@ -12,6 +13,9 @@
margin: 4% 0;
background: #999;
}
div.playButton {
text-align: center;
}
</style>

<div>
Expand All @@ -25,3 +29,6 @@
</h1>
</div>
<Messenger />
<div class="playButton">
<button on:click={playGame}>Play</button>
</div>
65 changes: 65 additions & 0 deletions src/client/ui/Messenger.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<script>
import { comments } from './model/store.js'
import { beforeUpdate, afterUpdate } from 'svelte'
let div
let autoscroll
beforeUpdate(() => {
autoscroll = div && div.offsetHeight + div.scrollTop > div.scrollHeight - 20
})
afterUpdate(() => {
if (autoscroll) div.scrollTo(0, div.scrollHeight)
})
</script>
<style>
.chat {
display: flex;
flex-direction: column;
height: 400px;
max-width: 240px;
border: 1px solid #eee;
margin: 0px auto;
}
.scrollable {
flex: 1 1 auto;
margin: 0 0.5em;
overflow-y: auto;
}
article {
margin: 0.5em 0;
}
.student {
text-align: right;
}
span {
padding: 0.5em 1em;
display: inline-block;
}
.teacher span {
background-color: #eee;
border-radius: 1em 1em 1em 0;
}
.student span {
background-color: #0074d9;
color: white;
border-radius: 1em 1em 0 1em;
}
</style>

<div class="chat">
<div class="scrollable" bind:this={div}>
{#each $comments as comment}
<article class={comment.author}>
<span>{comment.text}</span>
</article>
{/each}
</div>
</div>
8 changes: 1 addition & 7 deletions src/server/tts.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import fetch from 'node-fetch'
import API_KEY from "../../../secret/api_key.js"

const PlaySpeed = {
normal: 1.0,
slow: 0.85,
verySlow: 0.7
}

const Voices = {
jaF1: { name: 'ja-JP-Wavenet-B', languageCode: 'ja-JP' },
jaF2: { name: 'ja-JP-Wavenet-A', languageCode: 'ja-JP' },
Expand All @@ -22,7 +16,7 @@ export default async (req, res) => {
voice: Voices[req.query.voice],
audioConfig: {
audioEncoding: 'OGG_OPUS',
speakingRate: PlaySpeed[req.query.speed],
speakingRate: 1.0,
},
})
const response = await fetch(GOOGLE_TEXT_TO_SPEECH_URL, {
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
"outDir": "./xyz",
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"allowJs": true
"allowJs": true,
},
}

0 comments on commit 4c8b5fa

Please sign in to comment.