Как я могу воспроизводить двоичные данные wav с помощью pyaudio?

Я получаю двоичные аудиоданные из веб-запроса, и я хотел бы передать эти данные и немедленно воспроизвести их через динамики. Как я могу это сделать? В настоящее время я получаю ошибки, связанные со свойствами .wav, такими как количество неуказанных каналов, ширина выборки и т. д. Я не хочу записывать его в файл .wav, а затем загружать файл и воспроизводить его. Я хотел бы перейти от двоичных аудиоданных -> к воспроизведению на динамиках, возможно, я иду в неправильном направлении, чтобы решить эту проблему, но любая помощь будет оценена по достоинству. Я предполагаю, что должен быть какой-то способ передать эти данные в аудиопоток, и я просто не знаю, как это сделать.

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

wav = wave.open(response.audio_content, 'wb')
pa = pyaudio.PyAudio()
audio_stream = pa.open(format=pa.get_format_from_width(wav.getsampwidth()),
                       channels=wav.getnchannels(),
                       rate=wav.getframerate(),
                       output=True)

data = wav.readframes(CHUNK)

while data != '':
    audio_stream.write(data)
    data = wav.readframes(CHUNK)

audio_stream.stop_stream()
audio_stream.close()
pa.terminate()

Вот пример ошибки канала:

wave.Error: # channels not specified

person dmc94    schedule 10.10.2019    source источник


Ответы (2)


Попробуй это:

import pyaudio
import wave
import numpy as np
import sounddevice as sd

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)):
    # read data-chunks in strings
    data = stream.read(CHUNK)
    #frames.append(data)
    # change the format to numpy int16
    frames.append(np.fromstring(data,dtype=np.int16))
#newS = np.fromstring(frames,dtype=np.int16)
print("* done recording")
sound = np.array(frames)
sound = sound.flatten()
sd.play(sound,44100*2)

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()
person kevin-cali    schedule 13.10.2019

Вот более простое решение, использующее только pyaudio и встроенные функции:

import pyaudio
import wave
import io

# response.audio_content is a byte string
with wave.open(io.BytesIO(response.audio_content), 'rb') as f:
    width = f.getsampwidth()
    channels = f.getnchannels()
    rate = f.getframerate()
pa = pyaudio.PyAudio()
pa_stream = pa.open(
    format=pyaudio.get_format_from_width(width),
    channels=channels,
    rate=rate,
    output=True
)
pa_stream.write(response.audio_content)

Вы не можете открыть строку байтов напрямую; io.BytesIO предоставляет файловую оболочку, поэтому wave.open может работать со строкой байтов.

person Daniel Q    schedule 07.09.2020