การตรวจจับเสียงพูดและบันทึกเป็นไฟล์เสียง
การจะพูดคุยกับผู้ใช้งานได้นั้นเราจำเป็นต้องฟังผู้ใช้งานให้รู้เรื่องเสียก่อนว่าผู้ใช้งาน ต้องการอะไรจากเรา เราจึงจะสามารถตอบคำถาม พูดคุยหรือทำตามคำสั่งผู้ใช้งานได้ และนั่นทำให้เราจึงจำเป็นต้องมีการตรวจจับเสียงพูด โดย เราจะใช้ Pyaudio ซึางเป็น Library สำหรับภาษา Python ที่ต้องนำมาอัดเสียงผู้ใช่้งานว่ากำลังพูดอะไร โดยจะเก็บเป็นไฟล์นามสกุล .wav
Pyaudio
การติดตั้ง Pyaudio
ในการติดตั้งบน Raspberry pi เราจะใช้คำสั่ง
pip install PyAudio
Version ที่ใช้งานในขณะนั้นคือ V.0.2.11
การบันทึกเป็นไฟล์เสียง
จากตัวอย่างโค้ดด้านล่างจะเห็นได้ว่าได้ทำการทดลองบันทึกเสียง 5 วินาที และบันทึกเป็นไฟล์เสียง output.wav หากต้องบันทึกไฟล์เสียงการมากกว่า 5 วินาที สามารถปรับได้ที่ RECORD_SECONDS
import pyaudio
import wave
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("* recording")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("* done recording")
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
ตรวจจับเสียงพูด
เพื่อจะใช้การจับเสียงพูดแท่นการตั้งเวลาในการอัดเสียง โดยใช้ Library numpy ในการคำนวณหาค่าสูงสุดเพื่อหาค่าของเลเวลของเสียงแล้วนำมาใช้ในการจับเสียงพูด
ตัวอย่าง
import math, numpy as np
data = stream.read(CHUNK, exception_on_overflow=False)
data_conv = np.fromstring(data, dtype=np.int16)
max = np.max(data_conv)
frames.append(data)
เมื่อนำโค้ดรวมเข้าด้วยกันจะได้ดั่งนี้
ตัวอย่าง
import pyaudio
import wave
import math, numpy as np
import time
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE =48000
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
STATE ="start"
frames = []
t = float(0)
t1 = float(0)
while True:
data = stream.read(CHUNK, exception_on_overflow=False)
data_conv = np.fromstring(data, dtype=np.int16)
max = np.max(data_conv)
frames.append(data)
if STATE == "start":
frames = []
t = time.time()
STATE = "rec"
elif time.time()-t > float(3) and STATE == "rec" and max < 7000:
STATE = "start"
elif max => 7000 :
STATE = "wait"
elif STATE =="wait" and max<7000:
t1 = time.time()
STATE = "save"
elif max < 7000 and STATE =="save" and time.time()-t1 > float(1) :
STATE = "start"
wf = wave.open('output.wav', 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
stream.stop_stream()
stream.close()
p.terminate()
1. if จะเข้ามาทำก็ต่อเมื่อ STATE == “start” จะเริ่มเก็บ frames, เริ่มจำเวลา และจะเปลี่ยนค่าใน STATE จาก STATE = “start” เป็น STATE = “rec”
if STATE == "start":
frames = []
t = time.time()
STATE = "rec"
2. elif ตัวแรกจะเข้ามาทำก็ต่อเมื่อ time.time()-t มากกว่า 3 และ STATE == “rec” และ max น้อยกว่า 7000 เมื่อเข้ามาทำใน elif จะเปลี่ยนค่าใน STATE จาก STATE = “rec” เป็น STATE = “start”
elif time.time()-t > float(3) and STATE == "rec" and max < 7000:
STATE = "start"
3. elif ตัวที่สองจะเข้ามาทำก็ต่อเมื่อ max มีค่ามากกว่าหรือเท่ากับ 7000 เมื่อเข้ามาทำใน elif จะเปลี่ยนค่าใน STATE จาก STATE = “start” เป็น STATE = “wait”
elif max => 7000 :
STATE = "wait"
4. elif ตัวที่สามจะเข้ามาทำก็ต่อเมื่อ STATE == “wait” และ max มีค่าน้อยกว่า 7000 เมื่อเข้ามาทำใน elif เริ่มจับเวลา t1 และเปลี่ยนค่าใน STATE จาก STATE = “wait” เป็น STATE = “save”
elif STATE =="wait" and max<7000:
t1 = time.time()
STATE = "save"
5. elif ตัวที่สี่จะเข้ามาทำก็ต่อเมื่อ max มีค่าน้อยกว่า 7000 และ STATE == “save” และ time.time()-t1 มากกว่า 3 เมื่อเข้ามาทำใน elif จะเปลี่ยนค่าใน STATE จาก STATE = “save” เป็น STATE = “start” และบันทึกเป็นไฟล์เสียง output.wav
elif max < 7000 and STATE =="save" and time.time()-t1 > float(1) :
STATE = "start"
wf = wave.open('output.wav', 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))