LoginSignup
3
2

More than 3 years have passed since last update.

青空文庫スピーカー

Last updated at Posted at 2020-06-14

たぶんこれは誰も使わないと思いますが、 青空文庫 の作品を音声合成で読み上げるブックマークレットを作りました。

javascript: (() => { var VOICE_INDEX = 0, RATE = 5.0, VOLUME = 1.0, MIN_WAITING_TIME = 250; var ssu = new SpeechSynthesisUtterance(); ssu.lang = 'ja-JP'; ssu.rate = RATE; ssu.volume = VOLUME; var main = () => { var voices = speechSynthesis.getVoices().filter((voice) => voice.lang === 'ja-JP'); ssu.voice = voices[VOICE_INDEX]; console.info(voices); var mainText = document.querySelector('.main_text').cloneNode(true); mainText.querySelectorAll('rb, rp').forEach((node) => { node.parentNode.removeChild(node); }); var text = mainText.innerText; text = text.trim().replace(/(?:\r\n|\r)/g, '\n').replace(/。/g, '。\n').replace(/\n{2,}/g, '\n'); var lines = text.split('\n'); var speak = () => new Promise((resolve) => { ssu.onend = resolve; setTimeout(() => { speechSynthesis.speak(ssu) }, MIN_WAITING_TIME); }); var play = async () => { for (var i = 0; i < lines.length; i ++) { ssu.text = lines[i]; await speak(); } }; play(); }; speechSynthesis.getVoices().length === 0 ? speechSynthesis.onvoiceschanged = main : main(); })(); void 0;

ただし、いわゆる無能ボイスなので、抑揚もないし間違えもするので実用的ではありません。
Macのメジャーブラウザでは動きますが、Windowsでは試していません。また、期待通りに動かない作品もあります。とりあえず こちらの作品 で試してみてはどうでしょう。

仕様

  • ルビに対応。つまり振り仮名を優先的に読み上げます
  • 「準備(したく)をする」などと括弧内で仮名を振っている文章は「じゅんびしたくをする」などと読み上げられます
  • 句点に差し掛かると、いくらか間を持たせるようにしています
  • フォントセットにない外字などは画像で表示されているため、無視されます

カスタマイズ

変数をいじることでいくらかカスタマイズできます。

  • VOICE_INDEX 声質を選択します。Macではプリインストールされている女性の声と男性の声、Google翻訳をインストールしている環境ではGoogleの用意した声を選択できると思います。それぞれ 0 1 2 という感じです。怪談のような作品では 1 の男性の声が合っていると思いますが、環境によっては 0 以外を選択するとエラーになるかもしれません。
    (ちなみに開発者ツールのコンソールに選択肢を表示しているので、わかる人はそちらをご覧ください。)
  • RATE 読み上げる速度です。
  • VOLUME ボリュームです。
  • MIN_WAITING_TIME 句点( )で待機する時間です。ミリ秒で指定してください。

開発関係

どうも speechSynthesis.getVoices() の返り値が空だったり空でなかったりするので調べたところ、

  • speechSynthesis.onvoiceschanged を待ってから getVoices() すると良い
  • ただし Safari では onvoiceschanged は呼ばれない。しかし getVoices() は必ず成功する

という問題に出くわしました。そこでいったん getVoices() して、その返り値が空であれば onvoiceschanged を挟み、空でなければ挟まずに処理を続行するようにしています。

【その他の青空文庫用ブックマークレット】
* 青空文庫の闇堕ちブックマークレット
* 青空一行文庫ブックマークレット

3
2
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
3
2