pyaudioオーディオ録音python

Aug 31 2020

Pythonでマイクからの音声を録音しようとしています。そして私は次のコードを持っています:

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

コードは正常に機能しますが、録音を再生すると、最終出力ファイルに音が聞こえません(file.wav)。

ここで問題が発生するのはなぜですか?また、どのように修正すればよいですか?

回答

1 Azr Sep 08 2020 at 03:31

コードは正常に機能しています。あなたが直面している問題は、管理者権限によるものです。オーディオファイルには定数0のデータがあるため、生成されたwavファイルでサウンドを聞くことはできません。マイクデバイスがインストールされ、正常に動作していると思います。オーディオのインストールステータスがわからない場合は、オペレーティングシステムに従って次の手順を実行します。

MAC OS:[システム環境設定]-> [サウンド]-> [入力]をクリックすると、バーを視覚化してサウンドを作成できます。選択したデバイスタイプが組み込みであることを確認してください。

Windos OS:サウンド設定とマイクのテストをクリックして[このデバイスを聞く]をクリックします。音声がスピーカーにループバックし、大きなノイズが発生するため、後でオフにすることができます。

おそらくMacOSを使用しています。Atomエディターを使用してPythonコードを実行していたため、同様の問題が発生しました。Mac OS(またはWindowsを使用している場合はPower Shell)の端末からコードを実行してみてください(Mac OSでマイクにアクセスするためのポップアップが表示された場合は、[OK]を押してください)。それでおしまい!あなたのコードはうまく記録されます。テスターとして、以下のコードを実行してサウンドを視覚化できるかどうかを確認し、ターミナル(エディターやIDEなし)から実行してください。

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

このファイルをvoice.pyとしてフォルダー(たとえばAUDIO)に保存します。次に、ターミナルコマンドからAUDIOフォルダにcdし、次を使用して実行します。

python3 voice.py

または

python voice.py

Pythonのenv名によって異なります。

user0814 Sep 15 2020 at 09:00

を使用するとprint(sd.query_devices())、次のようなデバイスのリストが表示されます。

  1. Microsoft Sound Mapper-入力、MME(2入力、0出力)
  2. マイク(AudioHubNano2D_V1.5、MME(2入力、0出力)
  3. 内蔵マイク(Conexant S、MME(2入力、0出力)
  4. ..。

ただし、を使用してもdevice = 0、デバイス番号1のUSBマイクから音声を受信できます。デフォルトでは、すべての音声信号がサウンドマッパーに送られますか?つまり、を使用するとdevice = 0、すべてのオーディオ入力からすべてのオーディオ信号を取得します。また、特定のデバイスからのオーディオ入力だけが必要な場合は、その番号xをとして選択する必要がありますdevice = x

別の質問があります。1つのアプリケーションでデバイス1と2からのオーディオ信号を別々の方法でキャプチャすることは可能ですか?