Python+pyaudio实现音频控制示例详解

简介

PyAudio是一个跨平台的音频处理工具包,使用该工具包可以在Python程序中播放和录制音频,也可以产生wav文件等

安装

pip install PyAudio

注意:使用该命令安装时可能会报错,报错内容如下:

针对该问题,我们使用whl文件进行安装,首先在网址下面找到以下文件并下载,根据自己的python版本及计算机系统下载相应文件即可。

下载完成后,切换到文件所在目录,使用如下命令安装即可

pip3 install PyAudio-0.2.11-cp38-cp38-win_amd64.whl

pyaudio控制指定设备,录制音频/采集音频流/播放音频

#!/usr/bin/env python3
#-*- coding:utf-8 -*-
#------------- 音频设备操作模块 -------------------
#
#   功能:   录制/获取音频流/播放音频
#   时间:  2021-09-13
#
#--------------------------------------------------

import sys ,pyaudio, wave
from tqdm import tqdm

class UacAudioInAndOut:
    def __init__(self):
        """
            功能:   录音参数初始化
                    创建vad检测模块对象
            参数:   /
            返回值: /
        """
        self.input_format_dict = {"S8_LE":16, "S16_LE":8, "S24_LE":4, "S32_LE":2}
        self.framerate_list = [8000, 11025, 16000, 22050, 32000, 44100, 48000,
                            88200, 96000, 176400, 192000, 352800, 384000]

    def _inforPrintf(self, infor_content):
        """
            功能:   检测操作系统,使用正确编码
                    输出打印信息
            参数:   infor_content: 信息内容
            返回值: /
        """
        if sys.platform != "linux" and sys.platform != "darwin":
            infor_content = str(infor_content).encode("gbk","ignore").decode("gbk")
        print(infor_content)

    def GetAllDevInfor(self):
        """
            功能:   显示支持设备信息
            参数:   /
            返回值: /
        """
        PA = pyaudio.PyAudio()
        self._inforPrintf("----------------------< 本机支持设备 >------------------------------")
        for dev_index in range(PA.get_device_count()):
            self._inforPrintf("\n-------------------------------------------------------")
            for key in PA.get_device_info_by_index(dev_index):
                    self._inforPrintf("%s:%s"%(key, str(PA.get_device_info_by_index(dev_index)[key])))
            self._inforPrintf("========================================================")

    def GetUacDevInfor(self, devKeywordOrIndex=None):
        """
            功能:   获取UAC设备信息
            参数:   devKeywordOrIndex: 设备名称关键字或索引
            返回值: dic 设备信息字典
                    False 设备信息获取失败
        """
        PA = pyaudio.PyAudio()
        if devKeywordOrIndex == None:
            self._inforPrintf("\033[0;36;31m[UacAudioInAndOut] 未设设备, 当前使用默认设备\033[0m")
            return PA.get_default_input_device_info()
        if str(devKeywordOrIndex).isdigit():
            devKeywordOrIndex = int(devKeywordOrIndex)
            return PA.get_device_info_by_index(devKeywordOrIndex)

        uac_infor_list = []
        for uac_index in range(PA.get_device_count()):
            if PA.get_device_info_by_index(uac_index).get("name").find(str(devKeywordOrIndex)) >= 0:
                uac_infor_list.append(PA.get_device_info_by_index(uac_index))

        if len(uac_infor_list) > 1:
            self._inforPrintf("\033[0;36;33m[UacAudioInAndOut] UAC 设备有多个,\
                    请修正关键字, 当前设备如下: %s\033[0m"%str(uac_infor_list))
            return False
        else:
            return uac_infor_list.pop()

    def is_framerate_supported(self, setFramerate, UacAudioInHandle,
                                load_parame_dict, input_or_output="input"):
        """
            功能:   判断当配置在指定设备中是否支持
            参数:   setFramerate:       设置采样率
                    UacAudioInHandle:   设备句柄
                    load_parame_dict:   加载字典
                    input_or_output:    输入/输出功能
            返回值: bool True/False
        """
        try:
            if input_or_output == "input":
                UacAudioInHandle.is_format_supported(rate=float(setFramerate),
                            input_device=load_parame_dict['index'],
                            input_channels=load_parame_dict['setInputChannels'],
                            input_format=load_parame_dict['_setInputFormat'])
            else:
                UacAudioInHandle.is_format_supported(rate=float(setFramerate),
                            output_device=load_parame_dict['index'],
                            output_channels=load_parame_dict['maxOutputChannels'],
                            output_format=UacAudioInHandle.get_format_from_width(load_parame_dict['setOutputFormat']))
            return True
        except:
            return False

    def LoadUacAudioInDevice(self, maxStreamDuration=1000, setInputChannels=None,
                                        setInputFormat=None, devKeywordOrIndex=None):
        """
            功能:   加载音频获取设备
            参数:   maxStreamDuration=1000 默认一段流时长
                    setInputChannels:           通道数
                    setInputFormat:             位宽
                    devKeywordOrIndex:    录音设备关键字/索引
            返回值:
                    成功: UacAudioInHandle, StreamHandle, load_parame_dict
                    失败: False
        """
        try:
            load_parame_dict = {}
            uac_infor_dict = self.GetUacDevInfor(devKeywordOrIndex)
            if not setInputFormat:
                _Format = "S16_LE"
                self._inforPrintf("\033[0;36;33m[UacAudioInAndOut] 未设置位宽,使用默认 S16_LE \033[0m")
            else:
                _Format = setInputFormat
            setInputFormat = self.input_format_dict[_Format]

            if not setInputChannels or int(setInputChannels) > uac_infor_dict["maxInputChannels"]:
                setInputChannels = uac_infor_dict["maxInputChannels"]
                self._inforPrintf("\033[0;36;33m[UacAudioInAndOut] 输入通道未设置/超出当前设备最大值,使用默认最大通道 %s\
                                                                                    \033[0m"%setInputChannels)
            else:
                setInputChannels = int(setInputChannels)
            dev_index = uac_infor_dict["index"]
            load_parame_dict["index"]=dev_index
            load_parame_dict["setInputFormat"] = _Format
            load_parame_dict["_setInputFormat"] = setInputFormat
            load_parame_dict["setInputChannels"] = setInputChannels
            UacAudioInHandle = pyaudio.PyAudio()
            for setInputFramerate in self.framerate_list:
                if self.is_framerate_supported(setInputFramerate, UacAudioInHandle, load_parame_dict):
                    load_parame_dict["setInputFramerate"] = setInputFramerate
                    break
            #计算数据大小一段
            CHUNK_SIZE = int(setInputFramerate * maxStreamDuration / 1000)
            load_parame_dict["CHUNK_SIZE"] = CHUNK_SIZE
            self._inforPrintf("\033[0;36;38m[UacAudioInAndOut] 加载参数: %s\033[0m"%str(load_parame_dict))
            #加载设备
            StreamHandle = UacAudioInHandle.open(
                                format=load_parame_dict['_setInputFormat'],
                                channels=load_parame_dict['setInputChannels'],
                                rate=load_parame_dict['setInputFramerate'],
                                input=True,
                                input_device_index=load_parame_dict['index'],
                                start=False,
                                frames_per_buffer=int(CHUNK_SIZE))
            #开始流获取
            StreamHandle.start_stream()
            return UacAudioInHandle, StreamHandle, load_parame_dict
        except:
            self._inforPrintf("\033[0;36;31m[UacAudioInAndOut] Uac AudioIn 加载失败\033[0m")
            return False, False, False

    def LoadUacAudioOutDevice(self, devKeywordOrIndex):
        """
            功能:   加载音频输出设备
            参数:   /
            返回值: UacAudioInHandle 或 False
        """
        try:
            uac_infor_dict = self.GetUacDevInfor(devKeywordOrIndex)
            UacAudioInHandle = pyaudio.PyAudio()
            return UacAudioInHandle, uac_infor_dict
        except:
            return False

    def GetUacAudioInStream(self, StreamHandle, CHUNK_SIZE):
        """
            功能:   开始采集声卡音频
                    生成音频流
            参数:   UacAudioInHandle:   设备句柄
                    StreamHandle:       流句柄
            返回值  chunk_data 流数据
        """
        return StreamHandle.read(CHUNK_SIZE, exception_on_overflow=False) #防止溢出

    def UacAudioOutPlay(self, playWavFile, Repeat=None, Pdict=None, devKeywordOrIndex=None,):
        """
            功能:   可以循环播放指定文件
            参数:   playWavFile:            播放文件路径
                    Repeat:                 循环播放次数
                    CustomizeAudioParam:    自定义播放参数
            返回值: /
        """
        UacAudioInHandle, uac_infor_dict = self.LoadUacAudioOutDevice(devKeywordOrIndex)
        self._inforPrintf(str(uac_infor_dict).encode("gbk","ignore").decode("gbk"))
        self._inforPrintf("\033[1;36;34m[UacAudioInAndOut] 指定设备: %s\t播放文件: %s\t循环总数: %s\
                                            \033[0m"%(devKeywordOrIndex, playWavFile,Repeat))
        try:
            chunk=1024
            pfb = wave.open(playWavFile, 'rb')
            setOutputFormat = pfb.getsampwidth()
            setOutputChannels = pfb.getnchannels()
            setOutputFramerate = pfb.getframerate()
            uac_infor_dict['setOutputFormat'] = setOutputFormat

            if setOutputChannels > uac_infor_dict["maxOutputChannels"]:
                self._inforPrintf("\033[0;36;31m[UacAudioInAndOut] 当前通道数,在该设备上不支持, \
                                设备最大通道数: %s\033[0m"%uac_infor_dict["maxOutputChannels"])
                return False
            if not self.is_framerate_supported(setOutputFramerate, UacAudioInHandle, uac_infor_dict, "output"):
                self._inforPrintf("\033[0;36;31m[UacAudioInAndOut] 当前文件采样率,在该设备上不支持,\
                                    设备默认采样率: %s\033[0m"%uac_infor_dict["defaultSampleRate"])
                return False
            else:
                uac_infor_dict["defaultSampleRate"] = setOutputFramerate
            stream = UacAudioInHandle.open(
                                output_device_index=uac_infor_dict['index'],
                                format=UacAudioInHandle.get_format_from_width(setOutputFormat),
                                channels=setOutputChannels,
                                rate=setOutputFramerate,
                                output=True)

            if Repeat == "Dead_cycle":
                self._inforPrintf("\033[1;36;33m[UacAudioInAndOut] Dead cycle play !!! \033[0m")
                while True:
                    if type(Pdict) == dict and Pdict["play status"] == "stop":
                        break
                    pfb = wave.open(playWavFile, 'rb')
                    while True:
                        data = pfb.readframes(chunk)
                        if not data:
                            break
                        stream.write(data)
            else:
                for index in tqdm(range(int(Repeat))):
                    if type(Pdict) == dict and Pdict["play status"] == "stop":
                        break
                    pfb = wave.open(playWavFile, 'rb')
                    while True:
                        data = pfb.readframes(chunk)
                        if not data:
                            break
                        stream.write(data)

            stream.stop_stream()
            stream.close()
            self.CloseAudioDevice(UacAudioInHandle)
            return True
        except:
            stream.stop_stream()
            stream.close()
            return False

    def UacAudioInRecord(self, saveWavFile, recordTime, #单位秒
                        setInputChannels=None,
                        setInputFormat=None,
                        devKeywordOrIndex=None):
        """
            功能:   录制音频文件
            参数:   recordTime:         录音时长, 单位(s)
                    setInputFramerate:  采样率
                    setInputChannels:   通道数
                    setInputFormat:     位宽
                    devKeywordOrIndex:      录音设备索引
            返回值: /
        """
        maxStreamDuration=1000
        load_parame_dict = {}
        UacAudioInHandle, StreamHandle, load_parame_dict = self.LoadUacAudioInDevice(
                                                                    maxStreamDuration,
                                                                    setInputChannels,
                                                                    setInputFormat,
                                                                    devKeywordOrIndex)
        if not UacAudioInHandle or not StreamHandle:
            self._inforPrintf("\033[0;36;31m[UacAudioInAndOut] 录音失败\033[0m")
            return False

        self._inforPrintf("\033[1;36;34m[UacAudioInAndOut] 录音 -> 文件名: %s 时长: %s\
                                            \033[0m"%(saveWavFile,recordTime))
        self._inforPrintf(load_parame_dict["CHUNK_SIZE"])
        data_list = []
        for recordTime_index in range(int(recordTime)):
            data = None
            data = StreamHandle.read(load_parame_dict["CHUNK_SIZE"], exception_on_overflow=False)
            data_list.append(data)
        StreamHandle.stop_stream()
        StreamHandle.close()
        self.CloseAudioDevice(UacAudioInHandle)
        with wave.open(saveWavFile, "wb") as wavfb:
            wavfb.setnchannels(load_parame_dict["setInputChannels"])
            wavfb.setsampwidth(UacAudioInHandle.get_sample_size(load_parame_dict["_setInputFormat"]))
            wavfb.setframerate(load_parame_dict["setInputFramerate"])
            wavfb.writeframes(b''.join(data_list))

        """
            功能:   关闭音频流设备
            参数:   UacAudioInHandle
            返回值: bool True/False
        """
        try:
            StreamHandle.stop_stream()
            StreamHandle.close()
            self.CloseAudioDevice()
            return True
        except:
            return False

    def CloseAudioDevice(self, UacAudioDeviceHandle):
        """
            功能:   释放 Audio 设备
            参数:   UacAudioDeviceHandle
            返回值: bool True/False
        """
        try:
            UacAudioDeviceHandle.terminate()
            return True
        except:
            return False

if __name__=="__main__":
    asv = UacAudioInAndOut()
    asv.GetAllDevInfor()
    #asv.UacAudioOutPlay(sys.argv[1], int(sys.argv[2]), None, sys.argv[3])
    asv.UacAudioInRecord(sys.argv[1], sys.argv[2])

以上就是Python+pyaudio实现音频控制示例详解的详细内容,更多关于Python pyaudio音频控制的资料请关注我们其它相关文章!

(0)

相关推荐

  • python调用pyaudio使用麦克风录制wav声音文件的教程

    python的pyaudio可以进行录音,播放,生成wav文件等等,WAVE是录音时用的标准的WINDOWS文件格式,文件的扩展名为WAV,数据本身的格式为PCM或压缩型,属于无损音乐格式的一种.在我们研究语音识别,自然语言处理的过程中,常常会使用到它,比如我们调用百度语音识别所以我们首先研究一下pyaudio库的安装与使用. 安装: pip install pyaudio 调用pyaudio使用麦克风录制声音: python中的pyaudio库可以直接通过麦克风录制声音,我们可以通过调用该库,

  • Python使用PyAudio制作录音工具的实现代码

    目录 应用平台 音频录制部分 音频播放部分 GUI窗口所需属性值代码部分 pynput监听键盘 总结 最近有在使用屏幕录制软件录制桌面,在用的过程中突发奇想,使用python能不能做屏幕录制工具,也锻炼下自己的动手能力.接下准备写使用python如何做屏幕录制工具的系列文章: 录制屏幕制作视频 录制音频 合成视频,音频 基于pyqt5制作可视化窗口 大概上述四个部分,希望自己能够尽快完善,上一篇文章利用opencv制作了屏幕录制部分,接下继续更新系列,使用python录制音频. 应用平台 win

  • Python+opencv+pyaudio实现带声音屏幕录制

    基于个人的爱好和现实的需求,决定用Python做一个屏幕录制的脚本.因为要看一些加密的视频,每次都要登录,特别麻烦,遂决定用自己写的脚本,将加密视频的播放过程全程录制下来,这样以后看自己的录播就好了.结合近期自己学习的内容,正好用Python来练练手,巩固自己的学习效果. 经过多番搜索,决定采用Python+opencv+pyaudio来实现屏幕录制.网上搜索到的录屏,基本都是不带声音的,而我要实现的是带声音的屏幕录制.下面就开始一步一步的实现吧. 声音录制 import pyaudio imp

  • Python3.7安装pyaudio教程解析

    本人笔记本电脑安装的是 python3.7, 64位操作系统,基于x64的处理器 因为 pyaudio 暂时不支持 python3.7 和 3.8,所以若需要安装 pyaudio 需要下载 whl 文件后再离线进行安装. 首先:下载安装 pyaudio 的 whl 文件 下载网址:https://www.lfd.uci.edu/~gohlke/pythonlibs/ 然后按下 ctrl+f 输入关键字:pyaudio 本人原先选择的是第一个,但是后来发现一直提示错误:ERROR: PyAudio

  • Python音频操作工具PyAudio上手教程详解

    ​ 0.引子 当需要使用Python处理音频数据时,使用python读取与播放声音必不可少,下面介绍一个好用的处理音频PyAudio工具包. PyAudio是Python开源工具包,由名思义,是提供对语音操作的工具包.提供录音播放处理等功能,可以视作语音领域的OpenCv. 1.简介 PyAudio为跨平台音频I / O库 PortAudio 提供 Python 绑定.使用PyAudio,您可以轻松地使用Python在各种平台上播放和录制音频,例如GNU / Linux,Microsoft Wi

  • Python+pyaudio实现音频控制示例详解

    简介 PyAudio是一个跨平台的音频处理工具包,使用该工具包可以在Python程序中播放和录制音频,也可以产生wav文件等 安装 pip install PyAudio 注意:使用该命令安装时可能会报错,报错内容如下: 针对该问题,我们使用whl文件进行安装,首先在网址下面找到以下文件并下载,根据自己的python版本及计算机系统下载相应文件即可. 下载完成后,切换到文件所在目录,使用如下命令安装即可 pip3 install PyAudio-0.2.11-cp38-cp38-win_amd6

  • 利用Python实现智能合约的示例详解

    目录 智能合约 1. 是什么 2. 使用场景 用Python如何实现 1. 设计智能合约 2. 编写智能合约源代码 3. 编译智能合约 4. 部署智能合约 5. 调用智能合约方法 6. 监控智能合约事件 7. 升级智能合约 智能合约 1. 是什么 智能合约是一种由计算机程序编写的自动化合约,它可以在没有第三方干预的情况下执行交易和契约条款.智能合约使用区块链技术实现,可以实现不同的功能,例如交易.投票.代币发放和数据存储等.智能合约的执行是基于其代码的逻辑,并且在既定条件满足时自动执行.智能合约

  • python实现PCA降维的示例详解

    概述 本文主要介绍一种降维方法,PCA(Principal Component Analysis,主成分分析).降维致力于解决三类问题. 1. 降维可以缓解维度灾难问题: 2. 降维可以在压缩数据的同时让信息损失最小化: 3. 理解几百个维度的数据结构很困难,两三个维度的数据通过可视化更容易理解. PCA简介 在理解特征提取与处理时,涉及高维特征向量的问题往往容易陷入维度灾难.随着数据集维度的增加,算法学习需要的样本数量呈指数级增加.有些应用中,遇到这样的大数据是非常不利的,而且从大数据集中学习

  • Python线性点运算数字图像处理示例详解

    目录 点运算 定义 分类 线性点运算 分段线性点运算 非线性点运算 对数变换 幂次变换 点运算 定义 分类 线性点运算 例子: 分段线性点运算 非线性点运算 对数变换 幂次变换 1. 点运算是否会改变图像内像素点之间的空间位置关系? 点运算是一种像素的逐点运算,它与相邻的像素之间没有运算关系,点运算不会改变图像内像素点之间的空间位置关系. 2. 对图像灰度的拉伸,非线性拉伸与分段线性拉伸的区别? 非线性拉伸不是通过在不同灰度值区间选择不同的线性方程来实现对不同灰度值区间的扩展与压缩,而是在整个灰

  • Python面向对象编程repr方法示例详解

    目录 为什么要讲 __repr__ 重写 __repr__ 方法 str() 和 repr() 的区别 为什么要讲 __repr__ 在 Python 中,直接 print 一个实例对象,默认是输出这个对象由哪个类创建的对象,以及在内存中的地址(十六进制表示) 假设在开发调试过程中,希望使用 print 实例对象时,输出自定义内容,就可以用 __repr__ 方法了 或者通过 repr() 调用对象也会返回 __repr__ 方法返回的值 是不是似曾相识....没错..和 __str__ 一样的

  • python函数传参意义示例详解

    目录 C++这样的语言用多了之后,在Python函数传递参数的时候,经常会遇到一个问题,我要传递一个引用怎么办? 比如我们想要传一个x到函数中做个运算改变x的值: def change(y): y += 1 x = 1 print ("before change:", x) change(x) print ("after change: ", x) 得到的结果是 before change: 1 after change:  1 完全没用~~~这是怎么回事? 我来说

  • python模块shutil函数应用示例详解教程

    目录 本文大纲 知识串讲 1)模块导入 2)复制文件 3)复制文件夹 4)移动文件或文件夹 5)删除文件夹(慎用) 6)创建和解压压缩包 本文大纲 os模块是Python标准库中一个重要的模块,里面提供了对目录和文件的一般常用操作.而Python另外一个标准库--shutil库,它作为os模块的补充,提供了复制.移动.删除.压缩.解压等操作,这些 os 模块中一般是没有提供的.但是需要注意的是:shutil 模块对压缩包的处理是调用 ZipFile 和 TarFile这两个模块来进行的. 知识串

  • Python实现连接dr校园网示例详解

    目录 背景 分析 实现 背景 在校园里认证上网很麻烦需要web输入账号密码有时还会忘记web地址此时就需要一个人或者程序帮我们实现,这时我想到用python制作这个程序(初学者python代码不规范) 分析 需要分析web登录网址的浏览器头发现是get方法这就简单了,再次分析get请求发现有user_account字段,user_password字段还有ip字段mac字段这时我们的思路就来了使用curl命令直接把这个代码放到终端里运行发现是可以的 curl "http://学校认证服务器ip:8

  • Python绘制3D立体花朵示例详解

    目录 动态展示 导读 源码和详解 荷花 玫瑰花 桃花 月季 动态展示 这是一个动态图哦 导读 兄弟们可以收藏一下哦!情人节可以送出去,肥学找了几朵python写的花给封装好送给大家.不是多炫酷但是有足够的用心哦.别忘了点赞呀我也就不细说了,来吧展示! 源码和详解 荷花 def lotus(): fig = plt.figure(figsize=(10,7),facecolor='black',clear=True) ax = fig.gca(projection='3d') [x, t] = n

  • Python+matplotlib实现绘制等高线图示例详解

    目录 前言 1. 等高线图概述 什么是等高线图? 等高线图常用场景 绘制等高线图步骤 案例展示 2. 等高线图属性 设置等高线颜色 设置等高线透明度 设置等高线颜色级别 设置等高线宽度 设置等高线样式 3. 显示轮廓标签 4. 填充颜色 5. 添加颜色条说明 总结 前言 我们在往期对matplotlib.pyplot()方法学习,到现在我们已经会绘制折线图.柱状图.散点等常规的图表啦(往期的内容如下,大家可以方便查看往期内容) Python matplotlib底层原理解析 Python利用 m

随机推荐