demo
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.wav
|
||||
112
main.py
Normal file
112
main.py
Normal file
@@ -0,0 +1,112 @@
|
||||
import io
|
||||
import queue
|
||||
import threading
|
||||
import time
|
||||
import wave
|
||||
|
||||
|
||||
class SipCall:
|
||||
_queue: queue.Queue
|
||||
_file_path: str
|
||||
|
||||
def __init__(self, file_path) -> None:
|
||||
self._file_path = file_path
|
||||
self._queue = queue.Queue()
|
||||
with wave.open(file_path, "rb") as f:
|
||||
self._channels = f.getnchannels()
|
||||
self._sampwidth = f.getsampwidth()
|
||||
self._framerate = f.getframerate()
|
||||
|
||||
def wave_to_queue(self, chunk_size=4096, sleep=0.1):
|
||||
while True:
|
||||
with wave.open(self._file_path, "rb") as f:
|
||||
while True:
|
||||
frames = f.readframes(chunk_size)
|
||||
if not frames:
|
||||
break
|
||||
|
||||
self._queue.put_nowait(frames)
|
||||
time.sleep(sleep)
|
||||
|
||||
def process_recorded_audio(self, iters=10000):
|
||||
audio_bytes = bytearray()
|
||||
for _ in range(iters):
|
||||
try:
|
||||
if frame := self._queue.get_nowait():
|
||||
audio_bytes.extend(frame)
|
||||
except:
|
||||
break
|
||||
|
||||
return audio_bytes
|
||||
|
||||
|
||||
def get_audio(call: SipCall, buff: io.BytesIO):
|
||||
while True:
|
||||
if audio_bytes := call.process_recorded_audio():
|
||||
buff.write(audio_bytes)
|
||||
|
||||
|
||||
def get_audio_duration_seconds(call: SipCall, audio_data: bytes):
|
||||
num_frames = len(audio_data) // (call._channels * call._sampwidth)
|
||||
return num_frames / float(call._framerate)
|
||||
|
||||
|
||||
def read_audio_by_range(call: SipCall, buff: io.BytesIO, start_seconds, end_seconds):
|
||||
audio_data = buff.getvalue()
|
||||
num_frames = len(audio_data) // (call._channels * call._sampwidth)
|
||||
start_frame = max(0, start_seconds * call._framerate)
|
||||
end_frame = min(num_frames, end_seconds * call._framerate)
|
||||
start_byte = start_frame * call._channels * call._sampwidth
|
||||
end_byte = end_frame * call._channels * call._sampwidth
|
||||
frames = audio_data[start_byte:end_byte]
|
||||
print("read_audio_by_range duration ", get_audio_duration_seconds(call, frames))
|
||||
return frames
|
||||
|
||||
|
||||
def read_audio_by_last(call: SipCall, buff: io.BytesIO, last_seconds):
|
||||
audio_data = buff.getvalue()
|
||||
num_frames = len(audio_data) // (call._channels * call._sampwidth)
|
||||
start_frame = max(0, num_frames - last_seconds * call._framerate)
|
||||
start_byte = start_frame * call._channels * call._sampwidth
|
||||
frames = audio_data[start_byte:]
|
||||
print("read_audio_by_last duration ", get_audio_duration_seconds(call, frames))
|
||||
return frames
|
||||
|
||||
|
||||
def audio_to_text(call: SipCall, audio_buff: io.BytesIO):
|
||||
# тут логика нарезиния кусочков аудио и отправки на распознавание
|
||||
# получение из audio_buff не блокирует выполнение
|
||||
# как именно возвращать текст не придумал, но тоже не блокируя нужно
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
call = SipCall("voice.wav")
|
||||
audio_buff = io.BytesIO()
|
||||
t1 = threading.Thread(target=call.wave_to_queue, args=(4096, 0.1))
|
||||
t2 = threading.Thread(target=get_audio, args=(call, audio_buff))
|
||||
t3 = threading.Thread(target=audio_to_text, args=(call, audio_buff))
|
||||
t1.start()
|
||||
t2.start()
|
||||
t3.start()
|
||||
time.sleep(7)
|
||||
|
||||
frames = read_audio_by_last(call, audio_buff, 3)
|
||||
with wave.open("read_audio_by_last.wav", "wb") as wf:
|
||||
wf.setnchannels(call._channels)
|
||||
wf.setsampwidth(call._sampwidth)
|
||||
wf.setframerate(call._framerate)
|
||||
wf.writeframes(frames)
|
||||
|
||||
frames = read_audio_by_range(call, audio_buff, 1, 7)
|
||||
with wave.open("read_audio_by_range.wav", "wb") as wf:
|
||||
wf.setnchannels(call._channels)
|
||||
wf.setsampwidth(call._sampwidth)
|
||||
wf.setframerate(call._framerate)
|
||||
wf.writeframes(frames)
|
||||
|
||||
print("CTRL+C to exit")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user