![[Tutorial][Electron] Electronで文章を話すアプリを作ってみよう #3 Web Speech APIを使った音声機能実装編](https://casualdevelopers.com/wp-content/uploads/2017/10/electronlogo-700x300.png)
コーヒー豆が尽きた時にインスタントにするのですが味気ない。。。自分はそんなにコーヒーの味にうるさい方では無いのですが、ドリップしたての香りがたまらないのです。買いに行こうかな。新しいものを買うことは常にメリットがあります。選択できるからです。今まで使っていた商品か新しい商品かを選択できるチャンスです。そして、大抵新しい商品を買って後悔します。コーヒーの場合はね(笑)
前回は「文章を話すデスクトップアプリ」の基本機能まで作りました。今回はメイン機能である音声機能を作りましょう。音声機能の実装には、Chromeに搭載されているWeb Speech APIを利用します。使ったことがある人なら余裕でElectronとインテグレーションできます。
見出し
前回のおさらい
- 一流たるもの我慢強くなければならない
- Electronのウィンドウ間のデータ通信方式にはIPCシステムが使われている
- Electronアプリ作成はやってみると結構簡単。てか、楽しい
1. Web Speech APIとは?
Web Speech APIとは、音声合成(Text-to-Speech)と音声認識(Asynchronous Speech Recognition)から成る音声機能APIです。各ブラウザで実験的に実装が開始されており、ChromiumからできているElectronでもこの実験的な機能を利用することができます。今回はこのAPIの音声合成機能を使っていきます。(ちなみに、音声認識機能に関しては使うまでに少しハードルがあります。使うには、現時点でchromium-devグループへの参加とGoogle API Keyの取得が求められ、かつ、50回/日の制限付きです。ですが、この機能も面白いので試してみたい方は調べてみて下さい。ハードルをクリアした上でElectronで実行する場合は、「GOOGLE_API_KEY=XXXX npm run electron」のように渡してあげれば良いです。)
その他に、GoogleはGoogle Cloud Speech APIという有料のクラウドサービスを開始しています。無料なオープン展開を基本としているGoogleにしては残念なサービスですが、サポートもあるのでお金がある人にとってはいいかもしれません。
2. 音声機能を追加しよう!
それでは作っていきましょう。
2-1. 今回追加する機能の確認
まずは今回追加する機能を確認します。前回のUIイメージを思い出してください。残っている機能は?
そうです!Speakボタンが残っていました。このボタンをクリックした時に文章を読み上げてほしいのです。さらに、文章読み上げ中に中断できるように同じボタンをクリックすると音声が停止する機能も一緒に作りましょう。
2-2. Speak機能のコーディング
一応前回のフォルダ構成を見てみましょう。
$ cd speak-sentences
$ ls
index.html index.js input.html node_modules/ package-lock.json package.json
今回編集するのはindex.htmlだけです。
body部分に追加
<button id="speak-sentences">Speak/Stop</button>
scripts部分に追加
const speak = document.getElementById('speak-sentences');
// Speak sentences through SpeechSynthesis in Web Speech API.
const synth = window.speechSynthesis;
speak.addEventListener('click', (event) => {
// Stop.
if (synth.speaking) {
synth.cancel();
return;
}
// Speak.
const sentences = Array.from(document.querySelectorAll('#sentences p'))
.map((sentence) => {
return sentence.firstChild.nodeValue;
});
sentences.forEach((sentence) => {
const message = new SpeechSynthesisUtterance(sentence);
message.lang = 'ja-JP';
synth.speak(message);
});
});
2-3. 全体のソースコード
全体のコードは以下のようになります。
index.js
const electron = require("electron");
const { app, BrowserWindow, ipcMain } = electron;
let mainWindow;
let inputWindow;
app.on("ready", () => {
mainWindow = new BrowserWindow({
width: 500,
height: 500
});
mainWindow.loadURL(`file://${__dirname}/index.html`);
mainWindow.on("closed", () => app.quit());
});
function createInputWindow() {
inputWindow = new BrowserWindow({
width: 300,
height: 300
});
inputWindow.loadURL(`file://${__dirname}/input.html`);
inputWindow.on("closed", () => (inputWindow = null));
}
// Create a input window.
ipcMain.on("inputWindow:create", event => {
createInputWindow();
});
// Send a sentence to a main window.
ipcMain.on("sentence:insert", (event, sentence) => {
mainWindow.webContents.send("sentence:insert", sentence);
inputWindow.close();
});
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Speak Sentences</title>
</head>
<body>
<h1>Speak Sentences</h1>
<button id="input-sentence">Input</button>
<button id="clear-sentences">Clear</button>
<button id="speak-sentences">Speak/Stop</button>
<div id="sentences"></div>
<script>
const electron = require('electron');
const { ipcRenderer } = electron;
const sentences = document.getElementById('sentences');
const insert = document.getElementById('input-sentence');
const clear = document.getElementById('clear-sentences');
const speak = document.getElementById('speak-sentences');
// Request a input window.
insert.addEventListener('click', (event) => {
ipcRenderer.send('inputWindow:create');
});
// Clear sentences.
clear.addEventListener('click', (event) => {
sentences.innerHTML = '';
});
// Insert sentence.
ipcRenderer.on('sentence:insert', (event, sentence) => {
if (sentence.trim() === '') {
return;
}
const text = document.createTextNode(sentence);
const p = document.createElement('p');
p.appendChild(text);
sentences.appendChild(p);
});
// Speak sentences through SpeechSynthesis in Web Speech API.
const synth = window.speechSynthesis;
speak.addEventListener('click', (event) => {
// Stop.
if (synth.speaking) {
synth.cancel();
return;
}
// Speak.
const sentences = Array.from(document.querySelectorAll('#sentences p'))
.map((sentence) => {
return sentence.firstChild.nodeValue;
});
sentences.forEach((sentence) => {
const message = new SpeechSynthesisUtterance(sentence);
message.lang = 'ja-JP';
synth.speak(message);
});
});
</script>
</body>
</html>
input.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Input Text</title>
</head>
<body>
<form>
<div>
<label>Text: </label>
<input autofocus />
</div>
<button type="submit">Enter</button>
</form>
<script>
const electron = require('electron');
const { ipcRenderer } = electron;
// Insert text.
document.querySelector('form').addEventListener('submit', (event) => {
event.preventDefault();
const { value } = document.querySelector('input');
ipcRenderer.send('sentence:insert', value);
});
</script>
</body>
</html>
3. 動かしてみましょう!
最後に実行して動作確認をしてみましょう。
$ npm run electron
以下の画面が表示され、Speakボタンで文章を読み上げてくれれば、成功です!
なかなか日本語の発音が良いですよね(笑)
最後に
今回で一通りの機能実装は完了しました。これで終わり?とんでもない。それに、味気ない。次回からは周辺の小さい機能を追加していきます。ヒントはメニューバーです(笑)それでは。
環境
- OS: macOS Sierra 10.12.6
- NodeJS: v8.4.0
- NPM: 5.4.0
- Electron: 1.7.6


コメントを残す