You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python能否转换音频数据为文件?Flask服务端音频文件生成异常求助

问题分析

当前生成的temp.webm无法播放,核心原因有两点:

  1. 前端每次发送的是MediaRecorder生成的音频片段,后端直接将片段追加写入文件,破坏了WebM容器的结构,导致文件损坏。
  2. 若要生成可播放的WAV文件,需要将WebM格式的音频解码后重新编码为WAV。

解决方案

一、先修复WebM文件完整性(确保生成可播放的WebM)

前端代码调整(voice.js + fetch.js)

MediaRecorder的dataavailable事件返回的是媒体片段,需将所有片段合并为完整Blob后再一次性上传,而非分批发送:

// voice.js
let mediaRecorder;
const voiceChunks = [];

navigator.mediaDevices
    .getUserMedia({ audio: true })
    .then((mediaStream) => {
        mediaRecorder = new MediaRecorder(mediaStream, {
            mimeType: 'audio/webm; codecs=opus' // 明确编码,提升兼容性
        });

        mediaRecorder.start();

        mediaRecorder.addEventListener("dataavailable", (e) => {
            voiceChunks.push(e.data);
            // 示例:录制30秒后自动停止并上传
            setTimeout(() => {
                mediaRecorder.stop();
            }, 30000);
        });

        mediaRecorder.addEventListener("stop", () => {
            const fullBlob = new Blob(voiceChunks, { type: 'audio/webm' });
            uploadAudio(fullBlob);
        });
    });

// fetch.js 改为上传函数
function uploadAudio(blob) {
    fetch('http://localhost:5000/audio', {
        method: 'post',
        body: blob
    }).then(res => console.log('上传完成'))
      .catch(err => console.error('上传失败', err));
}

后端代码调整(server.py)

现在后端收到完整的WebM文件,直接写入即可:

from flask import Flask, render_template, request, make_response

app = Flask(__name__)

@app.route("/")
def hello_world():
    return render_template('index.html')

@app.route("/<name>.js")
def getJs(name):
    return render_template(f'{name}.js')

@app.route("/audio", methods=['post'])
def audio():
    with open('recording.webm', 'wb') as f:
        f.write(request.data)
    return make_response('', 200)

if __name__ == '__main__':
    app.run(debug=True)

此时recording.webm可正常播放。


二、将WebM转换为WAV格式

使用pydub库(依赖ffmpeg)完成转码:

1. 安装依赖

pip install pydub

同时安装ffmpeg:

  • Windows:下载ffmpeg并添加至系统PATH
  • macOS:brew install ffmpeg
  • Linux:sudo apt install ffmpeg

2. 修改后端代码添加转码逻辑

from flask import Flask, render_template, request, make_response
from pydub import AudioSegment

app = Flask(__name__)

@app.route("/")
def hello_world():
    return render_template('index.html')

@app.route("/<name>.js")
def getJs(name):
    return render_template(f'{name}.js')

@app.route("/audio", methods=['post'])
def audio():
    # 保存完整WebM文件
    with open('recording.webm', 'wb') as f:
        f.write(request.data)
    
    # 转码为WAV
    audio = AudioSegment.from_file('recording.webm', format='webm')
    audio.export('voice.wav', format='wav')
    
    return make_response('', 200)

if __name__ == '__main__':
    app.run(debug=True)

额外优化:实时分批上传场景

若需实时发送片段,后端需维护客户端的音频片段队列,合并后再转码:

from flask import Flask, render_template, request, make_response, session
from pydub import AudioSegment
import os

app = Flask(__name__)
app.secret_key = 'your_secret_key'
user_audio_chunks = {}  # 存储各用户的音频片段

@app.route("/")
def hello_world():
    if 'user_id' not in session:
        session['user_id'] = os.urandom(16).hex()
    return render_template('index.html')

@app.route("/<name>.js")
def getJs(name):
    return render_template(f'{name}.js')

@app.route("/audio", methods=['post'])
def audio():
    user_id = session['user_id']
    user_audio_chunks.setdefault(user_id, []).append(request.data)
    
    # 示例:累计5个片段后合并转码
    if len(user_audio_chunks[user_id]) >= 5:
        temp_webm = f'{user_id}_temp.webm'
        with open(temp_webm, 'wb') as f:
            for chunk in user_audio_chunks[user_id]:
                f.write(chunk)
        
        audio = AudioSegment.from_file(temp_webm, format='webm')
        audio.export(f'{user_id}_voice.wav', format='wav')
        
        user_audio_chunks[user_id] = []  # 清空队列
    
    return make_response('', 200)

if __name__ == '__main__':
    app.run(debug=True)

内容的提问来源于stack exchange,提问作者조성호

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 23:17:19