Reprint: voice recorder python development of (a) to record the sound card to play (in the record)
Preparing the Environment
python
wave
pyaudio
pip wave can directly install, the installation pyaudio
time, through normal pip install direct installation has been in a phase error, then think of can be installed directly through the wheels.
In pypi installation package provided there is a corresponding installation package, pay attention, just python2
and python3
differentiated, python3
small version is also a bit different. Can cup, the small main computer is installed python3.8
, then I think there is a website you can install pythonlibs , find the corresponding version download. Directly in the file directory, or perform installation in a specified file directory installation
pip install /c/Users/root/Downloads/PyAudio-0.2.11-cp38-cp38-win_amd64.whl
Code and run
def audio_record(out_file, rec_time):
CHUNK = 1024
FORMAT = pyaudio.paInt16 # 16bit编码格式
CHANNELS = 1 # 单声道
RATE = 16000 # 16000采样频率
p = pyaudio.PyAudio()
# 创建音频流
dev_idx = findInternalRecordingDevice(p)
stream = p.open(format=FORMAT, # 音频流wav格式
channels=CHANNELS, # 单声道
rate=RATE, # 采样率16000
input=True,
input_device_index=dev_idx, # 指定内录设备的id,可以不写,使用win的默认录音设备
frames_per_buffer=CHUNK)
print("Start Recording...")
frames = [] # 录制的音频流
# 录制音频数据
for i in range(0, int(RATE / CHUNK * rec_time)): # 控制录音时间
data = stream.read(CHUNK)
frames.append(data)
# 录制完成
stream.stop_stream()
stream.close()
p.terminate()
print("Recording Done...")
# 保存音频文件
wf = wave.open(out_file, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
When using the default recording device, they found a microphone recording, the effect is not too good, so go look up system can record sound directly.
def findInternalRecordingDevice(p):
# 要找查的设备名称中的关键字
target = '立体声混音'
# 逐一查找声音设备
for i in range(p.get_device_count()):
devInfo = p.get_device_info_by_index(i)
print(devInfo)
if devInfo['name'].find(target) >= 0 and devInfo['hostApi'] == 0:
# print('已找到内录设备,序号是 ',i)
return i
print('无法找到内录设备!')
return -1
Can be used p.get_device_info_by_index()
to view the system about the sound device, by setting the stereo mix can record the sound system.
Save voice
def save(fileName):
# 创建pyAudio对象
p = pyaudio.PyAudio()
# 打开用于保存数据的文件
wf = wave.open(fileName, 'wb')
# 设置音频参数
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
# 写入数据
wf.writeframes(b''.join(_frames))
# 关闭文件
wf.close()
# 结束pyaudio
p.terminate()
Save sound is preserved by the above code, here _frames
is a List, each recorded by a the chunk (data block stream), which put the piece of data added to it
Then only need to re-create the PyAudio
objects, put this list into a string of bytes stored in a file on it
problem
It said general can record the sound system, but in the implementation of the findings and could not.
The reason: an input device configured not win the stereo mix
Procedure:
- Adjusting the sound in the win, right-click to open the sound settings
- Find the sound device management
- Enable stereo mix at the input device
In this connection, to complete the requirements of a sound recording system
note
Above, you can 外放
, you can 插入3.5mm耳机
, but it 系统静音
and tpye-c耳机插入
when not to record sound
The complete code
import os
import pyaudio
import threading
import wave
import time
from datetime import datetime
# 需要系统打开立体声混音
# 录音类
class Recorder():
def __init__(self, chunk=1024, channels=2, rate=44100):
self.CHUNK = chunk
self.FORMAT = pyaudio.paInt16
self.CHANNELS = channels
self.RATE = rate
self._running = True
self._frames = []
# 获取内录设备序号,在windows操作系统上测试通过,hostAPI = 0 表明是MME设备
def findInternalRecordingDevice(self, p):
# 要找查的设备名称中的关键字
target = '立体声混音'
# 逐一查找声音设备
for i in range(p.get_device_count()):
devInfo = p.get_device_info_by_index(i)
# print(devInfo)
if devInfo['name'].find(target) >= 0 and devInfo['hostApi'] == 0:
# print('已找到内录设备,序号是 ',i)
return i
print('无法找到内录设备!')
return -1
# 开始录音,开启一个新线程进行录音操作
def start(self):
threading._start_new_thread(self.__record, ())
# 执行录音的线程函数
def __record(self):
self._running = True
self._frames = []
p = pyaudio.PyAudio()
# 查找内录设备
dev_idx = self.findInternalRecordingDevice(p)
if dev_idx < 0:
return
# 在打开输入流时指定输入设备
stream = p.open(input_device_index=dev_idx,
format=self.FORMAT,
channels=self.CHANNELS,
rate=self.RATE,
input=True,
frames_per_buffer=self.CHUNK)
# 循环读取输入流
while (self._running):
data = stream.read(self.CHUNK)
self._frames.append(data)
# 停止读取输入流
stream.stop_stream()
# 关闭输入流
stream.close()
# 结束pyaudio
p.terminate()
return
# 停止录音
def stop(self):
self._running = False
# 保存到文件
def save(self, fileName):
# 创建pyAudio对象
p = pyaudio.PyAudio()
# 打开用于保存数据的文件
wf = wave.open(fileName, 'wb')
# 设置音频参数
wf.setnchannels(self.CHANNELS)
wf.setsampwidth(p.get_sample_size(self.FORMAT))
wf.setframerate(self.RATE)
# 写入数据
wf.writeframes(b''.join(self._frames))
# 关闭文件
wf.close()
# 结束pyaudio
p.terminate()
if __name__ == "__main__":
# 检测当前目录下是否有record子目录
if not os.path.exists('record'):
os.makedirs('record')
print("\npython 录音机 ....\n")
print("提示:按 r 键并回车 开始录音\n")
i = input('请输入操作码:')
if i == 'r':
rec = Recorder()
begin = time.time()
print("\n开始录音,按 s 键并回车 停止录音,自动保存到 record 子目录\n")
rec.start()
running = True
while running:
i = input("请输入操作码:")
if i == 's':
running = False
print("录音已停止")
rec.stop()
t = time.time() - begin
print('录音时间为%ds' % t)
# 以当前时间为关键字保存wav文件
rec.save("record/rec_" + datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + ".wav")