小説家になろう・カクヨムの小説を良い感じに朗読してくれるChrome拡張機能「novels-reader」を作ったよー【充実の辞書機能を搭載！固有名詞と真正面から殴り合える読み上げツールをお探しのあなたへ】

# 前置き（スキップ可）
[前回の投稿](https://qiita.com/snowsunny/items/7a72d2e49aaea5d404c3)で次回予告してたやつです。宣伝６割、技術的な話２割どうでも良い話２割な感じです。

## モチベーション
最大の理由は「読むのが面倒臭い」←これです。

最近なろうの小説を結構読むようになったのですが、何と言っても読むのが面倒臭い！

それが理由で普通の小説も余り読まない私なのですが、なろうに関してはテキストデータが在るのに何でわざわざ読まないと駄目なん？
つらみ…(´・ω・｀)

と言う身勝手な理由でさらにつらみゲージが上がっていました…

最初は既存のテキストリーダーにコピペし、読み上げて貰ってつらみを抑えていたのですが、ルビに対する弱さと、コピペ自体が糞面倒臭いと言う新たなつらみを生む結果に終わりました…

先人達が作ってくれた専用アプリ等も試してみたのですが、ちょっと設定が面倒だったり、ルビ関連機能で痒い所にちょっと手が届かないなーって事があり、最終的に自分で作った方が早いんちゃう？と言う結論に至り、作ったのが今回ご紹介する拡張機能です！

# novels-readerって何？
> novels-readerは「小説家になろう（syosetu.com）」の小説ページに、読み上げ機能を追加するChrome拡張機能です。
> https://github.com/snowsunny/novels-reader

## 主な機能
### __テキスト読み上げ機能__
小説の各段落を連続読み上げます。それに加えて下記の機能を使う事が出来ます。

- 読み上げ速度、声の高さを変更出来る
- 読み上げている所をハイライト表示
- 次話がある場合に自動でページ移動
- 読み上げ箇所の指定が可能です。「題名・前書き・本文・後書き」から読み上げて欲しい箇所を選択出来ます。

__ブラウザの読み上げ機能を使っているので、外部ソフトを設定したりする必要がありません。__

### __ルビ辞書機能__
「ルビ対象文字::ルビ」のフォーマットで、対象文字を設定されたルビで読み替える事が出来ます。

#### ユーザー辞書
全ての小説に適用される辞書を設定出来ます。

#### 小説別辞書
各小説のみに適用される辞書を設定出来ます。
また、小説のルビを自動で辞書に登録する機能があります！

#### 無視するルビ（正規表現のみ）
強調表現等で使わるルビを無視する為の設定を、正規表現で記述出来ます。

# インストール方法
すみません…  :bow: 
まだウェブストアに公開していなくて、ちょっとインストールが面倒臭いのですが何卒よろしくお願いします。 :pray: 
自分が関わっていないウェブサービスの拡張機能を公開した事が無くて、利用規約的には大丈夫そうなのですが、一応お伺いを立てたうえで公開しようかなーって思ってます。

1. __novels-readerをダウンロード__
gitを使ってクローンするか、↓のリンクからzipファイルをダウンロードして下さい。
[novels-reader-2.0.2.zipをダウンロード](https://github.com/snowsunny/novels-reader/releases/download/2.0.2/novels-reader-2.0.2.zip)
2. __Chromeにインストールする__
初めにChromeの拡張機能の管理ページ（chrome://extensions）を開きます。
右上に表示されている「デベロッパーモード」にチェックが付いていない場合は、それを付けてデベロッパーモードを有効にして下さい。
「１」でクローンした場合は「novels-reader-crx」フォルダを、zipをダウンロードした場合はzipファイルを、Chromeの拡張機能管理ページで「パッケージ化されていない拡張機能を読み込む」をクリックして選択して下さい。
アイコンが追加され、何も問題が出なければインストール作業は終了です。

## 更新方法
既にnovels-readerをインストールしている方は、古いバージョンの物が入っている「novels-reader-crx」フォルダーの中身を、最新バージョンの中身と入れ替えて更新ボタンを押してください。オプションや辞書データをそのままで拡張機能の更新が行える筈です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10658/68b9d8cb-e6d3-7178-26ae-6a1cd6eb6acc.png)

### ⚠️⚠️⚠️ バージョン 1.x 系からバージョン 2.x 系へ移行する方へ ⚠️⚠️⚠️ 
予期しない問題が起こる可能性が高いです 😖
良ければ1.xの辞書データを保存しておいてから、2.xを新しい拡張機能としてインストールして貰えればと思います 🙏

## 使い方
下記の対応サービス・ページの小説ページを開きます、そうすると自動で小説の読み上げが始まります。
- 対応サービス(ドメイン)・ページ(ローカルファイル・特定のURLを含むページ)一覧
  - ncode.syosetu.com
  - novel18.syosetu.com
  - kakuyomu.jp
  - ローカルのHTMLファイル
    - HTMLファイルの直開きに対応。小説以外も色々な使い方が出来るかも？ :thinking: 
  - pages-for-novels-readerをURLに含むページ
    - 単純なHTTPサーバーでHTMLを配信する時に使える。有名な所で公開していなくても読み上げ対象ページになるので、何か便利に使って貰えればー :pray: 

# 使い方
「小説家になろう」の小説ページを開きます、そうすると自動で小説の読み上げが始まります。
※自動で再生するかは、読み上げ機能オプションから変更出来ます。

### 再生方法
各段落の左側に「再生ボタン」が表示されます。そのボタンをクリックすると、その段落から再生を開始します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/10658/86ef6e83-7f26-a311-f970-b710e9d0ad89.png)

### 停止方法
ページの左上に「停止ボタン」が表示されるので、そのボタンをクリックすると読み上げを停止する事が出来ます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/10658/91a08057-ff9c-03b3-c63b-5d1d9f3eb442.png)

## 読み上げ機能オプションと辞書機能
Chromeの右上に表示されている拡張機能のnovels-readerのアイコンを右クリックして、オプションページを開きます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/10658/9518201f-6780-4a38-a7a2-147acf158477.png)

↓の様なオプションページが開くと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10658/6cd8aca4-3f86-4b25-bc88-a63617cd121b.png)

# まとめ
どうでしょうか？少しでも使ってみたいと思って貰えたら幸いです！ :blush: 
もし使って貰えたなら、この記事に感想とかを書いて貰えると作者がとても喜びます…|ω・｀)ﾁﾗｯ

個人的に欲しい機能は大体実装出来たので、宣伝記事を書いた感じです。
何か不明点や、欲しい機能、問題の報告等があれば、Githubの方にIssueやPull Requestを作って貰うか、下記のフォームからよろしくお願いします！
(｀･ω･´)b
https://goo.gl/forms/PUGoOemm3sEXe42f2

# テクい話
ここまでは宣伝ですが、このままだとQiitaさんに怒られそうなので、ここからは少し技術的な話を書いてみたいと思います…ｗ

# 拡張機能作成に使ったもの
## ビルド系
- webpack
- gulp

今回初めてwebpackを使って拡張機能を作ってみましたが、わりと良い感じ作る事が出来ました。
manifest.jsonの書き出しは、なるべくファイルをまとめるって言うwebpackの音楽性と合わなかったのでgulpを使いましたが、他の部分はかなり楽に出来て良い感じでした。

また後で、この部分だけを取り出したcontentスクリプトを使う拡張機能向けのテンプレートをGithubに上げようかなーって思ってるので、その際は是非使ってやって下さい。
d(´・ω・｀)b

## 辞書データの保存
- localStorage
- chrome.runtime.sendMessage
- chrome.runtime.onMessage

辞書データの保存にはブラウザのlocalStorageを使用して、オプションページのlocalStorageに保存しています。
なのでブラウザのキャッシュデータ等を消す処理を行うと共に消え去ります…（´-ω...:.;::..
辞書データ書き出し機能＆読み込み機能を付けようと思ってはいるのですが、まだやってません…ｗ

小説ページとオプションページ間のデータのやり取りには公式ドキュメントに載っている`chrome.runtime.sendMessage`と`chrome.runtime.onMessage`を使って行っています。
> [Message Passing - Google Chrome](https://developer.chrome.com/extensions/messaging)

でも最近やったChrome拡張機能をFirefoxに移植した時の事を思うと、互換を考えて`chrome.runtime.connect`と`chrome.runtime.onConnect`を使った方が良いかなーと思っている今日この頃です…
(´ - ω - ｀)

# contentスクリプトでやっている事
小説ページで動くcontentスクリプトでやっている事をザクっと書いてみたいと思います。

オプションページと通信して、各種オプション、辞書データを取得
↓
必要なスタイル定義をページに読み込む
↓
オプションを確認して読み上げ箇所を取得、変数に投げ込む
↓
色々必要な変数を初期化
↓
各読み上げ箇所から読み上げデータを分割、読み上げ設定、ルビ抽出、再生ボタンを設置
↓
ルビの自動保存がオンになっている場合は、オプションページと通信して辞書データの更新
↓
読み上げ開始
↓
次の話があれば自動で移動

って感じの流れで処理を行っています。

# 大変だった事、やっといて良かった事
## 大変だった事
まぁやっぱり辞書機能を作るのが結構大変でした…ｗ
ルビの抽出もそうだし、自動保存の時に同じルビを保存しない処理とか、手動更新時との違い等で結構考える事があって、大分MPを消費しました…でもその甲斐あって結構良い感じの物が出来たかなーって思いです。

## やっといて良かった事
[前回の投稿](https://qiita.com/snowsunny/items/7a72d2e49aaea5d404c3)で紹介した「[roudokuka](https://github.com/snowsunny/roudokuka)」ですが、拡張機能を作ってて、やっぱり読み上げ部分を別パッケージにしといて良かったなー感が大分ありました。
別パッケージ化しとく事によって、コードが複雑にならず素早く拡張機能を作れたなーって気がします。

皆さんも他で使えそうなモジュールは、ドンドン別パッケージ化していこうな！（他の人が助かる物も在るだろうし
d(｀･ω･´)b

# 読みたい人だけ読んでねって話
テクい話は以上です。ここからは割りとどうでも良い「読みたい人だけ読んでね」って話を書いていきます。

# Why speechSynthesis!? ランキングトップ３
突然ですが、この拡張機能を使っていて「なんでそうなるんや…(´・ω・｀)」って感じる「speechSynthesisの読み上げランキグ」トップ３を紹介したいと思います。

## 第３位：「隙」を「ひま」と読む…
何故か「隙」を「ひま」って読んじゃうんですよね… :see_no_evil: 
文脈によってはちゃんと読み上げる事も在るかもしれないのですが、ほぼ100%「ひま」って読んじゃいます…
アクションシーンとかでは割りと頻出すると思うのですが、その度に「違うんだよなぁ…(´- ω - ｀)」と感じるこの読み上げが第３位にランクイン！

## 第２位：文脈によって読みが変わっちゃう事がある…
さっきはちゃんと読めてたのに、違う文脈だとちゃんと読めない…みたいなのが結構あります。日本語はﾑﾂｶｼｲ言語なのでしょうが無い気もするのですが、「さっきはちゃんと読めてたのに…(´・ω・｀)」感が凄いこの読み上げが第２位です！
※これからの進化に期待ですね…

## 第１位：「娘」を「にゃん」 と読む事がある… :cat: 
最初聞いた時に耳を疑ったこの読み上げが堂々の第１位です！ :clap: :clap: :clap: 

speechSynthesisの日本語の中の人が、実は中国人 or マクロスファンと言う線が濃厚ですが、最初聞いた時に本当に驚きましたｗ
「んん？えっ？(´・ω・｀)」ってなりました…ｗ

# おすすめ辞書設定＆使い方
上記ランキグを多少踏まえた、おすすめ辞書設定と使い方を書いてみたいと思います。

## おすすめ辞書設定
```:ユーザー辞書
隙::すき
獣人::じゅうじん
^\*+$::
```
ランキングに入っていた「隙」と、「獣人」がそのままだと「けものびと」って読まれちゃうので「じゅうじん」と読む辞書を追加しています。
「^\*+$」は区切り線的に使われてる時に「アスタリスク」を連呼されるので追加してあります。

```:無視するルビ
^・+$|^、+$
```
強調ルビで多いのは「・」と「、」だと思うので、その２つを設定しています。

## おすすめな使い方
### 読み上げ速度について
まぁこの拡張機能を作った大きな理由の一つでもあるのですが、個人的には「1.8〜2.0」くらいに設定して「読み上げを聞きならが、文章を読まずに見る」のが黙読よりも一番早く小説の話を進められます。
一昔前に流行った速聴的な効果もあるかもです…ｗ

### ルビの自動登録について
新しい小説を読み始めた場合、ある程度作品特有のルビが集まったら「小説のルビを自動で辞書に登録する」オプションをオフにして、一回辞書を調整してから読み上げを続けるが良いかなーと思います。
理由としては、ルビを多様している作品だと「先輩」と書いて「キャラ名」と読む等の代名詞的なルビを使ってる作品が結構多くて、それが混ざるとこの拡張機能では正しく読み上げが出来なくなってくるんですよね…
そういうルビが多い作品はこのやり方を試してみて下さーい。

### キャラの名前を置き換える
作品のキャラ名に違うルビを設定する事で、擬似的にキャラ名を変更する事が出来ます。
例えば「主人公の名前」に「自分の名前」のルビを付けると、ちょっとだけﾆﾔｯって出来ますｗ :smile: 

# まとめ２
novels-readerって言う名前の通り他の小説投稿サイトにも対応したいなとか、Googleスプレッドシートに共有辞書作って皆で使えるようにしたいなとか、何かで良い感じ形態素解析して読み上げに感情を追加したいなとかとか、色々やりたい事はあるのですがまぁゆっくり作っていこうと思います。

色々書きましたが、皆さんに是非一度使って貰えれば幸いです。
よろしくお願いしまーす！(｀･ω･´)b

# 注意書き
> 「小説家になろう」は株式会社ヒナプロジェクトの登録商標です。
> 本拡張機能は株式会社ヒナプロジェクトが提供するものではありません。