首页 > 解决方案 > 如何将 JS 音频 Blob 保存为文件,以便可以将其发送到 Flask API

问题描述

我正在为我的朋友构建一个应用程序,我需要录制音频并将其存储在服务器上。我已经用文本和图像成功地完成了它,但我不能让它适用于音频。

创建文件时我可能遗漏了一些东西(文件已创建但不可播放)。从 JS Blob 到实际文件的数据转换肯定有问题

我设法获得了音频 blob,甚至在 JS 中播放它。但是当我从 blob 创建一个文件时,它无法播放(我试图以相同的结果将其保存在本地 - 得到了文件但无法播放)。我还尝试以不同的格式保存它,但没有成功(wav、mp3)。所以问题必须在从blob到实际文件的转换中。对于文本和图像,它很简单,只需使用文件名保存它们就可以从 blob 创建文件。但我想音频并不是那么简单。

我的理解是我有一些二进制数据(JS Blob),可以保存为文件。但是对于音频,必须进行一些特殊的转换或编码,以便输出文件可以正常工作并且可以播放。

这是前端代码(我将它与一些变量一起使用,因为它是 Vue 组件的一部分)

this.mediaRecorder.addEventListener("stop", () => {
                // tried to save it as WAV with the same result got the file, but couldn't play it
                this.audioBlob = new Blob(this.audioChunks, { 'type' : 'audio/mpeg-3' })
                
                //debugging - playing back the sound in the browser works fine
                const audioUrl = URL.createObjectURL(this.audioBlob);
                const audio = new Audio(audioUrl);
                audio.play();
                
                //adding the blob to the request
                let filename = this.$store.state.counter + "-" + this.$store.state.step
                const formData = new FormData();
                formData.append('file', this.audioBlob, `${filename}.mp3`);
                const config = {
                    headers: { 'content-type': 'multipart/form-data' }
                }
                //sending it to my Flask API (xxx is the name of the folder it gets saved to on the server)
                this.$axios.post('http://localhost:5000/api/v1/file/upload/xxx', formData, config)
            })

这是我在服务器上的端点

@app.route('/api/v1/file/upload/<test_id>', methods=['POST'])
def upload_file(test_id):
    uploaded_file = request.files['file']
    filename = secure_filename(uploaded_file.filename)
    if filename != '':
        uploaded_file.save(os.path.join(app.config['UPLOAD_PATH'], test_id, filename))
    return jsonify({'message': 'file saved'})

这是整个录音代码片段

navigator.mediaDevices.getUserMedia({ audio: true })
        .then(stream => {
            this.mediaRecorder = new MediaRecorder(stream);
            // audio.srcObject = stream
            
            this.mediaRecorder.start();

            this.mediaRecorder.addEventListener("dataavailable", event => {
                this.audioChunks.push(event.data)
            })
            this.mediaRecorder.addEventListener("stop", () => {
                this.audioBlob = new Blob(this.audioChunks, { 'type' : 'audio/mpeg-3' })
                
                //debugging - playing back the sound in the browser works fine
                const audioUrl = URL.createObjectURL(this.audioBlob);
                const audio = new Audio(audioUrl);
                audio.play();
                
                //adding the blob to the request
                let filename = this.$store.state.counter + "-" + this.$store.state.step
                const formData = new FormData();
                formData.append('file', this.audioBlob, `${filename}.mp3`);
                const config = {
                    headers: { 'content-type': 'multipart/form-data' }
                }
                //sending it to my Flask API (xxx is the name of the folder it gets saved to on the server)
                this.$axios.post('http://localhost:5000/api/v1/file/upload/xxx', formData, config)
            })
        })

标签: javascriptvue.jsfileaudioblob

解决方案


推荐阅读