1. 概要
Google Chromeの Web Speech API を利用して音声認識し、結果を Discordのテキストチャンネルに書き込みをする方法を紹介します。
やっていることは、NAMAROIDの音声認識をChromeでやってみたとほぼ同様ですが、本記事では実装面を解説します。
本実装は Webサーバを介した、クライアント・サーバ形式で、相互のメッセージングに socket.ioを利用しています。
socket.ioを利用することにより、Web APIに比べて実装が簡単で、送受信の高速化が期待できます。
アイコンはおむ烈 様のフリーアイコンをお借りしております!
参考記事
- Discord Bot の登録方法
Discord Botアカウント初期設定ガイド for Developer
動作環境
- OS: Windows 10
- node: v9.11.1
- chrome: 78.X
ソースコード
https://bitbucket.org/YoshikazuOota/post_stt
2. 使い方
2.1 ライブラリのインストール
初回のみ npm install
(setting.bat) を実行して
2.2 Discord Bot・テキストチャンネルの設定
config/discord.json
で下記の2つを指定する
- Botのトークン
- 書き込み先のテキストチャンネル
2.3 サーバサイドの実行
node server.js
実行(start.bat) を実行- ブラウザで http://localhost:4000を開く
2.4 ブラウザ操作
- 『音声認識開始』ボタンをクリックして、音声認識かいし
- 『停止』ボタンで音声認識を終了
補足
音声入力がうまく出来ていないときは、マイクの使用許可設定が適切か確認してください。
3. 実装の解説
3.A クライアントサイド(index.html)
Chrome で音声認識して、サーバにテキストを送る
'server.js' を起動すると、http://localhost:4000
で 'index.html' にアクセスすることができます。
この index.html
がクライアントサイドになります。
音声認識のメイン処理は speech_recognition.js
で行われます。
<!DOCTYPE html><htmllang="ja"><head><metacharset="UTF-8"><title>音声認識 Discordブリッジ</title><linkrel="stylesheet"href="assets/bootstrap/css/bootstrap.min.css"><linkrel="stylesheet"href="assets/bootstrap/css/bootstrap-grid.min.css"><linkrel="stylesheet"href="assets/bootstrap/css/bootstrap-reboot.min.css"><script src="assets/lib_js/jquery-3.3.1.min.js"></script><script src="assets/bootstrap/js/bootstrap.js"></script><script src="/socket.io/socket.io.js"></script><!-- socket.io を読み込み --><script src="assets/js/speech_recognition.js"></script><!-- メインロジック --><style>.row{margin-top:20px;}</style></head><body><divclass="container"><divclass="row"><divclass="col-sm-12"><h3>Chromeで音声認識して、Discordに書き込み</h3></div></div><divclass="row"><divclass="col-sm-5"><buttonclass="btn btn-primary"id="start_btn">音声認識開始</button><!-- 音声認識開始ボタン --><buttonclass="btn btn-secondary"id="end_btn">停止</button><!-- 音声認識停止ボタン --></div><divclass="col-sm-7 d-flex align-items-center"><strong><spanid="status"style="font-size: 24px"></span></strong><!-- 音声認識 ON/OFF 表示 --></div></div><divclass="row"><divclass="col-sm-12"><divclass="card-text"><spanid="prosess"></span><!-- 音声認識イベント表示 --></div></div></div><divclass="row"><divclass="col-sm-12"><divclass="card"><divclass="card-body"><divclass="card-text"id="content"></div><!-- 認識したテキスト表示 --></div></div></div></div></div></body></html>
constsocket=io.connect();// ソケットioconstspeech=newwebkitSpeechRecognition();// 音声認識APIの使用speech.lang="ja";// 言語を日本語に設定letkeep_standby=false;functionupdate_prosess(text){$("#prosess").text(text);}// 音声認識 スタンバイ/停止 表示functionupdate_status(text){$("#status").html(text);}// 音声認識 イベント 表示// 音声認識した文字表示functionupdate_result_text(text){update_prosess('[結果表示]');$("#content").text(text);console.log(text);}// 音声認識の結果取得時の処理speech.onresult=result=>{consttext=result.results[0][0].transcript;update_result_text(text);socket.emit('get_word',{word:text});// 認識文字を socket.io 経由でサーバに送信する};// 音声認識の継続継続処理speech.onend=()=>{if(keep_standby)speech.start();elsespeech.stop();};speech.onspeechstart=()=>update_prosess('[音声取得開始]');speech.onspeechend=()=>update_prosess('[解析開始]');$(function(){$("#start_btn").on('click',()=>{update_status('<span class="text-success">『音声認識スタンバイ』</span>');keep_standby=true;speech.start();});$("#end_btn").on('click',()=>{update_status('<span class="text-danger">『停止中』</span>');update_prosess('[音声認識停止中]');keep_standby=false;speech.stop();});$("#end_btn").trigger('click');// 初期$("#start_btn").trigger('click');// 自動スタート});
音声認識の処理フロー
1. index.html: socket.io
, speech_recognition.js
を読み込み/socket.io/socket.io.js
の実態ファイルがソースコード一式にないため、不思議な感じですが、このファイルは server.js
で socket.io
の設定をすると勝手に用意してくれます。
<scriptsrc="/socket.io/socket.io.js"></script> <!-- socket.io を読み込み -->
<scriptsrc="assets/js/speech_recognition.js"></script> <!-- メインロジック -->
2. speech_recognition.js: socket.io オブジェクト取得
サーバ側(server.js)へのテキスト送信はこのオブジェクトを介して行います。
constsocket=io.connect();// ソケットio
3. speech_recognition.js: "音声認識APIの使用"
音声認識のオブジェクト(speech)を取得します。
音声認識に関わる処理はこちらを介して行います。
その際、speech.lang = "ja"
をお忘れなく。
constspeech=newwebkitSpeechRecognition();// 音声認識APIの使用speech.lang="ja";
4. speech_recognition.js: $("#start_btn").on
index.html で表示している、『音声認識開始』ボタンをクリックした時のイベント。
ここの speech.start();
で音声認識が開始されます。
以降、音声認識処理が完了すると speech.onresult
で、音声認識した文字列を取得出来ます。
$("#start_btn").on('click',()=>{update_status('<span class="text-success">『音声認識スタンバイ』</span>');keep_standby=true;speech.start();});
5. speech_recognition.js: speech.onresult
でサーバ(server.js)への文字送信
音声認識した文字列は result.results[0][0].transcript;
に格納されています。大抵このまま決め打ちでいいようです。
細かい仕様は https://wicg.github.io/speech-api/#speechreco-resultを参照してください。
6. speech_recognition.js: speech.onend
で音声認識を継続
7 の処理を継続するための処理です。
5 keep_standby = true
として、このフラグがtrue
であれば、speech.start()
をコールして継続処理をします。
B. サーバーサイド(server.js)
音声認識文字を受け取り、Discord の テキストチャンネル書き込む
server.js
では クライアント側のspeech_recognition.js
の socket.emit
で送信される文字を取得して、Discord のテキストチャンネルに書き込みをします。
constPORT=4000;constexpress=require('express');constos=require('os');constapp=express();app.use(express.static(__dirname));constserver=require('http').createServer(app).listen(PORT);constio=require('socket.io').listen(server);// ログイン処理constconfig=require("./config/discord");constDiscord=require('discord.js');constclient=newDiscord.Client();consttoken=config.token;client.on('ready',()=>{console.log('start server');console.log(`open chrome: http://localhost:${PORT}`);consttargetTextChannel=client.channels.find(val=>val.id===config.channel_id);// 指定テキストチャンネルを取得io.sockets.on('connection',function(socket){socket.on('get_word',function(data){if(data===undefined||data===""||data===null)return;console.log(data);targetTextChannel.send(data.word);});});});client.login(token);
音声認識の文字取得・テキストチャンネル書き込み処理フロー
- Web expressを利用して index.html 用の Webサーバを立ち上げ、Webサーバに socket.ioを追加する。
constapp=express();app.use(express.static(__dirname));constserver=require('http').createServer(app).listen(PORT);constio=require('socket.io').listen(server);
- Discord Botの設定
discord.js
を利用して Botを起動させる。client.login(token)
で Botが起動して、起動完了後client.on('ready', () => {})
がコールされます。
constconfig=require("./config/discord");constDiscord=require('discord.js');constclient=newDiscord.Client();consttoken=config.token;...client.login(token);
- 指定のテキストチャンネルを取得
config.channel_id
に一致する channelを取得します。find(val => val.name === 'チャンネル名')
とすると、チャンネル名でチャンネルを取得できます。
consttargetTextChannel=client.channels.find(val=>val.id===config.channel_id);// 指定テキストチャンネルを取得
socket.io の接続待ち
index.html側で socket.ioに接続するのを待ち、接続があった場合はio.sockets.on('connection', () => {})
が実行されます。
この処理は index.htmlを開いたページ毎にコールされ、音声入力する index.htmlは複数でも対応可能です。取得文字をテキストチャンネルにポスト
index.html側でget_word
イベントを発火すると、下記のget_word
がコールされます。data.word
に音声認識した文字列が格納されているので、それを送信するだけで、テキストチャンネルに書き込みをします。
socket.on('get_word',function(data){if(data===undefined||data===""||data===null)return;console.log(data);targetTextChannel.send(data.word);});
最後に
google chromeの音声認識は無料で、APIなどを発行する必要もないので、個人利用するのであればすごく便利ですね。
google Cloud の STT(Speech-to-Text)も低料金で利用できるのですが、音声処理周りの実装やAPI利用のための設定が大変ですですので、Chromeの Web Speechが一番楽です。
音声入力は未来感があって、筆者はとてもワクワクするインターフェイスだと思っています!