如何使用Python在实时中将WAV转换为MP3?

11

我有以下代码来获取麦克风的音频:

import pyaudio
p = pyaudio.PyAudio()
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 1024*10
RECORD_SECONDS = 10
stream = p.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                frames_per_buffer=CHUNK)
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
    data = stream.read(CHUNK)
    send_via_socket(data) # function to send each frame to remote system

这段代码运行正常。但是每个数据帧的大小为4kb。这意味着发送1秒音频数据需要40kb的互联网数据。 当我把这10个帧(1秒音频)保存到磁盘并使用pdub模块转换为mp3时,只有6kb的数据量。 我该如何在通过套接字发送之前将每个wav帧转换为mp3?(我只需要减小帧的大小以节省网络用量)。 例如:

for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
    data = stream.read(CHUNK)  # data =4kb
    mp3_frame = wav_to_mp3(data) # mp3_frame should be 1kb or less
    send_via_socket(mp3_frame) # function to send each frame to remote system

7
我只是简单地在谷歌上搜索了“mp3编码器python”,就发现了这个链接:http://pymedia.org/tut/recode_audio.html。看起来这正是你想要的。 - selbie
4
为什么不将这个转换成答案并领取悬赏? - jimm101
4
@jimm101 - 我所做的只是在谷歌上搜索答案。如果我的回答没有花费超过10秒钟,没有增加任何见解,也没有展示任何相关的经验/知识,除了我的精通互联网搜索技巧之外,那么期望得到分数就显得有些无足轻重了 :) 如果我经常使用Python进行编码并实现音频代码,那可能会是完全不同的情况。但对于这个问题,我所做的只是在谷歌上搜索答案... - selbie
2
@jimm101,你能给个例子吗?我试过pydub、pyffmpg和pyaudio,但都没有实时编码的选项。每个库都只有将音频写入文件的选项。 - open source guy
1
@selbie 我联系了Pymedia的作者,他说使用该库无法实现这个功能。 - open source guy
显示剩余5条评论
2个回答

2

我能够利用flaskffmpeg找到一个可行的解决方案...

import select
import subprocess

import numpy

from flask import Flask
from flask import Response

app = Flask(__name__)


def get_microphone_audio(num_samples):
    # TODO: Add the above microphone code. 
    audio = numpy.random.rand(num_samples).astype(numpy.float32) * 2 - 1
    assert audio.max() <= 1.0
    assert audio.min() >= -1.0
    assert audio.dtype == numpy.float32
    return audio


def response():
    pipe = subprocess.Popen(
        'ffmpeg -f f32le -acodec pcm_f32le -ar 24000 -ac 1 -i pipe: -f mp3 pipe:'
        .split(),
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE)
    poll = select.poll()
    poll.register(pipe.stdout, select.POLLIN)
    while True:
        pipe.stdin.write(get_synthetic_audio(24000).tobytes())
        while poll.poll(0):
            yield pipe.stdout.readline()


@app.route('/stream.mp3', methods=['GET'])
def stream():
    return Response(
        response(),
        headers={
            # NOTE: Ensure stream is not cached.
            'Cache-Control': 'no-cache, no-store, must-revalidate',
            'Pragma': 'no-cache',
            'Expires': '0',
        },
        mimetype='audio/mpeg')


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8000, debug=True)

这个解决方案允许实时流媒体,并支持Chrome,Firefox和Safari。

这个解决方案也适用于类似问题:如何在Python中给定NumPy数组流式传输MP3块?


交叉引用:Flask将Pyaudio发送到浏览器 - Markus
不明白为什么你需要使用flask模块来管理音频波形和MP3文件。 - ssoto

1

尝试使用Python音频工具。我认为它将有助于您流式传输所需的音频文件。


Python API文档(与命令行相对)位于http://audiotools.sourceforge.net/programming/index.html。 - Dragon

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