Как я могу в режиме реального времени обнаруживать голосовую активность в Python? - PullRequest
4 голосов
/ 24 марта 2020

Я выполняю обнаружение голосовой активности на записанном аудиофайле, чтобы обнаружить речь по сравнению с неречевыми частями в форме волны.

Выходной сигнал классификатора выглядит следующим образом (выделенные зеленые области обозначают речь):

enter image description here

Единственная проблема, с которой я здесь сталкиваюсь, - заставить его работать для потока аудиовхода (например, с микрофона) и выполнять анализ в реальном времени для оговоренный период времени.

Я знаю, PyAudio может использоваться для динамической записи речи с микрофона, и есть несколько примеров визуализации в реальном времени формы сигнала, спектра, спектрограммы и т. д. c, но не смог найти ничего подходящего для выполнения извлечения признаков практически в режиме реального времени.

Ответы [ 4 ]

2 голосов
/ 31 марта 2020

Вы должны попробовать использовать Python привязки к webRT C VAD от Google . Это легкий, быстрый и очень разумный результат, основанный на моделировании GMM. Поскольку решение предоставляется для каждого кадра, задержка минимальна.

# Run the VAD on 10 ms of silence. The result should be False.
import webrtcvad
vad = webrtcvad.Vad(2)

sample_rate = 16000
frame_duration = 10  # ms
frame = b'\x00\x00' * int(sample_rate * frame_duration / 1000)
print('Contains speech: %s' % (vad.is_speech(frame, sample_rate))

Кроме того, эта статья может быть полезна для вас.

2 голосов
/ 24 марта 2020

Аудио обычно имеет низкую скорость передачи данных, поэтому я не вижу проблем с полным написанием вашего кода в numpy и python. А если вам нужен низкоуровневый доступ к массиву, рассмотрите numba. Также укажите свой код, например, с помощью line_profiler. Также обратите внимание, что для более сложной обработки сигналов есть scipy.signal.

Обычно обработка аудио работает в сэмплах. Таким образом, вы определяете размер выборки для вашего процесса, а затем запускаете метод, чтобы решить, содержит ли этот образец речь или нет.

import numpy as np

def main_loop():
    stream = <create stream with your audio library>
    while True:
        sample = stream.readframes(<define number of samples / time to read>)
        print(is_speech(sample))

def is_speech(sample):
    audio = np.array(sample)

    < do you processing >

    # e.g. simple loudness test
    return np.any(audio > 0.8):

Это должно вас довольно далеко.

1 голос
/ 03 апреля 2020

Я узнал, что LibROSA может быть одним из решений вашей проблемы. На Medium есть простое руководство по использованию потоковой передачи с микрофона для реализации прогнозирования в реальном времени.

Давайте использовать кратковременное преобразование Фурье (STFT) в качестве экстрактора функций, поясняет автор:

Для расчета STFT, размер окна быстрого преобразования Фурье (n_fft) используется как 512. Согласно уравнению n_stft = n_fft / 2 + 1, 257 частотных бинов (n_stft) вычисляются для размера окна 512 . Окно перемещается на длину скачка 256, чтобы иметь лучшее перекрытие windows при расчете STFT.

stft = np.abs(librosa.stft(trimmed, n_fft=512, hop_length=256, win_length=512))

# Plot audio with zoomed in y axis
def plotAudio(output):
    fig, ax = plt.subplots(nrows=1,ncols=1, figsize=(20,10))
    plt.plot(output, color='blue')
    ax.set_xlim((0, len(output)))
    ax.margins(2, -0.1)
    plt.show()

# Plot audio
def plotAudio2(output):
    fig, ax = plt.subplots(nrows=1,ncols=1, figsize=(20,4))
    plt.plot(output, color='blue')
    ax.set_xlim((0, len(output)))
    plt.show()

def minMaxNormalize(arr):
    mn = np.min(arr)
    mx = np.max(arr)
    return (arr-mn)/(mx-mn)

def predictSound(X):
    clip, index = librosa.effects.trim(X, top_db=20, frame_length=512, hop_length=64) # Empherically select top_db for every sample
    stfts = np.abs(librosa.stft(clip, n_fft=512, hop_length=256, win_length=512))
    stfts = np.mean(stfts,axis=1)
    stfts = minMaxNormalize(stfts)
    result = model.predict(np.array([stfts]))
    predictions = [np.argmax(y) for y in result]
    print(lb.inverse_transform([predictions[0]])[0])
    plotAudio2(clip)

CHUNKSIZE = 22050 # fixed chunk size
RATE = 22050

p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paFloat32, channels=1, 
rate=RATE, input=True, frames_per_buffer=CHUNKSIZE)

#preprocessing the noise around
#noise window
data = stream.read(10000)
noise_sample = np.frombuffer(data, dtype=np.float32)
print("Noise Sample")
plotAudio2(noise_sample)
loud_threshold = np.mean(np.abs(noise_sample)) * 10
print("Loud threshold", loud_threshold)
audio_buffer = []
near = 0

while(True):
    # Read chunk and load it into numpy array.
    data = stream.read(CHUNKSIZE)
    current_window = np.frombuffer(data, dtype=np.float32)

    #Reduce noise real-time
    current_window = nr.reduce_noise(audio_clip=current_window, noise_clip=noise_sample, verbose=False)

    if(audio_buffer==[]):
        audio_buffer = current_window
    else:
        if(np.mean(np.abs(current_window))<loud_threshold):
            print("Inside silence reign")
            if(near<10):
                audio_buffer = np.concatenate((audio_buffer,current_window))
                near += 1
            else:
                predictSound(np.array(audio_buffer))
                audio_buffer = []
                near
        else:
            print("Inside loud reign")
            near = 0
            audio_buffer = np.concatenate((audio_buffer,current_window))

# close stream
stream.stop_stream()
stream.close()
p.terminate()

Код кредита для : Чатуранга Сиривардхана

Полный код можно найти здесь .

1 голос
/ 28 марта 2020

Я думаю, что здесь есть два подхода:

  1. Пороговый подход
  2. Маленький, развертываемый, нейронный net. Подход

Первый - быстрый, выполнимый , может быть реализован и проверен очень быстро . в то время как второй немного сложнее реализовать. Я думаю, что вы уже немного знакомы со вторым вариантом.

В случае второго подхода вам понадобится набор данных речей, помеченных в последовательности двоичной классификации 00000000111111110000000011110000. Нейронный net должен быть небольшим и оптимизирован для работы на периферийных устройствах, таких как мобильные.

Вы можете проверить этот из TensorFlow

Этот является детектором голосовой активности. Я думаю, что это для вашей цели.

Кроме того, проверьте это.

https://github.com/eesungkim/Voice_Activity_Detector

https://github.com/pyannote/pyannote-audio

конечно, вам следует сравнить производительность упомянутых наборов инструментов и моделей и осуществимость реализации мобильных устройств.

...