yamaken1343’s blog

技術ブログもどき

JavaScript で Google Cloud Speech-to-Text 音声認識

cloud.google.com

JavaScriptの練習がてらこれをブラウザ上で動作させます.
ページ内にサンプルがあると思いますが, あれの簡単なやつです.

もっとも, REST APIで公開されているのでそんなに難しくないです.
もうひとつgRPC形式のAPIが公開されてますが, 勉強中なので誰か教えてください.

準備

  • Google Cloud Platform にアカウントが必要なので取得
  • Cloud Speech APIを有効にしてAPIキーを発行

設計

  1. 音声取得
  2. base64エンコード
  3. JSON形式にしてAPIを叩く

実装

github.com

音声周りは素晴らしいライブラリがあるので利用します.
(最初は自分で書いてたけど挫折しました)

こちらの録音を吐き出す部分に上のエンコードAPI叩く部分を実装してあげれば良いです.

  • main.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>デモ用音声認識サンプル</title>
</head>
<body>
<button onclick="startRecording()">解析開始</button>
<button onclick="endRecording()">解析終了</button>
<hr>
<script src="api_key.js"></script>
<script src="./lib/recorder.js"></script>
<script src='main.js'></script>
</body>
</html>
  • main.js
let audio_context;
let recorder;

function arrayBufferToBase64(buffer) {
    let binary = '';
    let bytes = new Float32Array(buffer);
    let len = bytes.byteLength;
    for (let i = 0; i < len; i++) {
        binary += String.fromCharCode(bytes[i]);
    }
    return window.btoa(binary);
}

function startUserMedia(stream) {
    let input = audio_context.createMediaStreamSource(stream);

    recorder = new Recorder(input);
}


let startRecording = function () {
    audio_context.resume()
    recorder && recorder.record();
    console.log("record start")
};

let endRecording = function () {
    recorder && recorder.stop();
    console.log("record stop");

    // create WAV download link using audio data blob
    audioRecognize();

    recorder.clear();
};

function audioRecognize() {
    recorder && recorder.exportWAV(function (blob) {
        let reader = new FileReader();
        reader.onload = function () {
            let result = new Uint8Array(reader.result); // reader.result is ArrayBuffer
            let data = {
                "config": {
                    "encoding": "LINEAR16",
                    "sampleRateHertz": 44100, // 環境によってかわるっぽいので変えてください(おそらくエラーに正しい値が出てくると思います.
                    "languageCode": "ja-JP"
                },
                "audio": {
                    "content": arrayBufferToBase64(result)
                }
            };
            console.log("audio send...");
            fetch('https://speech.googleapis.com/v1/speech:recognize?key=' + apiKey, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json; charset=utf-8'
                },
                body: JSON.stringify(data)
            }).then(function (response) {
                return response.text();
            }).then(function (text) {
                let result_json = JSON.parse(text);
                //テキストデータ自体はresult_json.results[0].alternatives[0].transcriptに格納
                console.log("RESULT: " + text);
                console.log(result_json.results[0].alternatives[0].transcript);
                console.log(data)
            });
        };
        reader.readAsArrayBuffer(blob)

    });
}

window.onload = function init() {
    try {
        // webkit shim
        window.AudioContext = window.AudioContext || window.webkitAudioContext;
        navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
        window.URL = window.URL || window.webkitURL;

        audio_context = new AudioContext;
    } catch (e) {
        alert('No web audio support in this browser!');
    }

    navigator.getUserMedia({audio: true}, startUserMedia, function (e) {
    });
};

同階層にAPIキーを保持するファイルapi_key.jsとして作成してください

var apiKey = 'XXXXXXXXXXXXX';

成果物は以下 github.com

結果

f:id:yamaken1343:20181020193213p:plain

あとがき

JavaScriptわからん
結局ほとんどコード書いてないので勉強になったか微妙

注意点

APIキーが見え見えなので動作はローカルにとどめておいてください.

追記

2019/4/9 Google Chrome の自動再生ポリシーの変更に対応
動作しない場合コメントをください.