🌎

Macのsayコマンドで英語のテキストを読み上げる

2023/02/24に公開

text-to-speech

テキストファイルを音声で読み上げることをtext-to-speech と言います。
コマンドラインから使用できるtext-to-speechで何かよいものがないかと尋ねたところ、いくつか情報が寄せられました。
今回はmacに標準で付いている say コマンドを使ってみました。

まだ試していませんが、他の選択肢としては以下のものがあります。

https://cloud.google.com/text-to-speech

https://learn.microsoft.com/ja-jp/azure/cognitive-services/speech-service/spx-overview

テキストファイルを用意する

以下のような感じで用意しました。

$ ls -l text/*.txt
-rw-r--r--  1 koba  staff  37  2 24 20:30 text/a1a.txt
-rw-r--r--  1 koba  staff  68  2 24 20:31 text/a2b.txt
-rw-r--r--  1 koba  staff  50  2 24 20:31 text/a3a.txt
-rw-r--r--  1 koba  staff  55  2 24 20:31 text/a4b.txt
-rw-r--r--  1 koba  staff  16  2 24 20:32 text/a5a.txt
-rw-r--r--  1 koba  staff  21  2 24 20:32 text/a6b.txt
-rw-r--r--  1 koba  staff  15  2 24 20:32 text/a7a.txt
-rw-r--r--  1 koba  staff  84  2 24 20:32 text/a8b.txt
-rw-r--r--  1 koba  staff  50  2 24 20:33 text/a9a.txt

ファイル名の末尾がaのものは男性の声でbのものは女性の声を想定しています。

txt2aac

txt2aac.sh
#!/bin/sh -eu
if [ $# -eq 0 ];then
   echo "Usage: $0 input_text_file(.txt) ..."
   exit 1
fi
for i in $*; do
    OUTFILE=$(basename $i .txt).aac
    VOICE=Alex
    case $OUTFILE in
	*a.aac) VOICE=Alex;;
	*b.aac) VOICE=Victoria;;
    esac
    say -v $VOICE -o $OUTFILE -f $i 
done

-vでボイスのタイプを指定できます。Alexだと米国英語の男性、Victoriaだと米国英語の女性の声になります。

-v で指定可能なパラメータは以下のようにして調べることができます。

$ say -v '?' |head
Alex                en_US    # Most people recognize me by my voice.
Alice               it_IT    # Salve, mi chiamo Alice e sono una voce italiana.
Alva                sv_SE    # Hej, jag heter Alva. Jag är en svensk röst.
Amelie              fr_CA    # Bonjour, je m’appelle Amelie. Je suis une voix canadienne.
Anna                de_DE    # Hallo, ich heiße Anna und ich bin eine deutsche Stimme.
Carmit              he_IL    # שלום. קוראים לי כרמית, ואני קול בשפה העברית.
Damayanti           id_ID    # Halo, nama saya Damayanti. Saya berbahasa Indonesia.
Daniel              en_GB    # Hello, my name is Daniel. I am a British-English voice.
Diego               es_AR    # Hola, me llamo Diego y soy una voz española.
Ellen               nl_BE    # Hallo, mijn naam is Ellen. Ik ben een Belgische stem.

play.sh

生成されたaacファイルを順番に再生するために以下のスクリプトを作りました。
再生にはffplayコマンドを使っています。

#!/bin/bash -eu
trap 'exit' 2
if [ $# -eq 0 ];then
   echo "Usage: $0 audio_files ..."
   exit 1
fi
FFPLAY='ffplay -autoexit -nodisp -hide_banner -v error'
for i in $*; do
    echo -n "Playing" $i
    $FFPLAY $i
done

trap 'exit' 2 は^Cが押されたときに終了するためのものです。
ただし、ffplayの実行中の^Cはffplayが終了するだけなので、確実に止めるためには^Cを押し続けてshellスクリプトが^Cのシグナルを受け取るまで待つ必要があります。

ffplayでは正常時には何も出さないようにしたかったのですが、終了時に改行だけ出力されてしまいます。
そのため echo -n で再生中のファイル名を表示するようにしました。

/bin/sh では echo -n が想定通りに動かなかったので /bin/bash にしました。

使い方

$ ./txt2aac.sh text/*.txt
$ ./play.sh *.aac

とりあえずできましたが、ちょっと機械音っぽいです。まあ、無料で使えるものなので。

多分、GoogleやMicrosoftのAPIを使った方が滑らかなのでしょう。
何か情報のある方、教えてください。

関連

https://zenn.dev/tetsu_koba/articles/f54ae2cf4a18fb

Discussion