将PyAudio麦克风输入流转换为mp3

3

我正在寻找直接从麦克风录制并编码为mp3文件的方法,而不需要先保存为中间wav文件。有很多关于保存为wav文件的示例以及将wav文件转换为mp3的示例,但我找不到直接从麦克风保存mp3的方法。例如,我正在使用以下在网络上找到的示例来录制wav文件。

希望获得关于如何将frames列表(pyaudio流读取)直接转换为mp3的建议。或者,通过ffmpeg直接将pyaudio麦克风输入流传输到mp3,而无需使用列表/数组填充读取数据。非常感谢!

import pyaudio
import wave

# the file name output you want to record into
filename = "recorded.wav"
# set the chunk size of 1024 samples
chunk = 1024
# sample format
FORMAT = pyaudio.paInt16
# mono, change to 2 if you want stereo
channels = 1
# 44100 samples per second
sample_rate = 44100
record_seconds = 5
# initialize PyAudio object
p = pyaudio.PyAudio()
# open stream object as input & output
stream = p.open(format=FORMAT,
                channels=channels,
                rate=sample_rate,
                input=True,
                output=True,
                frames_per_buffer=chunk)
frames = []
print("Recording...")
for i in range(int(44100 / chunk * record_seconds)):
    data = stream.read(chunk)
    frames.append(data)
print("Finished recording.")
# stop and close stream
stream.stop_stream()
stream.close()
# terminate pyaudio object
p.terminate()
# save audio file
# open the file in 'write bytes' mode
wf = wave.open(filename, "wb")
# set the channels
wf.setnchannels(channels)
# set the sample format
wf.setsampwidth(p.get_sample_size(FORMAT))
# set the sample rate
wf.setframerate(sample_rate)
# write the frames as bytes
wf.writeframes(b"".join(frames))
# close the file
wf.close()

我应该说我正在使用Python 3.8.1和Windows10。 - chrismec
1个回答

2
我找到了一种方法,可以使用来自Rarewares的lame 3.1二进制文件将pyaudio pcm流转换为mp3,而无需保存到中间wav文件。我相信也可以使用ffmpeg完成此操作,但由于ffmpeg使用lame进行mp3编码,因此我只想专注于lame。
要直接将原始pcm数组转换为mp3,请删除所有波形文件操作,并替换为以下内容。这会将数据全部输入到lame中。
raw_pcm = b''.join(frames)
l = subprocess.Popen("lame - -r -m m recorded.mp3", stdin=subprocess.PIPE)
l.communicate(input=raw_pcm)

为了在读取时将pcm数据传输到lame,我使用了以下方法。如果您愿意,您可以在流回调中执行此操作。

l = subprocess.Popen("lame - -r -m m recorded.mp3", stdin=subprocess.PIPE)
for i in range(int(44100 / chunk * record_seconds)):
    l.stdin.write(stream.read(chunk))

请注意,无论哪种方式,lame都不会在数据传输完成之前开始编码。当在每个流读取时传输数据时,我认为编码会立即开始,但实际情况并非如此。

另外,如果没有读取stdout和stderr缓冲区,使用.stdin.write可能会导致一些问题。这是我需要进一步研究的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接