※追記:ウェブサイト読み上げは、拡張機能の Read Aloud: テキスト読み上げ音声リーダー を入れればOKだった…。
長いニュース記事などを読み上げてくれないかと試行錯誤した結果、以下の方法で、読み上げさせることができた。
下準備
Open JTalk をインストール
sudo apt install open-jtalk open-jtalk-mecab-naist-jdic hts-voice-nitech-jp-atr503-m001
ボイスデータをダウンロード
上記でダウンロードしたデフォルトのボイスデータ(nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice)では、長文を読ませると、ものすごく間延びするエラーが発生することがあるので、それ以外のボイスデータをダウンロードする。
以下のリンク先からzipファイル(2025年6月10日現在の最新は、MMDAgent_Example-1.8.zip)をダウンロードしてくる。
MMDAgent - Browse /MMDAgent_Example at SourceForge.net
zipファイルを展開したら、その中にある Voice ディレクトリを適当なところに置く。
pythonスクリプト(読み上げ.py)を作成する
ChatGPT曰く、Open JTalkのソースコードでは、バッファ長(MAXBUFLEN)が1024バイトに固定されているらしく、長文を読み上げさせると、途中で終わってしまう。
そこで、ChatGPTに長文を読み上げるスクリプトを作ってもらった。以下を、「読み上げ.py」として保存(端末を立ち上げて、すぐにスクリプトを実行させたいので、ホームディレクトリ(「/home/<ユーザ名>」)に保存するとよい。)
「# ボイスデータを指定」、「# 入力テキストファイル」、「# 入力テキストファイルのバックアップ(1度だけ)」、「# mpvで再生。デフォルトのボリューム調整。」の行を適宜、修正すること。
import subprocess import os import re import textwrap import sys import shutil # ========== 設定 ========== OPEN_JTALK_BIN = '/usr/bin/open_jtalk' DICT_PATH = '/var/lib/mecab/dic/open-jtalk/naist-jdic' VOICE_PATH = '/home/your_username/ドキュメント/Voice/mei/mei_normal.htsvoice' # ボイスデータを指定 TMP_WAV = 'tmp.wav' MAX_CHARS = 300 INPUT_ORIGINAL = '/home/your_username/ダウンロード/input.txt' # 入力テキストファイル INPUT_BACKUP = '/home/your_username/ダウンロード/input_backup.txt' # 入力テキストファイルのバックアップ(1度だけ) INPUT_FILE = 'tmp.txt' # 改行除去後の一時ファイル # ========== 改行をスペースに置換してtmp.txtに保存 ========== def preprocess_input_file(): with open(INPUT_ORIGINAL, "r", encoding="utf-8") as infile: content = infile.read().replace('\n', ' ') with open(INPUT_FILE, "w", encoding="utf-8") as outfile: outfile.write(content) # ========== 前処理 ========== def clean_text(text): text = re.sub(r'[()【】[]\[\]{}<>「」『』“”]', '', text) text = re.sub(r'[^\wぁ-んァ-ン一-龯。、!?\s]', '', text) return text def split_text(text, max_chars=MAX_CHARS): sentences = re.split(r'(?<=[。!?])', text) segments = [] current = '' for sentence in sentences: if len(current) + len(sentence) < max_chars: current += sentence else: if current: segments.append(current.strip()) current = sentence if current: segments.append(current.strip()) return segments # ========== 音声合成と再生 ========== def tts_openjtalk(text, out_path=TMP_WAV): cmd = [ OPEN_JTALK_BIN, '-x', DICT_PATH, '-m', VOICE_PATH, '-ow', out_path ] process = subprocess.Popen(cmd, stdin=subprocess.PIPE) process.communicate(text.encode('utf-8')) def play_wav_mpv(file_path): subprocess.run(['mpv', '--volume=80', file_path])# mpvで再生。デフォルトのボリューム調整。 def read_long_text(text): cleaned = clean_text(text) segments = split_text(cleaned) for i, segment in enumerate(segments): print(f"\n▶️ Part {i+1}/{len(segments)} 再生中...") tts_openjtalk(segment) play_wav_mpv(TMP_WAV) # ========== メイン処理 ========== if __name__ == '__main__': preprocess_input_file() if not os.path.exists(INPUT_FILE): print(f"❌ 中間ファイル {INPUT_FILE} が見つかりません。") sys.exit(1) with open(INPUT_FILE, "r", encoding="utf-8") as f: input_text = f.read() read_long_text(input_text) print("\n✅ 読み上げ完了!") # ===== 一時ファイル削除 ===== for tmp_file in [INPUT_FILE, TMP_WAV]: try: if os.path.exists(tmp_file): os.remove(tmp_file) print(f"🗑️ {tmp_file} を削除しました。") except Exception as e: print(f"⚠️ {tmp_file} の削除に失敗しました: {e}") # ===== input.txtを削除前にバックアップ(バックアップファイルがあった場合、上書き保存される) ===== # コピー元ファイルとコピー先パス src_path = INPUT_ORIGINAL dst_path = INPUT_BACKUP # ファイルをコピー shutil.copy2(src_path, dst_path) # ===== input.txt削除 ===== os.remove(INPUT_ORIGINAL) print(f"🗑️ input.txt を削除しました。")
読み上げるテキストを準備
読み上げるテキストを input.txt として保存(保存先はスクリプトの「# 入力テキストファイル」の行で指定された場所)。
webサイトの文章から input.txt を生成するには、ブラウザで選択した文章をテキストファイルにするブックマークレット - adbird(広告鳥) 備忘録 が便利。
読み上げ
端末を立ち上げて、以下を実行。
python3 読み上げ.py
スクリプト上でmpvのデフォルトのボリューム調整ができるが、いきなり大きな音量で再生されるかもしれないので、事前にシステムのボリュームを下げておいたほうが良いかもしれない。
逆に音量が小さすぎる場合は、長い文章を読み上げさせている間に、 設定>サウンド>サウンド>Volume Levels>mpv で音量を調整するといい。
また、上記スクリプトでは自動的に input.txt を削除するようにしているので(一応、backupファイルをコピーするが、すでにbackupファイルがあったばあいは上書き保存されるので注意)、input.txt を削除したくないときは、最後の2行をコメントアウトする。
webサイトの文章を読み上げさせる
ブラウザで選択した文章をテキストファイルにするブックマークレット - adbird(広告鳥) 備忘録 と組み合わせると、3アクションで読み上げてくれる。
- (ニュース記事など)読み上げさせたいテキストをブラウザ上で選択。
- テキストが選択されている状態で、「input.txt出力」のブックマークをクリックすると、input.txt がダウンロードされる。
- 端末を開いて、
python3 読み上げ.pyを実行。