nikkie-ftnextの日記

イベントレポートや読書メモを発信

「プログラムに読み上げてもらいたい!」というアイデアをPythonで手早く検証する

はじめに

やらなければいけないことは手短に nikkieです🍨

この記事は、アイうた円盤発売アドベントカレンダー 2日目の記事です。
昨日はnikkieさんによる『カウントダウンなら、まかせて!! #アイの歌声を聴かせて Blu-ray & DVD 発売アドベントカレンダーを始めます』でしたね。
アドベントカレンダーが開幕しました!🎊

さて、今回は(別の記事で触れたこともあるのですが)、プログラムに読み上げてもらう簡単な方法を取り上げます。
「アイうたのシオンみたいなプログラムが作れないかな」と考えるようになった後、最初に試した実装です。

目次

プログラムに読み上げてもらいたい!

アイの歌声を聴かせて』の"ポンコツAI"シオン🤖は、サトミを始めとする登場人物たちと 会話 します1
人間同士が会話するように、シオンも人間と会話できるわけです。

この会話機能はプログラムで実装されているわけですが、(フィクションとはいえ)「スムーズに会話するのすごい!」と思ったんですよね。
人がしゃべった音声をプログラムで聞き取り、それを処理して、プログラムが応答を読み上げる(※妄想です。音声を直接処理するようなやり方もあるでしょう)。
「プログラムで聞き取り・読み上げってどうやるんだろう」と興味を持ち、「シオンの一部の機能でも実装してみたいなー」とすぐできる実装で試してみました。

以下では、テキストを読み上げるプログラムというアイデアPythonというプログラミング言語でどのように手早く実装したかを書いていきます。
なお、プログラムによるテキスト読み上げは、Text-To-Speech(TTS)と呼ばれます2

Pythonプログラムで読み上げ

イデアを手早く実装したかったので、macOSにあるテキスト読み上げコマンドを、Pythonで書いたプログラムから呼び出すという実装にしました。

sayコマンド(macOS

ターミナルにsay いま、幸せ?のように入力すると、「いま、幸せ?」と読み上げます!
macOSのバージョンによるかもしれませんが、私の環境では日本語担当のKyoko-sanが読み上げました。

sayコマンドについて詳しくはこちらをどうぞ3

Pythonからsayコマンドを呼び出す

標準ライブラリのsubprocessを使って、sayコマンドを呼び出します4

>>> import subprocess
>>> subprocess.run(["say", "いま、幸せ?"])
CompletedProcess(args=['say', 'いま、幸せ?'], returncode=0)

ターミナルにおけるsay いま、幸せ?Pythonで書いたプログラムから呼び出す際はsubprocess.run(["say", "いま、幸せ?"])となります。
ターミナルにおけるコマンド全体を半角スペースで区切って、リスト(というデータ型)として渡すわけですね。

subprocesssayコマンドを呼び出す」という実装で、シオンの会話機能の一部が再現できました🙌

秘密はね、最後に明かされるんだよ(実はドキュメントに…!)

正直なところ、「Pythonというプログラミング言語でこんなことを実装しようというのは少数派だろうなあ(肩身狭い)」と思っていたのですが、なんとPython公式ドキュメントの一部に同様の試みが掲載されていました!

「Logging クックブック」の「ロギングメッセージを喋る」です!
https://docs.python.org/ja/3/howto/logging-cookbook.html#speaking-logging-messages

「ロギングメッセージを喋る」ではTTSにespeakコマンドを使っています。
eSpeakはLinuxWindows向けの会話合成ソフトウェアです5

標準ライブラリのsubprocessを使う点は共通ですね!
「ロギングメッセージを喋る」を参考に、Popenを使うように書き直しても動作しました6🙌

>>> import subprocess
>>> cmd = ["say", "いま、幸せ?"]
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)  # コマンド実行スタート
>>> p.communicate()  # コマンド終了待ち
(b'', None)

プログラムにテキストを読み上げてもらうのは、ドキュメントに載るくらいには主流ってことですね!(異論は認めます)

終わりに

人間と会話できるAI🤖シオンの一部をなすであろう(※妄想)、プログラムによるテキスト読み上げをPythonで手短に実現する方法を紹介しました。
subprocess自体はsayコマンドに限らずさまざまなコマンドを呼び出せるため、実はシオン実装のために触っていたのが思わぬところで役立ちもしました(記事化はまた別の機会に)。

動作確認した環境は以下です。

  • macOS 10.14.6 (メンテを怠っており、非常に古いです)
  • Python 3.10.2
>>> subprocess.run(["say", "以上、アイうた円盤発売アドベントカレンダー 2日目の記事でした。"])

P.S. より本格的な実装へ

手早く実装してできあがったシオンに満足し、開発を続けることにしました。
sayコマンドだとmacOSでしか動作しない(OS依存)ため、機械学習モデルを使った実装に置き換えました。

音声合成については以下の本で実装に必要な範囲をキャッチアップしています。


  1. こんな感じでしゃべります:

  2. この記事で取り上げるトピックは「音声合成」と呼ばれる技術です。「音声を計算機的に作り出す(合成する)技術」です。テキスト音声合成をText-To-Speech(TTS)と呼びます。(ref: 『Pythonで学ぶ音声合成』 p.18)

  3. こんな記事も見つかりました。すべては再現しませんでしたが、unagi😂 非実用 say コマンド · GitHub

  4. subprocess.run のドキュメント https://docs.python.org/ja/3/library/subprocess.html#subprocess.run

  5. 「eSpeak is a compact open source software speech synthesizer for English and other languages, for Linux and Windows.」 http://espeak.sourceforge.net/ より

  6. subprocessについて事例ベースで読めるこちらのプログもおすすめです: