今日は台風が近付いているようで雨がよく降る。近くの川は、この雨の影響で氾濫するかもしれないらしい。この部屋は大雨が降ると雨漏りするため、天井から水が落ちてきている。いろんな枝葉の事を無視して、目標に対して取り組んできた。だから雨漏りぐらいはする。いつか雨漏りしない部屋に住んでみたい。確か、遠方にいる仲間達の住む土地にも近くに川がある。皆が元気でやっているのか、少し心配だ。ただ向こうには敵がいるから、そいつらは全員洪水で流されればいいなと思う。
speech2speeh
wavファイルから音声データを取得する
音声データの取得はsounddeviceで取得するが、検証時にはファイルから読み出した方が楽な事がある。そのためファイルから入力と同じ形式のデータを取得できるようにした。
もしかすると、型は少し異なるかもしれない。
音声データを取得する
音声データはsounddevice経由で取得する。
import sounddevice
import numpy as np
SAMPLING_RATE = 16000
WINDOW_SIZE_SAMPLES = 512
def callback_sound(indata: np.ndarray[np.ndarray[np.int16]],
outdata, frames, time, status):
pass
with sounddevice.Stream(samplerate=SAMPLING_RATE, dtype="int16",
channels=1, blocksize=WINDOW_SIZE_SAMPLES,
callback=callback_sound):
while True:
time.sleep(0.01)
元々はFFmpegを使って標準入出力で受け渡しをしていたが、データを処理しずらいため、この実装に変更した。
ノイズリダクション
発話検出
import numpy as np
import torch
vad_model, utils = torch.hub.load("snakers4/silero-vad", "silero_vad")
(get_speech_timestamps,
save_audio,
read_audio,
VADIterator,
collect_chunks) = utils
vad_model.reset_states()
sound_data = torch.Tensor(wav_data)
window_size = 512 # Sampling rateが16000の場合512
chunk = sound_data[0:window_size] # 検出したい箇所を切り出す
ret = vad_model(chunk, sampling_rate)
speech_prob = ret.item() # 閾値よりも大きな数字であれば発話と見做す
if speech_prob > 0.5: # 発話検出の閾値。ここは自分で調整 (例: 0.5)
print("発話中")
else:
print("発話なし")
文字起こし
from reazonspeech.nemo.asr.audio import audio_from_tensor, audio_from_numpy
from nemo.collections.asr.models import EncDecRNNTBPEModel
from reazonspeech.nemo.asr.interface import AudioData
from reazonspeech.nemo.asr.transcribe import transcribe
rez_model = EncDecRNNTBPEModel.from_pretrained(
'reazon-research/reazonspeech-nemo-v2',
map_location="cpu")
audio: AudioData = audio_from_numpy(wav_data, sampling_rate)
ret = transcribe(rez_model, audio)
text = "".join(sg.text for sg in ret.segments)
print(text)
回答生成
from mlx_lm import load, generate
model, tokenizer = load("mlx-community/Llama-3-Swallow-8B-Instruct-v0.1-8bit")
response = generate(model, tokenizer, prompt="hello", verbose=True)
print(response)
テキストを音声データに変換する
import sounddevice
import numpy as np
import melo.api
sentence = "こんにちわ"
model = melo.api.TTS(language="JP", device="mps")
print(model.hps.data.spk2id)
audio_chunk = model.tts_to_file(sentence, model.hps.data.spk2id["JP"], quiet=True)
audio_chunk2 = librosa.resample(audio_chunk, orig_sr=44100, target_sr=16000)
audio_chunk3 = (audio_chunk2 * 32768).astype(np.int16)
sounddevice.play(audio_chunk3, 12100)
音を出す
import sounddevice as sd
import numpy as np
samplerate = 44100 # サンプリングレートの設定
duration = 2.0 # 秒数
frequency = 440.0 # 再生する音の周波数
# サイン波を生成
t = np.linspace(0, duration, int(samplerate * duration), endpoint=False)
waveform = 0.5 * np.sin(2 * np.pi * frequency * t)
def callback(outdata, frames, time, status):
# デフォルトでは np.int16 形式でデータを渡す
outdata[:] = (waveform[:frames] * 32767).astype(np.int16).tostring()
# RawOutputStreamを使用してデータをストリーミング
with sd.RawOutputStream(samplerate=samplerate, channels=1, dtype='int16', callback=callback):
# duration秒間のデータをストリーミング
sd.sleep(int(duration * 1000))