LoginSignup
13
9

More than 3 years have passed since last update.

翻訳こんにゃくなんて1時間で作れる話

Posted at

はじめに

先日LTをする機会がありまして、この記事の題通り、翻訳こんにゃくを1時間で作れる話をしてきました。
主題としては、「1時間で作れること」がメインなのですが、技術的な部分をもう少し聞きたいという声がありましたので、ここにざっくりとまとめます。詳しくはリポジトリを眺めてください。

作ったものはこちら


コードに関してはこちらを→Githubリポジトリ

翻訳こんにゃくの仕様

翻訳こんにゃくといえば、ドラ○もんのひ○つ道具として有名です。それを食べることで、あらゆる言語を理解することができます。自分の知らない言語を話すことができ、聞き取って理解することができるという代物です。

ここでは、翻訳こんにゃくをWebアプリケーションとして実装します。
フローはこんな感じ。
名称未設定.001.jpeg

環境

クライアントサイドは、JQueryやReactは特に使わず、生のJSで記述します。
サーバサイドは、Node.js(v8.9.4)で記述します。

音声認識・音声合成にはWebSpeechAPIに含まれる、SpeechRecognitionとSpeechSynthesisを使います。
翻訳には、Microsoftが提供するTranslatorTextAPIを使います。
また、クライアントとサーバ間をWebSocketで通信します。

以降で、WebSpeechAPI、TranslatorTextAPI、WebSocket通信について、翻訳こんにゃくを1時間で作るのに十分な内容だけ説明します。

Web Speech API

Web Speech APIは、音声認識のSpeech Recognitionインタフェースと、音声合成のSpeech Synthesisインタフェースから構成されるAPIです。インターネット接続せずにローカルな環境で動作し、簡単な記述で音声認識と音声合成を試すことができます。1時間で翻訳こんにゃくを作る上では、最適です。

Speech Recognition

const recognition = new webkitSpeechRecognition;

recognition.lang='en-US';
recognition.start();

recognition.onresult = function(e){
  console.log(e.results[0][0].transcript);
}

SpeechRecognitionを試すだけなら、これだけで動きます。
インスタンスを生成して、認識する言語を設定し、start()を実行するだけです。
onresultイベントで認識結果を取得できます。

SpeechRecognitionでは、認識の途中結果や、連続で認識し続けるなども可能です。

const recognition = new webkitSpeechRecognition;
recognition.continuous = true; //連続認識
recognition.interimResults = true; //途中結果を吐き出す

詳細はこちらをどうぞ

Speech Synthesis

const synth = window.SpeechSynthesis;
const utterance = new SpeechSynthesisUtterance("Hello world");
synth.speak(utterance);

音声合成をするには、発話情報(SpeechSynthesisUtterance)をSpeechSynthesisspeak()に渡してやるだけでOKです。これだけで、ブラウザが"Hello world"と喋ってくれます。

SpeechSynthesisUtteranceをいじることで、声色や声の高さ、速さなどを調整できます。

const synth = window.SpeechSynthesis;
const voices = synth.getVoices();

let utterance = new SpeechSynthesisUtterance();
utterance.lang  = 'ja-JP';
utterance.text  = 'こんにちは';
utterance.pitch = 1.5; //高さ 0.0~2.0  default:1
utterance.rate  = 1.0; //速さ 0.1~10.0 default:1
utterance.voice = voices[0]; //声色 

声色はたくさんあります。2019/06/19時点で66種類。
スクリーンショット 2019-06-19 17.57.11.png

Translator Text API

MicrosoftのAPIを選択した理由は特になく。Web Speech APIのように、インターネット接続せずにローカルで動き、簡単な記述で済むものがあればよかったのですが、特に見つからない(というより、探してない)ので、使った次第です。

このAPIはPOSTしたテキストの言語を自動で推定して、指定した言語に翻訳してくれます。
POSTで送るものは、翻訳先の言語と翻訳したい元のテキストです。

基本、こちらの公式ドキュメントをなぞるだけで、十分です。

Node.js
const request = require('request');
const uuidv4 = require('uuid/v4');
function translate(_text){
  return new Promise((resolve, reject)=>{
    const subscriptionKey = 'xxxxxxxxxxxxxxxxxxxxxxxx';
    let options = {
      method: 'POST',
      baseUrl: 'https://api.cognitive.microsofttranslator.com/',
      url: 'translate',
      qs: {
        'api-version': '3.0',
        'to': 'ja' // ここで翻訳先の言語を指定
      },
      headers: {
        'Ocp-Apim-Subscription-Key': subscriptionKey,
        'Content-type': 'application/json',
        'X-ClientTraceId': uuidv4().toString()
      },
      body: [{
        'text': _text // 翻訳したいテキスト。今回で言えば、音声認識したテキスト。
      }],
      json: true,
    };

    request(options, function(err, res, body){
      if(err) {
        console.log(err);
        return
      }
      let json = JSON.stringify(body, null, 4);
      let data = JSON.parse(json);
      resolve(data[0]["translations"][0]["text"]);

    });
  })
}

WebSocket

今回作ったシステムでは、クライアントとサーバ間をWebSocketで通信しているので、その話もついでにしましょう。

WebSocketはウェブアプリケーションにおいて、クライアントとサーバの低コストに双方向通信を簡単に実現するための通信規格です。チャットでクライアントとサーバの間を何度も通信するときに使ったりします。今回は、音声認識するたびにサーバに送って、翻訳したテキストをクライアントに返すという通信をしたいので、WebSocketを使おうということです。

Node.jsではsocket.ioというライブラリを使うことで、Webアプリケーションに簡単にWebSocketを組み込むことができます。npmやyarnを使ってsocket.ioをインストールしましょう。

socket.io

socket.ioはイベントベースでWebSocket通信を可能にするライブラリです。クライアントとNode.jsサーバ用の機能を含んでいます。

<!-- クライアント側 -->
<script>
//これだけでサーバにWebSocketで接続できます。
const socket = io(); 

// 'from-client'というイベント名で'Hello'というメッセージを送ります。
socket.emit('from-client', 'Hello'); 

// 'from-server'というイベント名でメッセージが来たら、それをconsole出力します。
socket.on('from-server', msg=>{console.log(msg)}); 
</script>
Node.js
//サーバ構築にはexpressを使います。
const app = require('express')();
const http = require('http').Server(app);
const server = http.listen(3000, ()=>{});

const io = require('socket.io')(http);

// 接続時の処理
io.on('connection', socket => {
  // 'from-client'というイベント名で、clientからメッセージを受信
  socket.on('from-client', msg => {
    // 'from-server'というイベント名で、clientにメッセージを送信
    io.emit('server:message', msg);
  });
});

1時間で作る話

この辺の基本的な技術を組み合わせてしまえば、翻訳こんにゃく(みたいなもの)を作れてしまいます。
何も難しいものは使っていません。APIとか組み合わせれば、作れるものは無限大だぜ
という話をLTでしました。新しい技術はどんどん触って、技術の引き出しを増やしていきたいですね。

13
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
9