2013-09-28 3 views
2

У меня возникли проблемы, и я, похоже, не понимаю, как это выглядит.pyaudio - «Слушайте» до тех пор, пока не будет обнаружен голос, а затем запишите в .wav-файл.

То, что я пытаюсь сделать это:

У микрофона «слушать» для голоса (выше определенного порогового значения), а затем начать запись в файл .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» второй блоки, а затем, если блок считается «озвученным», тогда поток должен запускаться до тех пор, пока все голосовые данные не будут захвачены. Однако, поскольку при текущем значении while True: я не хочу захватывать весь звук до тех пор, пока не будут озвучены команды, так, например, «нет голоса», «нет голоса», «голос», «голос», «нет голоса», «нет голоса», я просто хочу «голос» внутри wav-файла. У кого-нибудь есть предложения?

Спасибо

EDIT:

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) в то время как ему делает это, а затем запускает запись обратно ..

+1

Чтение http://www.python.org/dev/peps/pep-0008/ настоятельно рекомендуется :) –

+0

Вопрос: Вы действительно когда-либо создавали несколько объектов 'Audio'? Я спрашиваю, потому что я не совсем понимаю, почему вы помещаете свой код в класс - я получаю Java-for-beginners * deja vu *, где они всегда требуют, чтобы все было сделано OO только ради этого. –

+0

@ErikAllik Должен признаться, я новичок в Python :( – Phorce

ответ

5

Посмотрите здесь:

https://github.com/jeysonmc/python-google-speech-scripts/blob/master/stt_google.py

Он даже преобразует Wav в FLAC и отправляет его на API Google Speech, просто удалите функцию stt_google_wav, если вам не нужно это;)

+2

Это правильная идея, но обратите внимание, что метод обнаружения, который он использует, довольно примитивен. Он просто проверяет интенсивность микрофона и предполагает, что кто-то говорит, если есть достаточный шум. На практике речь работает в определенном диапазоне частот, поэтому код будет иметь много ложных срабатываний в любой среде с небольшим шумом. Лучшим решением было бы использовать БПФ и начать запись, если сигнал обнаружен в [диапазоне частот голоса] (http://en.wikipedia.org/wiki/Voice_frequency). – Cerin

+0

@Cerin и измерьте спектральную плоскость звука, чтобы узнать, озвучен ли он или шум – endolith

4

Проведя некоторое время на этом, я придумал следующий код, который, кажется, делает то, что вам нужно. Конечно, это не письмо аудиоданные в файл .wav (или эквивалентный), но вы можете реализовать это сами:

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() 
+1

Спасибо за ваш ответ. Я использовал код, который вы мне дали, но мои обстоятельства изменились, и я попытался его реализовать. (См. Мое обновление выше ^^). Я просто не могу понять, как выполнить «process()» через каждые 10 секунд, завершить обработку и затем начать запись снова. Любые предложения? Спасибо за это! – Phorce

+1

Во-первых, я ответил на ваш первоначальный вопрос; во-вторых, я не совсем понимаю, каковы ваши изменившиеся обстоятельства, потому что вы не описали их очень четко. Даже код, который вы вставили, сломан, потому что вы не нашли времени для исправления отступа/форматирования. –

+1

На самом деле, я понятия не имею, что вы сделали с моим оригинальным фрагментом - вы полностью испортили его. Я думаю, вы должны прочитать книгу Python/Programming для начинающих или что-то в этом роде. –

Смежные вопросы