2026-02-16


ボイスチェンジャーを使ってみたいと1度は考えるもその性能の悪さにあきらめる人も多いのではないか。自分もそう。
しかし、しゃべる→テキスト化→テキストをボーカロイドに読ませる、のルートであれば、現実的に質の良いボイスチェンジができるのだ。
一番重要なのが、しゃべる→テキスト化のところ。ここの質が悪いと意味がない。ここはOpenAIのSpeech-to-Textが最も正しい選択。
https://developers.openai.com/api/docs/guides/speech-to-text/
今回はWindows10マシンにUSBマイクをつなげて、しゃべったデータをgpt-4o-mini-transcribeモデルに投げて得たテキストをライブ配信用OBS StudioのCaptionソースに表示する。
準備
・OpenAIにAPIクレジットチャージを何ドルか行い、OPENAI_API_KEYを取得し環境変数に入れる。Windowsだとコントロールパネル→システムとセキュリティ→システム→システムの詳細設定→環境変数、にて、OPENAI_API_KEYを設定。コマンドプロンプトを開いて「set」と入力してそれが一覧に出てくればOK。
・OBS Studio
ツール → WebSocketサーバ設定→「WebSocketサーバを有効化」ON
パスワード設定(例: yourpass)
ポート(通常 4455)
シーンにCaptionソースを作成する
テキスト(GDI+) ソース
名前:Caption(この名前をコードで使います)
・Python for Windowsのインストール
https://www.python.org/downloads/windows/
コマンドプロンプトを開いて、仮想環境を作成し有効化する
python -m venv venv cd venv/Scripts activate
必要モジュールのインストール
(venv) pip install openai sounddevice soundfile numpy requests obsws-python
実行
以下のコードによって、マイクでしゃべるとOBSの画面にテキストで表示される。
| Python | live_whisper_to_obs_caption.py | GitHub Source |
import io, time, queue
import numpy as np
import sounddevice as sd
import soundfile as sf
from openai import OpenAI
from obsws_python import ReqClient
# === OpenAI ===
client = OpenAI() # OPENAI_API_KEY を環境変数に入れておく
MODEL = "gpt-4o-mini-transcribe"
LANG = "ja"
# === OBS websocket ===
OBS_HOST="127.0.0.1"; OBS_PORT=4455; OBS_PASS="yourpass"
TEXT_SOURCE="Caption"
obs = ReqClient(host=OBS_HOST, port=OBS_PORT, password=OBS_PASS)
# === Audio ===
SR = 16000
CHANNELS = 1
BLOCK_SEC = 0.25 # 0.25秒ごとに音声を受け取る
SILENCE_SEC = 1.1 # これだけ無音が続いたら「区切り」
MIN_SPEECH_SEC = 2.2 # これ未満の短い発話は送らない(切れ防止)
MAX_UTTER_SEC = 25.0 # 1発の最大長(無限に溜めない)
SILENCE_THRESHOLD = 0.012 # 無音判定(環境で調整)
def rms(x: np.ndarray) -> float:
return float(np.sqrt(np.mean(np.square(x)) + 1e-12))
def stt_openai(wav_bytes: bytes) -> str:
bio = io.BytesIO(wav_bytes)
bio.name = "audio.wav"
t = client.audio.transcriptions.create(
model=MODEL,
file=bio,
language=LANG,
# prompt="駅名・路線名・地名が出ます。固有名詞はカタカナ/漢字で。" # 任意
)
return (t.text or "").strip()
def obs_set_text(text: str):
obs.set_input_settings(
name=TEXT_SOURCE,
settings={"text": text},
overlay=True
)
def main():
blocksize = int(SR * BLOCK_SEC)
q = queue.Queue()
def callback(indata, frames, time_info, status):
if status:
print("Audio status:", status)
q.put(indata.copy())
silence_blocks_needed = int(SILENCE_SEC / BLOCK_SEC)
max_blocks = int(MAX_UTTER_SEC / BLOCK_SEC)
print("Ready. Speak. (Ctrl+C to stop)")
with sd.InputStream(
samplerate=SR,
channels=CHANNELS,
dtype="float32",
blocksize=blocksize,
callback=callback,
):
buf = []
silent = 0
started = False
while True:
try:
data = q.get(timeout=0.5)
except queue.Empty:
continue
x = data.reshape(-1)
level = rms(x)
if level > SILENCE_THRESHOLD:
started = True
silent = 0
buf.append(x)
else:
if started:
silent += 1
buf.append(x) # 少し無音を入れると自然
# バッファが長くなりすぎたら強制区切り
if started and len(buf) >= max_blocks:
silent = silence_blocks_needed
# 無音が一定続いたら「確定」
if started and silent >= silence_blocks_needed:
audio = np.concatenate(buf) if buf else np.array([], dtype=np.float32)
buf, silent, started = [], 0, False
duration = len(audio) / SR
if duration < MIN_SPEECH_SEC:
# 短すぎるので捨てる(ブツ切れ防止)
continue
# WAV化(メモリ上)
bio = io.BytesIO()
sf.write(bio, audio, SR, format="WAV")
wav_bytes = bio.getvalue()
text = stt_openai(wav_bytes)
if text:
print("STT:", text)
obs_set_text(text)
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\nStopped.")
(venv) python live_whisper_to_obs_caption.py
OpenAI APIはデータ従量課金であるので、このように使用したらこまめに課金画面をチェックしておかないといけない。
https://platform.openai.com/settings/organization/billing/overview
※本記事内容の無断転載を禁じます。
ご連絡は以下アドレスまでお願いします★
マイクで喋った日本語をテキスト変換してOBS Studioにリアルタイムで表示する【1】
Raspberry PI 2 bookworm 32bitでCanon IP4300プリンタ印刷する
【VMware】Apple silicon M2 MacでWindows11を無償で動かす
A4用紙タテ2ページ分をA3用紙ヨコ1ページに印刷するには
【Android】apkのインストールができたのにアプリ一覧に出ない場合
【Node.js】chrono-nodeを使用して自然言語を日付に変換する
CUDA13環境下でGPU使用版のllama.cppを導入しC++ライブラリを使う
CUDA13環境下でGPU使用版のllama-cpp-pythonを導入する
CUDA13環境下でGPU使用版のPyTorchを導入する
進研ゼミチャレンジタッチをAndroid端末化する
CUDA13環境下でGPU使用版のPyTorchを導入する
Windows11+WSL2でUbuntuを使う【2】ブリッジ接続+固定IPの設定
LinuxからWindowsの共有フォルダをマウントする
VirtualBoxの仮想マシンをWindows起動時に自動起動し終了時に自動サスペンドする
【Debian】古いバージョンでapt updateしたら404 not foundでエラーになる場合
【PHP】Mail/mimeDecodeを使ってメールの中身を解析(準備編)
【ウマ娘】「円弧のマエストロ」スキルを取得するには
【Apache】サーバーに同時接続可能なクライアント数を調整する