python 录制系统声音的示例


Posted in Python onDecember 21, 2020

环境准备

python

  • wave
  • pyaudio

wave 可以通过pip直接install,在安装pyaudio时,通过正常的pip install 直接安装一直处于报错阶段,后来想到可以通过轮子直接安装。

在pypi提供的安装包中有对应的安装包,注意,不仅仅是python2和python3的区别,python3的小版本也有点差别。可杯具的是,小主电脑里装的是python3.8,后来想到还有一个网站可以安装pythonlibs,找到对应的版本后,下载下来。直接在文件所在目录,或者在安装中指定文件目录中执行安装

pip install /c/Users/root/Downloads/PyAudio-0.2.11-cp38-cp38-win_amd64.whl

代码和运行

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

在使用默认录音设备时,发现是话筒录音,效果并不是太理想,所以就去查查能不能直接录系统的声音。

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

可以使用p.get_device_info_by_index()去查看系统有关声音的设备,通过设置为立体声混音就可以录制系统声音。

保存声音

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

保存声音是通过上述代码进行保存,此处的_frames是个list,是通过每录一个chunk(数据流块),就把这一块的数据添加进去

然后只需要重新创建PyAudio对象,把这个list转为字节串保存到文件中就可以了

问题

上述一般可以录到系统声音,但在执行的时候发现,并不能。

原因是:win的输入设备中没有配置立体声混音

设置步骤:

  • 在win的声音调节出,右击打开声音设置
  • 找到管理声音设备
  • 在输入设备处启用立体声混音

就此,就完成了录制系统声音的需求

注意

上述操作,可以外放,可以插入3.5mm耳机,但系统静音和tpye-c耳机插入的时候不能录到声音

完整代码

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")

以上就是python 录制系统声音的示例的详细内容,更多关于python 录制系统声音的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python THREADING模块中的JOIN()方法深入理解
Feb 18 Python
Python接收Gmail新邮件并发送到gtalk的方法
Mar 10 Python
Python ldap实现登录实例代码
Sep 30 Python
Python 网页解析HTMLParse的实例详解
Aug 10 Python
python爬取拉勾网职位数据的方法
Jan 24 Python
pyinstaller参数介绍以及总结详解
Jul 12 Python
Django在pycharm下修改默认启动端口的方法
Jul 26 Python
python常见字符串处理函数与用法汇总
Oct 30 Python
pytorch 实现将自己的图片数据处理成可以训练的图片类型
Jan 08 Python
基于virtualenv创建python虚拟环境过程图解
Mar 30 Python
Python依赖包迁移到断网环境操作
Jul 13 Python
python用tkinter实现一个简易能进行随机点名的界面
Sep 27 Python
用python发送微信消息
Dec 21 #Python
关于多种方式完美解决Python pip命令下载第三方库的问题
Dec 21 #Python
Python爬虫模拟登陆哔哩哔哩(bilibili)并突破点选验证码功能
Dec 21 #Python
python switch 实现多分支选择功能
Dec 21 #Python
selenium自动化测试入门实战
Dec 21 #Python
django中ImageField的使用详解
Dec 21 #Python
python文件路径操作方法总结
Dec 21 #Python
You might like
Php中文件下载功能实现超详细流程分析
2012/06/13 PHP
thinkphp5框架API token身份验证功能示例
2019/05/21 PHP
PHP手机号码及邮箱正则表达式实例解析
2020/07/11 PHP
如何实现动态删除javascript函数
2007/05/27 Javascript
jQuery get和post 方法传值注意事项
2009/11/03 Javascript
鼠标滚轮控制网页横向移动实现思路
2013/03/22 Javascript
Jquery为a标签的href赋值实现代码
2013/05/03 Javascript
Jquery通过Ajax访问XML数据的小例子
2013/11/18 Javascript
Js冒泡事件详解及阻止示例
2014/03/21 Javascript
13 款最热门的 jQuery 图像 360 度旋转插件推荐
2014/12/09 Javascript
JavaScript实现LI列表数据绑定的方法
2015/08/04 Javascript
Bootstrap入门教程一Hello Bootstrap初识
2017/03/02 Javascript
Vuex模块化实现待办事项的状态管理
2017/03/15 Javascript
通过js修改input、select默认字体颜色
2017/04/19 Javascript
小程序实现列表删除功能
2018/10/30 Javascript
vue+php实现的微博留言功能示例
2019/03/16 Javascript
JS数组Object.keys()方法的使用示例
2019/06/05 Javascript
VUE项目初建和常见问题总结
2019/09/12 Javascript
JavaScript实现鼠标经过表格某行时此行变色
2020/11/20 Javascript
JS hasOwnProperty()方法检测一个属性是否是对象的自有属性的方法
2021/01/29 Javascript
python通过ssh-powershell监控windows的方法
2015/06/02 Python
Python采用Django开发自己的博客系统
2020/09/29 Python
使用Pyinstaller转换.py文件为.exe可执行程序过程详解
2019/08/06 Python
python正则爬取某段子网站前20页段子(request库)过程解析
2019/08/10 Python
PyCharm2019安装教程及其使用(图文教程)
2019/09/29 Python
如何使用python的ctypes调用医保中心的dll动态库下载医保中心的账单
2020/05/24 Python
俄罗斯达美乐比萨外送服务:Domino’s Pizza
2020/12/18 全球购物
大学生应聘自荐信
2013/10/11 职场文书
专科毕业生求职简历的自我评价
2013/10/12 职场文书
竞聘副主任科员演讲稿
2014/01/11 职场文书
cf战队收人广告词
2014/03/14 职场文书
新教师培训心得体会
2014/09/02 职场文书
2014年涉外离婚协议书范本
2014/11/20 职场文书
2014年财政局工作总结
2014/12/09 职场文书
三严三实学习心得体会(精选N篇)
2016/01/05 职场文书
聊聊golang中多个defer的执行顺序
2021/05/08 Golang