Macで選択した文字列を ずんだもん（VOICEVOX）に読み上げさせる - Automatorを使う方法 -

## はじめに

VOICEVOXは、ずんだもん動画を作るための不真面目なツールとして有名ですが、個人的にはとても実用性の高い日本語読み上げツールだと思っています。

## 選択した文字列を読み上げさせたい

さて、選択した文字列を右クリックしてVOICEVOXに読み上げさせたいケースはよくあるでしょう。しかし、なかなか「これ」といった方法がありませんでした。

## Automatorを使う

そこで安直でありながら高い汎用性を持つと思われる方法として、Automatorを採用します。

まず、Automatorを起動して、新規作成で「クイックアクション」を選びます。これで、**右クリック**もしくは**自分で割り当てたキーボードショートカット**から「サービス」に投げられるクイックアクションが作成できます。

![Automatorを起動](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/8fee8dda-763a-46b6-84a3-e513ff3863d6.png)

次に、シェルスクリプトを入力します。ユーティリティから、シェルスクリプトを実行を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/86b2482e-c731-4e1f-a500-4adff95d6d18.png)

あとは、こんな感じで一枚にまとめてバチンと貼れば動きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/86c388b4-999b-4079-a87b-692aa6fba0c3.png)

```sh
# VOICEVOX エンジンの URL
ENGINE_URL="http://localhost:50021"

# Automator からの標準入力を取得し、URL エンコード
INPUT_TEXT=$(cat)
ENCODED_TEXT=$(echo "$INPUT_TEXT" | jq -sRr @uri)

# 音声合成用クエリの生成
QUERY_JSON=$(curl -s -X POST \
    "${ENGINE_URL}/audio_query?text=${ENCODED_TEXT}&speaker=1" \
    -H "accept: application/json")

# 音声データの生成
OUTPUT_WAV="/tmp/voicevox.wav"
curl -s -X POST "${ENGINE_URL}/synthesis?speaker=1" \
    -H "Content-Type: application/json" \
    -d "${QUERY_JSON}" \
    --output "${OUTPUT_WAV}"

# 音声を再生
afplay "${OUTPUT_WAV}"

# 一時ファイルを削除
rm "${OUTPUT_WAV}"
```

あとは **ファイル → 保存** するだけです。ここで、アクションの名前を求められますので、**VOICEVOXで読み上げる** とすればよいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/a9ef2771-a9ae-4895-bb20-159dc5cfe105.png)

これで、全てのMacのアプリケーションで、**右クリック → サービス → VOICEVOXで読み上げ** でずんだもんが読んでくれるようになりました。もちろん、**環境設定 → キーボード → キーボードショートカット → サービス → テキスト** から任意のキーボードショートカットを割り当てる事も可能です。

作成されたワークフローは `~/Library/Services/` に保存されます。従って、サービスが不要になった場合は、

```sh
rm -r ~/Library/Services/VOICEVOXで読み上げる.workflow
```

で削除できます。

## おまけ１

VOICEVOXが起動していない時は起動させて待つようにChatGPTにスクリプトを書いてもらいました。

```sh
# VOICEVOX エンジンの URL
ENGINE_URL="http://localhost:50021"

# VOICEVOX のアプリケーション名
VOICEVOX_APP="VOICEVOX"

# VOICEVOXが起動しているかチェック
if ! pgrep -x "$VOICEVOX_APP" > /dev/null; then
    echo "VOICEVOXが起動していないため、バックグラウンドで起動します..."
    open -a "$VOICEVOX_APP" --background
    
    # エンジンの起動を待機（最大30秒）
    echo "エンジンの起動を待機中..."
    for i in {1..30}; do
        if curl -s --head --request GET "$ENGINE_URL" | grep "200 OK" > /dev/null; then
            echo "VOICEVOXエンジンが起動しました。"
            break
        fi
        sleep 1
    done
fi

# Automator からの標準入力を取得し、URL エンコード
INPUT_TEXT=$(cat)
ENCODED_TEXT=$(echo "$INPUT_TEXT" | jq -sRr @uri)

# 音声合成用クエリの生成
QUERY_JSON=$(curl -s -X POST \
    "${ENGINE_URL}/audio_query?text=${ENCODED_TEXT}&speaker=1" \
    -H "accept: application/json" \
    -d '')

# 音声データの生成
OUTPUT_WAV="/tmp/voicevox.wav"
curl -s -X POST "${ENGINE_URL}/synthesis?speaker=1" \
    -H "Content-Type: application/json" \
    -d "${QUERY_JSON}" \
    --output "${OUTPUT_WAV}"

# 音声を再生
afplay "${OUTPUT_WAV}"

# 一時ファイルを削除
rm "${OUTPUT_WAV}"
```

## おまけ２

せっかくAutomatorを使っているので、以下のように、複数に分割して、標準入力でつなぐことも可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/1b9e9c9a-075c-425b-8ab5-30153ed39829.png)

```zsh
jq -sRr @uri 
```

```zsh
curl -s -X POST \
    "http://localhost:50021/audio_query?text=$(cat)&speaker=1" \
    -H "accept: application/json" \
    -d ''
```

```zsh
curl -s -X POST "http://localhost:50021/synthesis?speaker=1" \
    -H "Content-Type: application/json" \
    -d "$(cat)" \
    --output "/tmp/voicevox.wav"
```

```zsh
afplay "/tmp/voicevox.wav"
```

```zsh
rm "/tmp/voicevox.wav"
```

こうすると、Automatorを使っているな〜という感じがしますし、途中にいろいろなアクションを挟んで一コマずつ実行することでデバッグしやすくなるかもしれません。

この記事は以上です。