pyaudio Audioaufnahme Python
Ich versuche, mit Python Audio vom Mikrofon aufzunehmen. Und ich habe folgenden Code:
import pyaudio
import wave
import threading
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
CHUNK = 1024
WAVE_OUTPUT_FILENAME = "file.wav"
stop_ = False
audio = pyaudio.PyAudio()
stream = audio.open(format=FORMAT, channels=CHANNELS,
rate=RATE, input=True,
frames_per_buffer=CHUNK)
def stop():
global stop_
while True:
if not input('Press Enter >>>'):
print('exit')
stop_ = True
t = threading.Thread(target=stop, daemon=True).start()
frames = []
while True:
data = stream.read(CHUNK)
frames.append(data)
if stop_:
break
stream.stop_stream()
stream.close()
audio.terminate()
waveFile = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
waveFile.setnchannels(CHANNELS)
waveFile.setsampwidth(audio.get_sample_size(FORMAT))
waveFile.setframerate(RATE)
waveFile.writeframes(b''.join(frames))
waveFile.close()
Mein Code funktioniert einwandfrei, aber wenn ich meine Aufnahme wiedergebe, höre ich keinen Ton in meiner endgültigen Ausgabedatei ( file.wav).
Warum treten hier Probleme auf und wie behebe ich sie?
Antworten
Ihr Code funktioniert einwandfrei. Das Problem, mit dem Sie konfrontiert sind, ist auf die Administratorrechte zurückzuführen. Die Audiodatei enthält konstante 0-Daten. Daher können Sie in der generierten WAV-Datei keinen Ton hören. Ich nehme an, Ihr Mikrofon ist installiert und funktioniert ordnungsgemäß. Wenn Sie sich über den Status der Audio-Installation nicht sicher sind, führen Sie die folgenden Schritte gemäß Betriebssystem aus:
MAC OS: Systemeinstellungen-> Sound-> Eingabe und dort können Sie die Balken als Sound visualisieren. Stellen Sie sicher, dass der ausgewählte Gerätetyp Integriert ist.
Windos OS: Soundeinstellungen und Testen des Mikrofons durch Klicken auf dieses Gerät anhören. Sie können es später deaktivieren, da es Ihre Stimme zu den Lautsprechern zurückschleift und große Geräusche erzeugt.
Höchstwahrscheinlich verwenden Sie Mac OS. Ich hatte das ähnliche Problem, weil ich den Atom-Editor zum Ausführen des Python-Codes verwendete. Versuchen Sie, Ihren Code über das Terminal von Mac OS (oder Power Shell, wenn Sie Windows verwenden) auszuführen (falls unter Mac OS ein Popup für den Zugriff auf das Mikrofon angezeigt wird, drücken Sie OK). Das ist es! Ihr Code wird gut aufgezeichnet. Führen Sie als Tester den folgenden Code aus, um zu überprüfen, ob Sie den Sound visualisieren können, und stellen Sie sicher, dass Sie ihn über das Terminal ausführen (keine Editoren oder IDEs).
import queue
import sys
from matplotlib.animation import FuncAnimation
import matplotlib.pyplot as plt
import numpy as np
import sounddevice as sd
# Lets define audio variables
# We will use the default PC or Laptop mic to input the sound
device = 0 # id of the audio device by default
window = 1000 # window for the data
downsample = 1 # how much samples to drop
channels = [1] # a list of audio channels
interval = 30 # this is update interval in miliseconds for plot
# lets make a queue
q = queue.Queue()
# Please note that this sd.query_devices has an s in the end.
device_info = sd.query_devices(device, 'input')
samplerate = device_info['default_samplerate']
length = int(window*samplerate/(1000*downsample))
# lets print it
print("Sample Rate: ", samplerate)
# Typical sample rate is 44100 so lets see.
# Ok so lets move forward
# Now we require a variable to hold the samples
plotdata = np.zeros((length,len(channels)))
# Lets look at the shape of this plotdata
print("plotdata shape: ", plotdata.shape)
# So its vector of length 44100
# Or we can also say that its a matrix of rows 44100 and cols 1
# next is to make fig and axis of matplotlib plt
fig,ax = plt.subplots(figsize=(8,4))
# lets set the title
ax.set_title("PyShine")
# Make a matplotlib.lines.Line2D plot item of color green
# R,G,B = 0,1,0.29
lines = ax.plot(plotdata,color = (0,1,0.29))
# We will use an audio call back function to put the data in queue
def audio_callback(indata,frames,time,status):
q.put(indata[::downsample,[0]])
# now we will use an another function
# It will take frame of audio samples from the queue and update
# to the lines
def update_plot(frame):
global plotdata
while True:
try:
data = q.get_nowait()
except queue.Empty:
break
shift = len(data)
plotdata = np.roll(plotdata, -shift,axis = 0)
# Elements that roll beyond the last position are
# re-introduced
plotdata[-shift:,:] = data
for column, line in enumerate(lines):
line.set_ydata(plotdata[:,column])
return lines
ax.set_facecolor((0,0,0))
# Lets add the grid
ax.set_yticks([0])
ax.yaxis.grid(True)
""" INPUT FROM MIC """
stream = sd.InputStream( device = device, channels = max(channels), samplerate = samplerate, callback = audio_callback)
""" OUTPUT """
ani = FuncAnimation(fig,update_plot, interval=interval,blit=True)
with stream:
plt.show()
Speichern Sie diese Datei als voice.py in einem Ordner (sagen wir AUDIO). Dann vom Terminalbefehl in den AUDIO-Ordner cd und dann ausführen mit:
python3 voice.py
oder
python voice.py
abhängig von Ihrem Python-Env-Namen.
Bei Verwendung von print(sd.query_devices())sehe ich eine Liste von Geräten wie folgt:
- Microsoft Sound Mapper - Eingang, MME (2 in, 0 out)
- Mikrofon (AudioHubNano2D_V1.5, MME (2 in, 0 out)
- Internes Mikrofon (Conexant S, MME (2 in, 0 out)
- ...
Wenn ich jedoch verwende device = 0, kann ich weiterhin Ton vom USB-Mikrofon empfangen, das die Gerätenummer 1 ist. Ist es standardmäßig so, dass das gesamte Audiosignal an den Sound Mapper gesendet wird? Das heißt, wenn ich benutze device = 0, erhalte ich das gesamte Audiosignal von allen Audioeingängen. und wenn ich nur Audioeingang von einem bestimmten Gerät möchte, muss ich dessen Nummer x als wählen device = x.
Ich habe noch eine andere Frage: Ist es möglich, Audiosignale von Gerät 1 und 2 in einer Anwendung, aber auf separate Weise zu erfassen?