Udemy の字幕を Web Speech API で読み上げてもらった → Chrome 拡張機能にした

# 概要
Chrome 拡張機能としてウェブストアに公開してみたので、個人のログとして記事にします。

:::note warn
Chrome 拡張機能の作成方法などは一切書いていません。
:::

# 作ったもの
[Speak U : 字幕読み上げツール - Chrome ウェブストア](https://chrome.google.com/webstore/detail/speak-u-%E5%AD%97%E5%B9%95%E8%AA%AD%E3%81%BF%E4%B8%8A%E3%81%92%E3%83%84%E3%83%BC%E3%83%AB/nabpbhldnibjnmimbneabgdjdgobopoj?hl=ja)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378101/d1b5fd5e-71a4-ac49-95aa-9b8994dca0f3.png "Speak U : 字幕読み上げツール")

## そもそもの話
### 背景
Udemyで学習していたプログラミングのビデオコースが英語（日本語字幕あり）のものだった。
- ちなみにそのビデオコースは[「Full Stack: Angular and Java Spring Boot E-Commerce Website」](https://www.udemy.com/course/full-stack-angular-spring-boot-tutorial/)というもの
- 最近？では海外のビデオコースでも、（自動生成だが）日本語字幕ありのものが増え、学びやすい印象
### 課題
字幕を読みながらメモを書いたりコードを書いたりするのは結構やりづらい！

## どうしたか
「API 読み上げ」でググると、無料かつ簡単にテキストの読み上げができることが分かった。

**[Web Speech API - Web API](https://developer.mozilla.org/ja/docs/Web/API/Web_Speech_API)**
> Web Speech API は、音声データをウェブアプリに組み入れることを可能にします。Web Speech API は、SpeechSynthesis (Text-to-Speech; 音声合成) と SpeechRecognition (Asynchronous Speech Recognition; 非同期音声認識) の 2 つの部分から成り立っています。

Microsoft Edge ブラウザで右クリックするとオプションに表示される「音声で読み上げる」も、おそらく上記のAPI。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378101/86e804de-a899-9852-93a2-882f1c3020c9.png "音声で読み上げる - Microsoft Edge")

ビデオコンテンツの字幕を出力している箇所を開発者ツールで確認したところ、どのコンテンツも`div`の`class`属性が共通だった。
→ 字幕に関係する [DOM](https://developer.mozilla.org/ja/docs/Web/API/Document_Object_Model) の変化を監視すればいい感じに捕捉して利用できるのではないかと思った。

**[MutationObserver - Web API](https://developer.mozilla.org/ja/docs/Web/API/MutationObserver)**
> MutationObserver インターフェイスは、 DOM ツリーへ変更が加えられたことを監視することができる機能を提供します。これは DOM3 Events の仕様で定義されていた Mutation Events (en-US) 機能の置き換えとして設計されたものです。

**「よし！できそうだから Chrome 拡張機能にしちゃえ！」** までの流れはいつ何をきっかけにして決まったか自分のことながら記憶がないので割愛。

# 作るにあたって知ったこと
傍から見れば「そんなことも知らないのか」ばかりだと思いますが…。

## 音声合成機能が環境ごとに色々違う
### 音声リストについて
上で紹介した Web Speech API の `SpeechSynthesis` もとい音声合成だが、まず音声リストが OS やブラウザごとに種類が異なる。

（例）Windows の Chrome ブラウザの場合（日本語のもの）
```
0: Microsoft Ayumi - Japanese (Japan)
1: Microsoft Haruka - Japanese (Japan)
2: Microsoft Ichiro - Japanese (Japan)
3: Microsoft Sayaka - Japanese (Japan)
4: Google 日本語
```

（例）macOS の Chrome ブラウザの場合（日本語のもの）
```
0: Kyoko
1: Google 日本語
```

`Kyoko` は iPhone の「画面の読み上げ」機能で利用できる音声と同じ。ちなみに Windows の Microsoft Edge では `Microsoft Nanami` という音声があった。（自然な発話で個人的にベストな音声 Nanami ちゃん :D ）

### 読み上げ方（発話リクエスト）について
`SpeechSynthesisUtterance` にプロパティを設定することで任意のテキスト読み上げやピッチ調整、音量調整などができた。

```
// 音声合成
const SYNTHESIS = window.speechSynthesis;

// 発話リクエスト
let speech = new SpeechSynthesisUtterance();
speech.text = 'こんにちは';
speech.pitch = 1.5;
speech.volume = 0.5;
speech.rate = 1.5;

// 発話リクエスト内容で読み上げ
SYNTHESIS.speak(speech);
```

この発話リクエストだが、速度プロパティ `rate` について、音声やブラウザごとに最小値と最大値が異なることが分かった。

例えば、音声別の比較。環境は Windows の Google Chrome で、`Microsoft Ayumi` 系は最小値が `0.1` で最大値が `10` であった。対して `Google 日本語` の場合は、最小値が `0.1` で最大値が `2` であった。**（2以上を指定すると読み上げなくなる）**
ブラウザ別の比較では、音声は同じでも Google Chrome で `rate = 10` が、Microsoft Edge での `rate = 3` と同じ速度で読み上げられた。

:::note info
まとめ
MDN Web Docs の Web Speech API ドキュメントページにて、実験的な機能であることからブラウザ互換性をチェックして利用しようという記載がある。今後仕様が変わることも大いにあると思うので、別の機会で利用するときは必ず確認する。
:::

## 拡張機能の公開は予想以上に簡単
Qiita でも 「chrome 拡張機能 公開」でキーワード検索すると多くの方が公開手順の説明をされているが、手順の感想通り「え？これで公開できるの？」レベルでサクッと公開された。
特に自分の作った拡張機能の `permissions` がストレージだけだったこともあるかもしれないが、**初回の審査申請から公開まで15分もかからなかった。**
後日、修正を反映させるために2回申請を行ったが、どちらも24時間以内に審査&公開された。モバイル系のアプリをストアに申請して公開するのと比べれば、とってもお手軽にできるのだなぁと思った。

:::note info
まとめ
Chrome 拡張機能の審査は Bot もしくは 審査員がめちゃ仕事できる。
:::

# さいごに
ふとした課題をきっかけに `Web Speech API` や Chrome 拡張機能について知ることができました。
~~Udemy のビデオコース学習は全然進んでない~~ これからも学習しながら出来ることを増やしていきたいです。