python - pyaudio - "Listen"直到检测到语音然后录制到 .wav 文件

标签 python multithreading audio pyaudio

我遇到了一些问题,我似乎无法理解这个概念。

我想做的是:

让麦克风“收听”语音(高于特定阈值),然后开始录制到 .wav 文件,直到此人停止说话/信号不再存在。例如:

begin:
   listen() -> nothing is being said
   listen() -> nothing is being said
   listen() -> VOICED - _BEGIN RECORDING_
   listen() -> VOICED - _BEGIN RECORDING_
   listen() -> UNVOICED - _END RECORDING_
end

我也想使用“线程”来做到这一点,因此将创建一个线程来不断“监听”文件,并且,当有语音数据时,另一个线程将开始。但是,我一辈子都做不到弄清楚我应该怎么做。这是我目前的代码:

import wave
import sys
import threading
from array import array
from sys import byteorder

try:
    import pyaudio
    CHECK_PYLIB = True
except ImportError:
    CHECK_PYLIB = False

class Audio:
    _chunk = 0.0
    _format = 0.0
    _channels = 0.0
    _rate = 0.0
    record_for = 0.0
    stream = None

    p = None

    sample_width = None
    THRESHOLD = 500

    # initial constructor to accept params
    def __init__(self, chunk, format, channels, rate):
        #### set data-types

        self._chunk = chunk
        self.format = pyaudio.paInt16,
        self.channels = channels
        self.rate = rate

        self.p = pyaudio.PyAudio();

   def open(self):
       # print "opened"
       self.stream = self.p.open(format=pyaudio.paInt16,
                                 channels=2,
                                 rate=44100,
                                 input=True,
                                 frames_per_buffer=1024);
       return True

   def record(self):
       # create a new instance/thread to record the sound
       threading.Thread(target=self.listen).start();

   def is_silence(snd_data):
       return max(snd_data) < THRESHOLD

   def listen(self):
       r = array('h')

       while True:
           snd_data = array('h', self.stream.read(self._chunk))

           if byteorder == 'big':
               snd_data.byteswap()
           r.extend(snd_data)

       return sample_width, r

我猜我可以录制“5”秒的 block ,然后如果该 block 被视为“有声”,那么线程应该启动,直到所有语音数据都被捕获。但是,因为目前它处于 while True: 我不想在有语音命令之前捕获所有音频,所以例如"no voice", "no voice", "voice", "voice", "no voice", "no voice"我只想要 wav 文件中的 "voice".. 任何人有什么建议吗?

谢谢

编辑:

import wave
import sys
import time 
import threading 
from array import array
from sys import byteorder
from Queue import Queue, Full

import pyaudio 

CHUNK_SIZE = 1024
MIN_VOLUME = 500

BUF_MAX_SIZE = 1024 * 10 

process_g = 0 

def main():

stopped = threading.Event()

q = Queue(maxsize=int(round(BUF_MAX_SIZE / CHUNK_SIZE)))

listen_t = threading.Thread(target=listen, args=(stopped, q))

listen_t.start()

process_g = threading.Thread(target=process, args=(stopped, q))

process_g.start()

try:

    while True:
        listen_t.join(0.1)
        process_g.join(0.1)
except KeyboardInterrupt:
        stopped.set()

listen_t.join()
process_g.join()

  def process(stopped, q):

  while True:
    if stopped.wait(timeout = 0):
        break
    print "I'm processing.."
    time.sleep(300)

   def listen(stopped, q):

   stream = pyaudio.PyAudio().open(
        format = pyaudio.paInt16,
        channels = 2,
        rate = 44100,
        input = True,
        frames_per_buffer = 1024    
            )

     while True:

      if stopped and stopped.wait(timeout=0):
          break
      try:
        print process_g
        for i in range(0, int(44100 / 1024 * 5)):
            data_chunk = array('h', stream.read(CHUNK_SIZE))
            vol = max(data_chunk)
            if(vol >= MIN_VOLUME):
                print "WORDS.."
            else:
                print "Nothing.."

        except Full:
                pass 

    if __name__ == '__main__':
    main()

现在,每 5 秒后,我需要执行“处理”函数,然后处理数据 (time.delay(10),同时执行此操作,然后开始备份备份..

最佳答案

花了一些时间,我想出了以下代码,除了写入文件外,它们似乎可以满足您的需求:

import threading
from array import array
from Queue import Queue, Full

import pyaudio


CHUNK_SIZE = 1024
MIN_VOLUME = 500
# if the recording thread can't consume fast enough, the listener will start discarding
BUF_MAX_SIZE = CHUNK_SIZE * 10


def main():
    stopped = threading.Event()
    q = Queue(maxsize=int(round(BUF_MAX_SIZE / CHUNK_SIZE)))

    listen_t = threading.Thread(target=listen, args=(stopped, q))
    listen_t.start()
    record_t = threading.Thread(target=record, args=(stopped, q))
    record_t.start()

    try:
        while True:
            listen_t.join(0.1)
            record_t.join(0.1)
    except KeyboardInterrupt:
        stopped.set()

    listen_t.join()
    record_t.join()


def record(stopped, q):
    while True:
        if stopped.wait(timeout=0):
            break
        chunk = q.get()
        vol = max(chunk)
        if vol >= MIN_VOLUME:
            # TODO: write to file
            print "O",
        else:
            print "-",


def listen(stopped, q):
    stream = pyaudio.PyAudio().open(
        format=pyaudio.paInt16,
        channels=2,
        rate=44100,
        input=True,
        frames_per_buffer=1024,
    )

    while True:
        if stopped.wait(timeout=0):
            break
        try:
            q.put(array('h', stream.read(CHUNK_SIZE)))
        except Full:
            pass  # discard


if __name__ == '__main__':
    main()

关于python - pyaudio - "Listen"直到检测到语音然后录制到 .wav 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19070290/

相关文章:

java - 确定麦克风声音的幅度

javascript - 单击按钮时播放音频,然后停止,单击其他按钮时播放新音频

python - 如何从我们正在爬取的网页上的链接网页中爬取数据

java - 音频播放速度太快

python - 从数据样本计算逆 CDF

java - Java:ConcurrentListModel-试图绕过Swing线程安全规则,我是否陷入困境或发疯

java - Apache Thrift 在不同线程中重用连接

java - 为什么线程仍然不一致?

python - Pandas : Cumulative sum with moving window (following and preceding rows)

python - 将多个过滤器应用于 pandas DataFrame 或 Series 的有效方法