🎙️

リアルタイム音声読み上げアプリを作ってみたら一瞬でできた

2023/04/21に公開

声が出せない環境でも通話に参加できる、リアルタイムな音声読み上げアプリをつくりました。
https://shovelful.vercel.app

タイピングした文字を読み上げてくれるというだけの超シンプルなものなので記事にするかどうかも迷ったのですが、技術的には個人的に少し面白かったのでかんたんに書いてみます。

デモ

https://twitter.com/koluriri/status/1649085568192753664

背景

Discordで作業通話をよくするのですが、私があまり声が出せない環境なことが多いため、もともとGoogle翻訳の読み上げ機能を使って発声(?)したりしていました。
ですがそういった既存の読み上げ機能では、文章を打ってから毎回再生ボタンを押さなければいけないので、通常の会話スピードに追いつこうとしてもどうしてもラグが発生します。
またその性質上、短い相槌には不向きだったり、少し長い文章を発話しようとするとタイピング中しばらく沈黙が生まれることがあるなどの問題もありました。
そこで、まるで普通に話しているかのような感じで、変換終了や句点などのもう少し細かい区切りでリアルタイムに読み上げできるものがあればいいな(作りたいな)とずっと思っていました。
多分1年以上、下手したら2年以上?アイディアとしてはあったのですがなんか着手する気にならず、今回やっと着手してみたら思ったより簡単で根幹となる部分は45分くらいでできてしまいました😱

技術

  • 言語: TypeScript
  • ライブラリ: React(create-react-app)
  • ルーティング: React Router
  • ホスティング: Vercel

だけです
スタイリングに関してはCSS in JSどころかCSS Modulesすら使用せずグローバルCSSでゴリゴリ書いています😵

音声合成API

やっとこの記事の本題なのですが、さて読み上げ機能をどう実装しようかというときに色々調べていて、GoogleのText-to-SpeechのAPIがいいかな〜といろいろ見ていたのですが
なんと、ブラウザの標準APIだけで音声合成ができてしまうらしいことを知り、、
実際に以下の2行で読み上げができてしまいました。かんたんすぎる😱

const uttr = new SpeechSynthesisUtterance("こんにちは");
window.speechSynthesis.speak(uttr);

ブラウザだけで済むので当然登録などはいらないし無料です。外部ライブラリなどもいりません。

また速度やピッチ、言語などプロパティも色々あるので声色のカスタマイズもできそうですし、スマホも含めて主要なブラウザはサポートしているようなのでブラウザサポートも大丈夫そうなかんじ🤔
https://developer.mozilla.org/ja/docs/Web/API/SpeechSynthesisUtterance

さらにさらに、speechSynthesis.getVoices()で得られるSpeechSynthesisVoiceオブジェクトを以下のようにvoiceに渡すと声色も変えられました。

const uttr = new SpeechSynthesisUtterance();
uttr.text = "こんにちは";

var voice = speechSynthesis.getVoices().find((voice) => {
   return voice.name === "Google 日本語";
});
if (voice) uttr.voice = voice;

window.speechSynthesis.speak(uttr);

この例ではGoogle日本語の声にしています。(ブラウザによって用意されている声の種類は違うので、上のように存在するか確認する必要がある)
もちろん高性能な外部APIにはかなわないですが、標準APIの声質でも事足りる用途に関しては全然使えそうではないでしょうか🤔

また今回は試しませんでしたが、、このWeb Speech APIではブラウザだけで音声認識もできるらしいです。
ブラウザすごい…🙂

デザインとアニメーション

せっかくなのでデザインとアニメーションについても書いておきます。

45分で完成した状態がこれです。例によって超殺風景です。
自分で使う用に作ったので最初はこれでいいと思ってたのですが、だんだん見た目もちゃんとしたくなってきたのでデザインを整えました。

今回はアイコンもロゴも含めすべてFigmaで完結しました。

アニメーションについては冒頭のツイートにもありましたが、inputのborder-bottom(実際にはborderではないけど)や、発話中の背景のぽわぽわモーションはほぼPure CSSです。(ほぼというのは、発話中のモーションについてはJSで発話開始と終了のタイミングでクラスを操作しています。)

ということで、デザインとアニメーションを含めたら多分5-6時間くらいかかってますが、爆速でアプリができた話でした🤔

Discussion