VOICEVOX の API を観察してみる
VOICEVOX はエディターとエンジンとコアで構成されているとあります。
参考: 全体構成
エディターがアプリで、エンジンが http サーバー、コアが音声合成の処理を行うモジュールになっているらしいです。
つまり、エディターがエンジンに対して REST API (以下 API) を叩いているというわけですね。
というわけで、その API の内容を観察してみようという記事になります。
API のキャプチャーには Wireshark を用いました。
起動時の通信
http and tcp.port == 50021 でフィルターをかけてみた結果が、こちら。

起動時には以下の情報を読み取っているようです。
- バージョン情報
/version - エンジンのマニフェスト情報
/engine_manifest - スピーカー情報
/speakers(ずんだもんなどのキャラクターリスト) - シンガー情報
/singers(〃)
スピーカー・シンガー取得後は各キャラクターの情報をより詳細に取得しているようですね。(/speaker_info?speaker_uuid=xxx, /singer_info?speaker_uuid=xxx)
音声合成リクエスト時の通信

では実際にずんだもんで音声合成のリクエストを送って、API を覗いてみました。

以下のような流れで音声が取得されているみたいです。
/accent_phrasesでアクセントの情報/synthesis?speaker=3でずんだもんの声を合成
(2.) で送っているリクエストボディの内容は、以下のように (1.) のレスポンスと似たようなものになっています。
したがって、(1.) でアクセントを取得し、(2.) でアクセントから音声を合成するという流れのようです。
実際に API を叩いてみる
httpie というツールを用いて API を叩きました。
- スピーカー情報を取得

ずんだもん (ノーマル) の id は 3 であることがわかりました。
- アクセント情報を取得
ずんだもんなのだ でアクセント情報を取得してみました。
(スピーカー情報と異なり、POST リクエストで取得)

- 音声合成
以下のようなリクエストボディーを作成します。
{
"accent_phrases": </accent_phrases で取得したデータ>,
"speedScale": 1,
"pitchScale": 0,
"intonationScale": 1,
"volumeScale": 1,
"prePhonemeLength": 0.1,
"postPhonemeLength": 0.1,
"outputSamplingRate": 24000,
"outputStereo": false,
"kana": ""
}
httpie では wav が扱えないようなので、PowerShell でリクエストを送ります。
# URLとJSONデータを定義
$url = 'http://localhost:50021/synthesis?speaker=3'
$jsonBody = @"
{
"accent_phrases": [
{
"moras": [
{
"text": "ズ",
"consonant": "z",
"consonant_length": 0.12722788751125336,
"vowel": "u",
"vowel_length": 0.11318323761224747,
"pitch": 5.773037910461426
},
{
"text": "ン",
"consonant": null,
"consonant_length": null,
"vowel": "N",
"vowel_length": 0.09306197613477707,
"pitch": 6.108947277069092
},
{
"text": "ダ",
"consonant": "d",
"consonant_length": 0.04249810427427292,
"vowel": "a",
"vowel_length": 0.09372275322675705,
"pitch": 6.09743070602417
},
{
"text": "モ",
"consonant": "m",
"consonant_length": 0.07012023776769638,
"vowel": "o",
"vowel_length": 0.1172478124499321,
"pitch": 5.932623386383057
},
{
"text": "ン",
"consonant": null,
"consonant_length": null,
"vowel": "N",
"vowel_length": 0.06496299058198929,
"pitch": 5.745952129364014
},
{
"text": "ナ",
"consonant": "n",
"consonant_length": 0.038462959229946136,
"vowel": "a",
"vowel_length": 0.08576127141714096,
"pitch": 5.5794854164123535
}
],
"accent": 1,
"pause_mora": null,
"is_interrogative": false
},
{
"moras": [
{
"text": "ノ",
"consonant": "n",
"consonant_length": 0.05504273623228073,
"vowel": "o",
"vowel_length": 0.0903041884303093,
"pitch": 5.551316261291504
},
{
"text": "ダ",
"consonant": "d",
"consonant_length": 0.05024997144937515,
"vowel": "a",
"vowel_length": 0.20450790226459503,
"pitch": 5.633930206298828
}
],
"accent": 2,
"pause_mora": null,
"is_interrogative": false
}
],
"speedScale": 1,
"pitchScale": 0,
"intonationScale": 1,
"volumeScale": 1,
"prePhonemeLength": 0.1,
"postPhonemeLength": 0.1,
"outputSamplingRate": 24000,
"outputStereo": false,
"kana": ""
}
"@
# HTTPヘッダーを作成
$headers = @{
'Content-Type' = 'application/json'
}
# POSTリクエストを送信し、レスポンスを取得
$response = Invoke-WebRequest -Uri $url -Method Post -Headers $headers -Body $jsonBody -OutFile "output.wav"
# 開いて再生
start output.wav
VOICEVOX: ずんだもん
以上!
fluent-listbox のスクロールを可能にする方法 (@fluentui/web-components)
0.248 (16) を 10 進数の分数にする問題の簡単な解き方 (基本情報技術者試験)
「16 進数の少数 0.248 を 10 進数の分数で表したものはどれか。」の問題について簡単に解く方法を紹介します。
ポイント
16 進数の問題は 2 進数を使う
手順
-
16 進数を 2 進数に変換
0.248(16) = 0.0010 0100 1000(2) -
小数点をなくす
0.0010 0100 1000(2) = 0.0010 0100 1000(2) × 0010 0000 0000(2) / 0010 0000 0000(2) = 0100 1001(2) / 0010 0000 0000(2) -
2 進数を 10 進数に変換
0100 1001(2) / 0010 0000 0000(2) = (64 + 8 + 1) / 512
= 73 / 512
Matplotlib (Pyplot) でよく使うコードの例
よく使うものを例としてコードとグラフを紹介します。
目次
- グラフを作成
- グラフをプロット
- タイトルの設定
- 軸ラベルの設定
- グラフの上端・下端を設定
- グラフの左端・右端を設定
- グリッドの表示
- 目盛りの設定
- 目盛りの削除
- 目盛りの色の設定
- グラフの間隔を調整
- 画像を保存
グラフを作成
まず使用するライブラリを読み込んでおきます。
import matplotlib.pyplot as plt
import numpy as np
1 つのグラフ
fig, ax = plt.subplots()

2 x 3 のグラフ
fig, axs = plt.subplots(2, 3)

グラフをプロット
放物線のプロット
x = np.linspace(-1, 1, 201)
y = x ** 2
fig, ax = plt.subplots()
ax.plot(x, y)

点で放物線をプロット
fig, ax = plt.subplots()
x = np.linspace(-1, 1, 21)
y = x ** 2
ax.plot(x, y, 'o')

色をオレンジに
fig, ax = plt.subplots()
x = np.linspace(-1, 1, 21)
y = x ** 2
ax.plot(x, y, color="tab:orange")

標準の色は以下の通り
| 色 | 文字列 |
|---|---|
| 青 | tab:blue |
| オレンジ | tab:orange |
| 緑 | tab:green |
| 赤 | tab:red |
| 紫 | tab:purple |
| 茶 | tab:brown |
| ピンク | tab:pink |
| グレー | tab:gray |
| オリーブ | tab:olive |
| シアン | tab:cyan |
線の太さを 4 に設定
fig, ax = plt.subplots()
x = np.linspace(-1, 1, 21)
y = x ** 2
ax.plot(x, y, lw=4)

タイトルの設定
タイトルを Title に設定
fig, ax = plt.subplots()
ax.set_title("Title")

軸ラベルの設定
x 軸ラベルの設定
x 軸ラベルを Time (s) に設定
fig, ax = plt.subplots()
ax.set_xlabel("Time (s)")

y 軸ラベルの設定
y 軸ラベルを Distance (m) に設定
fig, ax = plt.subplots()
ax.set_ylabel("Distance (m)")

グラフの上端・下端を設定
上端を 100 に設定
fig, ax = plt.subplots()
ax.set_ylim(top=100)

下端を -100 に設定
fig, ax = plt.subplots()
ax.set_ylim(bottom=-100)

上端を 100、下端を -100 に設定
fig, ax = plt.subplots()
ax.set_ylim([-100, 100])

グラフの左端・右端を設定
左端を -100 に設定
fig, ax = plt.subplots()
ax.set_xlim(left=-100)

右端を 100 に設定
fig, ax = plt.subplots()
ax.set_xlim(right=100)

左端を -100、右端を 100 に設定
fig, ax = plt.subplots()
ax.set_xlim([-100, 100])

グリッドの表示
fig, ax = plt.subplots()
ax.grid()

縦のみグリッドを表示
fig, ax = plt.subplots()
ax.grid(axis="x")

横のみグリッドを表示
fig, ax = plt.subplots()
ax.grid(axis="y")

目盛りの設定
x 軸目盛りの設定
fig, ax = plt.subplots()
xticks = range(6)
ax.set_xticks(xticks)

x 軸目盛と目盛りラベルの設定
fig, ax = plt.subplots()
xticks = range(6)
ax.set_xticks(xticks, [f"{xtick}m" for xtick in xticks])

y 軸目盛りの設定
fig, ax = plt.subplots()
yticks = [i * 20 for i in range(6)]
ax.set_yticks(yticks)

y 軸目盛りと目盛りラベルの設定
fig, ax = plt.subplots()
yticks = [i * 20 for i in range(6)]
ax.set_yticks(yticks, [f"{ytick}%" for ytick in yticks])

目盛りの削除
x 軸目盛りの削除
fig, ax = plt.subplots()
ax.tick_params(bottom=False)

x 軸目盛りラベルの削除
fig, ax = plt.subplots()
ax.tick_params(labelbottom=False)

y 軸目盛の削除
fig, ax = plt.subplots()
ax.tick_params(left=False)

y 軸目盛りラベルの削除
fig, ax = plt.subplots()
ax.tick_params(labelleft=False)

目盛りの色の設定
x 軸目盛りの色を赤に設定
fig, ax = plt.subplots()
ax.tick_params(axis="x", color="tab:red")

x 軸目盛りラベルの色を赤に設定
fig, ax = plt.subplots()
ax.tick_params(axis="x", labelcolor="tab:red")

y 軸目盛りの色を赤に設定
fig, ax = plt.subplots()
ax.tick_params(axis="y", color="tab:red")

y 軸目盛りラベルの色を赤に設定
fig, ax = plt.subplots()
ax.tick_params(axis="y", labelcolor="tab:red")

グラフの間隔を調整
縦の感覚を 0.2、横の間隔を 0.3 に設定
fig, ax = plt.subplots(3, 3)
fig.subplots_adjust(hspace=0.2, wspace=0.3)
%Cpu22 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

間隔を自動に設定
fig, ax = plt.subplots(3, 3)
fig.tight_layout()

画像を保存
PNG 形式で保存
fig, ax = plt.subplots()
plt.savefig("graph.png")
SVG 形式で保存
fig, ax = plt.subplots()
plt.savefig("svg.png")
PDF 形式で保存
fig, ax = plt.subplots()
plt.savefig("svg.pdf")
300 dpi で保存
fig, ax = plt.subplots()
plt.savefig("graph300.png", dpi=300)

よく使う dotnet コマンドまとめ
Linux のネットワーク管理コマンド nmcli と nmtui
nmcli
nmcli connection: すべての接続を表示
pi@raspberrypi:~ $ nmcli connection
NAME UUID TYPE DEVICE
preconfigured 1b29633c-51a7-42a8-8357-a23ddbb791b9 wifi wlan0
lo 37334688-5c87-47fc-87d3-8c4e31934dd2 loopback lo
有線接続 1 0df9157e-b1a9-3026-9bd5-f05234e1cf4b ethernet --
nmcli device: デバイスと状態を表示
pi@raspberrypi:~ $ nmcli device
DEVICE TYPE STATE CONNECTION
wlan0 wifi 接続済み preconfigured
lo loopback 接続済み (外部) lo
p2p-dev-wlan0 wifi-p2p 切断済み --
eth0 ethernet 利用不可 --
nmcli connection show ...: プロパティを表示
nmcli connection show プロファイル名 を実行し、プロパティを表示できる。
pi@raspberrypi:~ $ nmcli connection show <プロファイル名>
connection.id: <プロファイル名>
connection.uuid: 1b29633c-51a7-42a8-8357-a23ddbb791b9
connection.stable-id: --
connection.type: 802-11-wireless
connection.interface-name: --
connection.autoconnect: はい
connection.autoconnect-priority: 0
connection.autoconnect-retries: -1 (default)
connection.multi-connect: 0 (default)
connection.auth-retries: -1
connection.timestamp: 1710955164
connection.read-only: いいえ
connection.permissions: --
connection.zone: --
connection.master: --
connection.slave-type: --
connection.autoconnect-slaves: -1 (default)
connection.secondaries: --
connection.gateway-ping-timeout: 0
connection.metered: 不明
connection.lldp: default
connection.mdns: -1 (default)
connection.llmnr: -1 (default)
connection.dns-over-tls: -1 (default)
lines 1-24
IP アドレスの確認
pi@raspberrypi:~ $ nmcli connection show <プロファイル名> | grep ipv4.addresses
ipv4.addresses: 192.168.10.113/24
IP アドレスの設定
以下の例では、IP アドレスを 192.168.10.113、プレフィックス長を 24 に設定。
sudo nmcli connection modify <プロファイル名> ipv4.addresses 192.168.10.113/24
DNS サーバーの確認
pi@raspberrypi:~ $ nmcli connection show <プロファイル名> | grep ipv4.dns:
ipv4.dns: 192.168.10.1
DNS サーバーの設定
以下の例では、DNS サーバーを 192.168.10.1 に設定
sudo nmcli connection modify <プロファイル名> ipv4.dns 192.168.10.1
接続を切断
sudo nmcli connection down <プロファイル名>
接続
sudo nmcli connection up <プロファイル名>
nmtui: TUI でネットワーク接続を設定
sudo nmtui
Linux プロンプトを日本語化する方法
Linux のプロンプトを日本語化する方法を紹介します。
1. 日本語ロケールのインストール
次に、日本語のロケールが存在しない場合は、それをインストールします。以下のコマンドを実行します。
sudo apt update
sudo apt install language-pack-ja
2. ロケールの設定
日本語のロケールを設定します。以下のコマンドを実行します。
sudo update-locale LANG=ja_JP.UTF8
3. システムの再起動
最後に、システムを再起動します。これにより、新しいロケール設定が反映されます。
sudo reboot
以上で、Linux プロンプトが日本語化されます。
RaspberryPi のプロンプトを日本語化する方法
Ubuntu (WSL2 含む) に pyenv と Python をインストールする方法
依存パッケージのインストール
sudo apt update
sudo apt install build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev curl \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
Pyenv のインストール
参考: pyenv/pyenv-installer: This tool is used to install pyenv and friends.
curl https://pyenv.run | bash
~/.bashrc に初期化スクリプトを書き込む
# ~/.bashrc を開く
code ~/.bashrc
以下を書き込みます。
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
Python のインストール
インストール可能なバージョン一覧を表示
pyenv install -l
Python のインストール
Python 3.12.2 をインストールします。
pyenv install 3.12.2
Python のバージョンを指定
デフォルトのバージョンを Python 3.12.2 に設定します。
pyenv global 3.12.2
python -V # Python 3.12.2

