如何将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
相关产品推荐
相关产品推荐

