ほんじゃらねっと

ダイエット中プログラマのブログ

Web Speech Synthesis APIを使って、正月のかるた読み上げ無間地獄タスクを自動化する

f:id:piro_suke:20170104012805j:plain

正月休み、帰省した実家で娘たちがかるた遊びにハマり、

ほぼ毎日祖母やいとこと遊んでいた。

楽しそうだし、瞬発力やら記憶力やらが鍛えられそうで大変良い。

大変良いのだけど、

かるた遊びの困ったところは、プレイヤー以外に読み手が必要だというところで、

その際はだいたい近くでダラダラしている人間(私)が呼ばれて参加させられる。

最初はこちらも娘達に相手をしてもらえるのが嬉しいので喜んで参加するのだけど、

毎回同じ内容を読み上げるので、何回かやっているとげんなりしてくる。

しかしダラダラしている手前、断るのも難しい。

そこで、「繰り返し作業は自動化や!」と

「テキスト読み上げ」でググったら出てきたWeb Speech Synthesis API を使って、

かるた自動読み上げツールを作ってみた。

Web Speech API とは

Web Speech API はブラウザで音声合成(音声読み上げ。Synthesis)や

音声認識(Recognition)を行うためのAPIらしい。

Web Speech API Specification

ChromeやSafariが標準対応しているようなので、Chromeで試した。

作成したもの

こちらが作成したツール。

See the Pen Karuta Reader by Pirosuke (@pirosuke) on CodePen.

「最初から」または「スタート」をクリックすると、

あらかじめ指定したテキストリストを5秒間隔で順に読み上げていく。

「ストップ」をクリックすると一時停止し、また「スタート」をクリックすると再開する。

ソース

HTML:

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>かるたリーダー</title>

  </head>

  <body>

    <h1>かるたリーダー</h1>

    <div>
      <button id="restart-btn">最初から</button>
      <button id="start-btn">スタート</button>
      <button id="stop-btn">ストップ</button>
    </div>

    <script src="js/bower_components/jquery/dist/jquery.min.js"></script>
    <script src="js/main.js"></script>
  </body>
</html>

Javascript:

$(function() {
    var ssu = new SpeechSynthesisUtterance();
    ssu.lang = 'ja-JP';                                                                                                                                                                

    var karutaList = [
        "へびさん、へるめっとが、よくにあう",
        "いぬさん、いちごをみつけたよ、いいな",
        "さるさんが、さつまいもくわえて、さかだちしたよ",
        "こあらのあかちゃん、おかあさんのせなかで、こっくりこっくり"
        // ...
    ];

    var count = 0;
    var threadId = null;

    var shuffle = function (arr) {
        for (var i = arr.length - 1; i > 0; i--) {
            var r = Math.floor(Math.random() * (i * 1));
            var tmp = arr[i];
            arr[i] = arr[r];
            arr[r] = tmp;
        }
    };

    var startReading = function () {
        threadId = setInterval(function () {
            ssu.text = karutaList[count];
            speechSynthesis.speak(ssu);
            if (count >= karutaList.length - 1) {
                clearInterval(threadId);
            }
            count++;
        }, 5000);
    };

    shuffle(karutaList);

    $('#restart-btn').on('click', function () {
        count = 0;
        startReading();
    });

    $('#start-btn').on('click', function () {
        startReading();
    });

    $('#stop-btn').on('click', function () {
        clearInterval(threadId);
    });
});

処理内容としては、

karutaListという配列に読み上げたいテキスト

(今回の場合はかるたの読み上げ用テキスト)を入れておき、

それをshuffle関数でシャッフルしておく。

シャッフル用関数は

こちらのFisher–Yatesアルゴリズムを用いる方法を使わせていただいた。

qiita.com

「最初から」「スタート」ボタンのいずれかがクリックされると、

startReading関数で5秒間隔でリスト内容を順に読み上げていく。

かるたの種類が変わったら、karutaListの内容を変更すればOK。

おわり

出来上がったツールを使ってみると、

やや不自然なイントネーションながら、ちゃんと読み上げてくれる。

かるた遊びには支障なく、なかなか満足のいく結果だった。

残念な点としては、5秒間隔で読み上げるために使用している

setIntervalがスマホのブラウザではうまく動作しないようで、

PCがないと使えないのが不便なところ。

また来年の正月休みに改良したい。

今回は使わなかった音声認識APIをつかって、

ボタンクリックではなく音声で操作できるようにするのも面白そうだ。

ただ、読み上げの機械的な音声を流していると、

奥さんに

「お前そこはちゃんとお前が読んで子供の相手しろや」

みたいな目で見られるので、

がんばる方向を間違えているかもしれない。

いもとようこあいうえおかるた ([かるた])

いもとようこあいうえおかるた ([かるた])