pyaudio ghi âm python

Aug 31 2020

Tôi đang cố gắng ghi lại âm thanh từ micrô bằng Python. Và tôi có mã sau:

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

Mã của tôi hoạt động tốt, nhưng khi tôi phát bản ghi của mình, tôi không nghe thấy bất kỳ âm thanh nào trong tệp đầu ra cuối cùng của mình ( file.wav).

Tại sao sự cố lại xảy ra ở đây và làm cách nào để khắc phục chúng?

Trả lời

1 Azr Sep 08 2020 at 03:31

Mã của bạn đang hoạt động tốt. Vấn đề bạn đang gặp phải là do quyền quản trị. Tệp âm thanh có dữ liệu 0 không đổi, do đó, bạn không thể nghe âm thanh trong tệp wav đã tạo. Tôi cho rằng thiết bị micrô của bạn đã được cài đặt và hoạt động bình thường. Nếu bạn không chắc chắn về trạng thái cài đặt âm thanh, hãy làm theo các bước sau:

MAC OS: System Preferences-> Sound-> Input và ở đó bạn có thể hình dung các thanh như tạo ra âm thanh. Đảm bảo rằng loại thiết bị đã chọn được Tích hợp sẵn.

Windos OS: Cài đặt âm thanh và kiểm tra Micrô bằng cách nhấp vào nghe thiết bị này, sau đó bạn có thể bỏ chọn vì nó sẽ lặp lại giọng nói của bạn với loa và sẽ tạo ra tiếng ồn lớn.

Có lẽ hầu hết bạn đang sử dụng Mac OS. Tôi gặp sự cố tương tự vì tôi đang sử dụng trình chỉnh sửa Atom để chạy mã python. Cố gắng chạy mã của bạn từ thiết bị đầu cuối của Mac OS (hoặc Power Shell nếu bạn đang sử dụng windows), (trong trường hợp cửa sổ bật lên xuất hiện để truy cập vào micrô trên Mac OS, hãy nhấn Ok). Đó là nó! mã của bạn sẽ tốt. Với tư cách là người thử nghiệm, vui lòng chạy mã bên dưới để kiểm tra xem bạn có thể hình dung âm thanh hay không và đảm bảo chạy nó thông qua Terminal (Không có trình chỉnh sửa hoặc 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()

Lưu tệp này dưới dạng voice.py vào một thư mục (giả sử AUDIO). Sau đó cd vào thư mục AUDIO từ lệnh terminal và sau đó thực thi nó bằng cách sử dụng:

python3 voice.py

hoặc là

python voice.py

tùy thuộc vào tên env python của bạn.

user0814 Sep 15 2020 at 09:00

Bằng cách sử dụng print(sd.query_devices()), tôi thấy danh sách các thiết bị như bên dưới:

  1. Microsoft Sound Mapper - Đầu vào, MME (2 đầu vào, 0 đầu ra)
  2. Micrô (AudioHubNano2D_V1.5, MME (2 đầu vào, 0 đầu ra)
  3. Micrô bên trong (Conexant S, MME (2 vào, 0 ra)
  4. ...

Tuy nhiên, nếu sử dụng device = 0, tôi vẫn có thể nhận âm thanh từ micrô USB, đây là thiết bị số 1. Có phải theo mặc định, tất cả tín hiệu âm thanh sẽ được chuyển đến Trình chỉnh sửa âm thanh không? Điều đó có nghĩa là nếu tôi sử dụng device = 0, tôi sẽ nhận được tất cả tín hiệu âm thanh từ tất cả các đầu vào âm thanh; và nếu tôi chỉ muốn đầu vào âm thanh từ một thiết bị cụ thể, tôi cần chọn số x của nó là device = x.

Tôi có một câu hỏi khác: có thể thu tín hiệu âm thanh từ thiết bị 1 và 2 trong một ứng dụng nhưng theo cách riêng biệt không?