使用PyAudio在Python中使用回送“您听到的内容”录制麦克风声音和扬声器声音

问题描述

我正在尝试制作一个程序,该程序允许我使用Pyaudio捕捉Python声音和通过扬声器通过扬声器听到的所有声音。首先,我创建了一个流,该流记录来自麦克风的声音,另一个流具有环回模式,因此它将记录来自扬声器的输出。我们知道,官方的PyAudio版本无法记录输出。但是,在Windows Vista及更高版本中,引入了新的API WASAPI,其中包括以环回模式打开流到输出设备的功能在这种模式下,流的行为类似于输入流,并具有记录传出音频流的能力,所以这就是我所做的!!

因此,使用此解决方案可以成功完成音频文件的创建,但是在录制过程中,我遇到了麻烦,因为它捕获了加扰的声音。我们可以在这里听到声音,但有时会出现鼻子,所以我们在这里感觉不好!

请提供任何解决方案!

感谢您的回答:)

import wave
import numpy as np
# Global imports
import os
import sys
import time
import keyboard

import wave
import pydub
from pydub.utils import mediainfo
import requests
from threading import Thread

# Log and information to use the UBIQUS API
"""payload = {'apiKey': 'b5eb9744c06e4a8a8028242d740f8abf','language': 'french'}
headers = {}"""

defaultframes = 512

CHUNK = 1024
FORMAT = pyaudio.paInt16
RATE = 48000
RECORD_SECONDS = 10
WAVE_OUTPUT_FILENAME = "tmp.wav"

class hooks:
    begin = '['
    end = ']'

recorded_frames = []
device_info = {}
useloopback = False
recordtime = 1

#Use module
p = pyaudio.PyAudio()

#Set default to first in list or ask Windows
try:
    default_device_index = p.get_default_input_device_info()
except IOError:
    default_device_index = -1

#Select Device
print (hooks.begin + "Available devices:" + hooks.end + "\n")

for i in range(0,p.get_device_count()):
    info = p.get_device_info_by_index(i)
    is_wasapi = (p.get_host_api_info_by_index(info["hostApi"])["name"]).find("WASAPI") != -1
    is_casque =  str(info["name"]).find("Casque") != -1
    is_speakers = str(info["name"]).find("Speakers") != -1
  
    if is_wasapi and (is_casque or is_speakers):
        print (hooks.begin + str(info["index"]) + hooks.end + ": \t %s \n \t %s \n" % (info["name"],p.get_host_api_info_by_index(info["hostApi"])["name"]))
        print("maxOutputChannels = ",info["maxOutputChannels"])
        print("maxInputChannels = ",info["maxInputChannels"])

    if default_device_index == -1:
        default_device_index = info["index"]

#Handle no devices available
if default_device_index == -1:
    print (hooks.begin + "No device available. Quitting." + hooks.end)
    exit()

#Get input or default
device_id = int(input("Choose device number " + hooks.begin + hooks.end + ": ") or default_device_index)
print ("")

#Get device info
try:
    device_info = p.get_device_info_by_index(device_id)
except IOError:
    device_info = p.get_device_info_by_index(default_device_index)
    print (hooks.begin + "Selection not available,using default." + hooks.end)

#Choose between loopback or standard mode
is_input = device_info["maxInputChannels"] > 0
is_wasapi = (p.get_host_api_info_by_index(device_info["hostApi"])["name"]).find("WASAPI") != -1

if is_input:
    print (hooks.begin + "Selection is input using standard mode." + hooks.end)
else:
    if is_wasapi:
        useloopback = True;
        print (hooks.begin + "Selection is output. Using loopback mode." + hooks.end)
    else:
        print (hooks.begin + "Selection is input and does not support loopback mode. Quitting." + hooks.end)
        exit()

#stream using as_loopback to get sound from OS
#Open stream
channelcount = device_info["maxInputChannels"] if (device_info["maxOutputChannels"] < device_info["maxInputChannels"]) else device_info["maxOutputChannels"]

print("Configuration effectuée.\nSaisir Ctrl+s+t pour débuter l'enregistrement.\n")

# Waiting for the user to press Enter to start recording
keyboard.wait('ctrl+s+t')

stream = p.open(
    format = pyaudio.paInt16,channels = channelcount,rate = int(device_info["defaultSampleRate"]),input = True,frames_per_buffer = defaultframes,input_device_index = device_info["index"],as_loopback = useloopback)

##stream using my Microphone's input device
stream2 = p.open(
    format = FORMAT,channels = 1,rate = RATE,input=True,frames_per_buffer=defaultframes,input_device_index=1,as_loopback=False)


frames = []
frames2 = []

#Start Recording
print("* recording")
print("Start : %s" % time.ctime())

for i in range(0,int(RATE / CHUNK * RECORD_SECONDS)):
    data = stream.read(CHUNK)
    data2 = stream2.read(CHUNK)
    frames.append(data)
    frames2.append(data2)


#frames = as_loopback sound data (Speakers)
frames= b''.join(frames);

#frames2 = sound data of Microphone
frames2= b''.join(frames2);

#decoding Speaker data
Sdecoded = np.frombuffer(frames,'int16')

#decoding the microphone data
Mdecoded = np.frombuffer(frames2,'int16')
print("Mdecoded = ",Mdecoded,np.size(Mdecoded))

#converting Speaker data into a Numpy vector (making life easier when picking up audio channels)
Sdecoded= np.array(Sdecoded,dtype='int16') 
print("Sdecoded =",Sdecoded,np.size(Sdecoded))

#getting the data on the right side
rightData=Sdecoded[1::2]
print("rightData = ",rightData,np.size(rightData))

#getting the data on the left side
leftData=Sdecoded[::2]
print("leftData = ",leftData,np.size(leftData))

#mixing everything to mono = add right side + left side + Microphone decoded data that is already mono
mix = (rightData + leftData + Mdecoded)
print("mix = ",mix,np.size(mix))

#ensuring no value goes beyond the limits of short int
signal=np.clip(mix,-32767,32766)

#encode the data again
encodecoded = wave.struct.pack("%dh"%(len(signal)),*list(signal))

#stop all streams and terminate pyaudio
stream.stop_stream()
stream.close()
stream2.stop_stream()
stream2.close()
p.terminate()

#recording mixed audio in mono 
wf = wave.open(WAVE_OUTPUT_FILENAME,'wb')
wf.setnchannels(1)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes((encodecoded))
wf.close()```

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...