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

如何将Streamlit中JS生成的Blob音频文件保存至目录供Python脚本调用

如何将Streamlit中JS生成的音频Blob保存到本地目录供Python使用

可以实现,核心思路是将JS中的音频Blob转换为Base64编码,传递给Python端后解码保存到本地。以下是具体修改步骤:

1. 修改JS代码,添加Blob转Base64并发送消息逻辑

在原JS的mediaRecorder.onstop函数中,新增将Blob转为Base64并发送给Python的代码,同时修正重新录音的逻辑:

mediaRecorder.onstop = (event) => {
    const audio = new Audio();
    audio.setAttribute("controls", "");
    $("#sound-clip").append(audio);
    $("#sound-clip").append("<br />");

    const blob = new Blob(chunks, { "type": "audio/wav; codecs=0" });
    audio.src = window.URL.createObjectURL(blob);

    // 新增:将Blob转为Base64并发送给Python
    const reader = new FileReader();
    reader.onloadend = function() {
        window.parent.postMessage({
            type: 'AUDIO_BLOB',
            data: reader.result.split(',')[1] // 移除base64前缀,只保留编码内容
        }, '*');
    };
    reader.readAsDataURL(blob);

    chunks = [];
};

// 修正按钮点击逻辑:补充重新启动录音的代码
$("#record").on("click", () => {
    if (recording) {
        mediaRecorder.stop();
        recording = false;
        $("#record").html("Record");
    } else {
        mediaRecorder.start();
        recording = true;
        $("#record").html("Stop");
    }
});

2. 修改Python代码,添加消息处理函数

在Python端定义处理音频消息的函数,接收Base64数据后解码保存为本地文件:

import base64
import os
import streamlit as st
from streamlit.components.v1 import html as components_html

def handle_audio_message(message):
    # 确保保存目录存在
    save_dir = "./recorded_audio"
    os.makedirs(save_dir, exist_ok=True)
    
    # 解码Base64数据并保存为WAV文件
    audio_data = base64.b64decode(message['data'])
    file_path = os.path.join(save_dir, "recorded_audio.wav")
    with open(file_path, 'wb') as f:
        f.write(audio_data)
    
    st.success(f"音频文件已保存到:{file_path}")

# 调用components.html并绑定消息处理函数
components_html(
    """
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <center>
            <p><button id="record">Record</button></p>
            <div id="sound-clip"></div>
        </center>
        <script src="https://code.jquery.com/jquery-3.3.1.min.js"
            integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
        <script>
            const audioCtx = new AudioContext();
            let recording = false;

            if (navigator.mediaDevices) {
                navigator.mediaDevices.getUserMedia({ "audio": true }).then((stream) => {
                    const mediaRecorder = new MediaRecorder(stream);
                    let chunks = [];

                    mediaRecorder.ondataavailable = (event) => {
                        chunks.push(event.data);
                    }

                    mediaRecorder.onstop = (event) => {
                        const audio = new Audio();
                        audio.setAttribute("controls", "");
                        $("#sound-clip").append(audio);
                        $("#sound-clip").append("<br />");

                        const blob = new Blob(chunks, { "type": "audio/wav; codecs=0" });
                        audio.src = window.URL.createObjectURL(blob);

                        // 将Blob转为Base64并发送给Python
                        const reader = new FileReader();
                        reader.onloadend = function() {
                            window.parent.postMessage({
                                type: 'AUDIO_BLOB',
                                data: reader.result.split(',')[1]
                            }, '*');
                        };
                        reader.readAsDataURL(blob);

                        chunks = [];
                    };

                    mediaRecorder.start();
                    recording = true;
                    $("#record").html("Stop");

                    $("#record").on("click", () => {
                        if (recording) {
                            mediaRecorder.stop();
                            recording = false;
                            $("#record").html("Record");
                        } else {
                            mediaRecorder.start();
                            recording = true;
                            $("#record").html("Stop");
                        }
                    });

                }).catch((err) => {
                    alert("Oh no! Your browser cannot access your computer's microphone.");
                });
            } else {
                alert("Oh no! Your browser cannot access your computer's microphone. Please update your browser.");
            }
        </script>
    </body>
    </html>
    """,
    on_message=handle_audio_message
)

注意事项

  • 可以自定义保存路径和文件名,确保目标目录存在,避免写入失败。
  • 消息发送时的*可以替换为你的Streamlit应用域名,提升安全性。
  • 运行前需确保浏览器已授予麦克风访问权限。

内容的提问来源于stack exchange,提问作者Ettore Carlessi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:05:28