Запись и воспроизведение звука через PyAudio
Введение
Звук в компьютере представляет собой последовательность значений амплитуды (громкости) реальной звуковой волны. Одно значение амплитуды в последовательности будем называть отсчетом (или фреймом).
Частота дискретизации - количество отсчетов на одну секунду записи (чем больше, тем выше качество). Стандартная частота дискретизации для CD - 44100.
Глубина звука - количество бит для хранения одного отсчета. Чем больше - тем точнее можно передать реальное значение амплитуды, а значит выше качество. Стандартное значение для CD - 16 бит (2 байта).
Количество каналов - количество звуковых дорожек внутри файла. В файле для стерео системы (т.е. обычной файле) на самом деле есть сразу две звуковые дорожки - для правого и левого динамика.
Поток - это буфер в памяти звукового устройства (записывающего или воспроизводящего), куда устройство времено складывает данные в ожидании момента, когда их заберет ваш скрипт.
CHUNK - количество отсчетов, которые будут считываться из потока за один раз.
Байт-строка - последовательность байт записанная в виде строки. Именно в таком виде данные будут считываться из потока.
Запись и воспроизведение звука с помощью PyAudio
import pyaudio
FORMAT = pyaudio.paInt16 # глубина звука = 16 бит = 2 байта
CHANNELS = 1 # моно
RATE = 48000 # частота дискретизации - кол-во фреймов в секунду
CHUNK = 4000 # кол-во фреймов за один "запрос" к микрофону - тк читаем по кусочкам
RECORD_SECONDS = 5 # длительность записи
# подключаемся к аудиокарте
audio = pyaudio.PyAudio()
# открываем поток для чтения данных с устройства записи по-умолчанию и задаем параметры
in_stream = audio.open(format=FORMAT, channels=CHANNELS,
rate=RATE, input=True,
frames_per_buffer=CHUNK)
# открываем поток для записи на устройство вывода - динамик - с такими же параметрами
out_stream = audio.open(format=FORMAT, channels=CHANNELS,
rate=RATE, output=True)
print("recording...")
audio_recording = b'' # пустая строка из байт
# для каждого "запроса"
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)): # RATE / CHUNK - кол-во запросов в секунду
audio_recording += in_stream.read(CHUNK) # читаем строку из байт длиной CHUNK * FORMAT = 4000*2 байт
print("finished recording")
print("now playing...")
# отправляем все что записали на колонки
out_stream.write(audio_recording) # отправляем на динамик
# отключаемся от микрофона и динамика
out_stream.stop_stream()
out_stream.close()
in_stream.stop_stream()
in_stream.close()
# отключаемся от аудиокарты
audio.terminate()
Потоковая обработка звука с микрофона
В примере ниже мы используем библиотеку PyAudio чтобы получить доступ к микрофону и выводить на экран среднюю громкость звука за секунду.
import struct, pyaudio
FORMAT = pyaudio.paInt16 # глубина звука = 16 бит = 2 байта
CHANNELS = 1 # моно
RATE = 48000 # частота дискретизации - кол-во фреймов в секунду
CHUNK = 4000 # кол-во фреймов за один "запрос" к микрофону - тк читаем по кусочкам
RECORD_SECONDS = 20 # длительность записи
audio = pyaudio.PyAudio()
# открываем поток для чтения данных с устройства записи по умолчанию
# и задаем параметры
stream = audio.open(format=FORMAT, channels=CHANNELS,
rate=RATE, input=True,
frames_per_buffer=CHUNK)
print("recording...")
# каждую секунду
for i in range(RECORD_SECONDS):
s = 0 # сумма отсчетов за секунду
# для каждого "запроса"
for j in range(RATE // CHUNK): # RATE//CHUNK - количество "запросов" к микрофону в секунду
data = stream.read(CHUNK) # читаем строку из байт длиной CHUNK * FORMAT = 4000*2 байт
# здесь мы превращаем байты в список из чисел, каждые два байта превращаются в число
frames = struct.unpack("<" + str(CHUNK) + "h", data) # строка -> список из CHUNK отсчетов, h - это short int
# суммируем модули отсчетов - они могут быть отрицательными, поэтому убираем минус
for frame in frames:
s += abs(frame)
print(s // RATE) # выводим среднюю громкость секунды
print("finished recording")
Как записать звук в файл?
import pyaudio
import wave
# частока дискретизации и размер кусочка для считывания
FORMAT = pyaudio.paInt16
FRAMERATE = 44100
BUFFER = 4096
CHANNELS = 1 # моно
# открываем файл
music_file = wave.open("result2.wav", "wb")
music_file.setnchannels(CHANNELS)
music_file.setframerate(FRAMERATE)
music_file.setsampwidth(FORMAT)
# запрашиваем сигнал с микрофона
audio = pyaudio.PyAudio()
in_stream = audio.open(format=FORMAT, channels=CHANNELS,
rate=FRAMERATE, input=True, frames_per_buffer=BUFFER)
# длительность записи
seconds = 5
for i in range(seconds * FRAMERATE // BUFFER):
data = in_stream.read(BUFFER)
music_file.writeframes(data)
in_stream.stop_stream()
Как воспроизвести звук из файла?
import pyaudio
import wave
audio_file = wave.open("ИМЯ ФАЙЛА.wav")
FORMAT = audio_file.getsampwidth() # глубина звука
CHANNELS = audio_file.getnchannels() # количество каналов
RATE = audio_file.getframerate() # частота дискретизации
N_FRAMES = audio_file.getnframes() # кол-во отсчетов
audio = pyaudio.PyAudio()
# открываем поток для записи на устройство вывода - динамик - с такими же параметрами
out_stream = audio.open(format=FORMAT, channels=CHANNELS,
rate=RATE, output=True)
out_stream.write(audio_file.readframes(N_FRAMES)) # отправляем на динамик
audio.terminate()