pav*_*163 14 javascript python audio html5 flask
我目前正在实现一个Web应用程序,我希望用户录制一些音频然后我想要一个提交按钮来POST记录到服务器的mp3文件.
我的服务器(Flask)的主要路由'/'
是等待POST请求:
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == "GET":
return render_template('index.html', request="GET")
else:
print request.files
print request.form
print request.form['file']
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
handle_file(file)
return render_template('index.html', request="POST")
Run Code Online (Sandbox Code Playgroud)
这是我的JS代码:
这里有两个主要问题:
1)录制后下载mp3文件时,媒体播放器无法打开.在录制音频时,我似乎做错了.
2)当我print request.form
在收到POST请求后进入我的服务器时,我只得到这个:
ImmutableMultiDict([('file', u'')])
Run Code Online (Sandbox Code Playgroud)
并print request.form['file']
返回一个空行.
为什么会这样?POST请求有问题吗?
最后,我希望能够解码我发布的字符串以转换回mp3.我怎么做?
注意:这些都不能保持不变.任务是录制音频,然后将其POST到服务器.如果有更有效的方法,欢迎任何提示.另外,我不在乎文件是wav还是mp3.
注意:此答案仅处理 chrome 和 Firefox 中的当前实现。所有这些都可能很快发生变化。
我不确定您的服务器端代码是否有问题,但不要将二进制数据作为字符串发送。相反,使用 FormData 将其作为多部分发送(您将赢得 30% 的数据 + 完整性)。
此外,在您的 MediaRecorder 代码中,您似乎在每个dataavailable
事件中都完成了文件。这通常不是你想要的。
目前,没有浏览器本身支持录制为 mp3。
var mimes = ['mpeg', 'mpeg3', 'x-mpeg3', 'mp3', 'x-mpeg']
console.log(mimes.some(m=>MediaRecorder.isTypeSupported('audio/'+m)));
Run Code Online (Sandbox Code Playgroud)
因此,如果您想采用 MediaRecorder 方式,则必须使用opus
编解码器来容纳自己,封装在webm
chrome 或ogg
FF 中:
var enc = ['ogg', 'webm'];
var mime = "";
enc.forEach(e => {
if (!mime && MediaRecorder.isTypeSupported(`audio/${e};codecs="opus"`)) {
mime = `audio/${e};codecs="opus"`;
}
});
console.log(mime);
Run Code Online (Sandbox Code Playgroud)
所以现在我们有了正确的 mimeType,我们可以简单地告诉浏览器使用它:
var enc = ['ogg', 'webm'];
var extension = "",
mime = '';
enc.forEach(e => !extension &&
(mime = `audio/${e};codecs="opus"`) &&
MediaRecorder.isTypeSupported(mime) &&
(extension = e));
navigator.mediaDevices.getUserMedia({
audio: true
})
.then(stream => {
const chunks = [];
const rec = new MediaRecorder(stream, {
mimeType: mime // use the mimeType we've found
});
// this is not where we build the file, but where we store the chunks
rec.ondataavailable = e => chunks.push(e.data);
rec.onstop = e => {
// stop our gUM stream
stream.getTracks().forEach(t => t.stop());
// NOW create the file
let blob = new Blob(chunks, {
type: mime
});
// we could now send this blob :
// let form = new FormData();
// form.append('file', blob, 'filename.'+extension;
// ... declare xhr
// xhr.send(form);
// but we'll just fetch it for the demo :
let url = URL.createObjectURL(blob);
let au = new Audio(url);
au.controls = true;
document.body.appendChild(au);
au.play();
// and create an downloadable link from it :
let a = document.createElement('a');
a.href = url;
a.download = 'filename.' + extension;
a.innerHTML = 'download';
document.body.appendChild(a);
};
rec.start();
setTimeout(() => rec.stop(), 3000);
});
Run Code Online (Sandbox Code Playgroud)
或者我们也可以让浏览器默认执行所有操作。这只会是文件扩展名的问题......
现在,如果你喜欢wav
了opus
,你可以让MediaRecorder路程,只需使用WebAudioAPI,你胶物流传递给它,并从那里记录数据。在这里,为了简单起见,我将使用recorder.js库。
navigator.mediaDevices.getUserMedia({
audio: true
})
.then(stream => {
const aCtx = new AudioContext();
const streamSource = aCtx.createMediaStreamSource(stream);
var rec = new Recorder(streamSource);
rec.record();
setTimeout(() => {
stream.getTracks().forEach(t => t.stop());
rec.stop()
rec.exportWAV((blob) => {
// now we could send this blob with an FormData too
const url = URL.createObjectURL(blob);
let au = new Audio(url);
au.controls = true;
document.body.appendChild(au);
au.play();
let a = document.createElement('a');
a.href = url;
a.innerHTML = 'download';
a.download = 'filename.wav';
document.body.appendChild(a);
});
}, 3000);
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://rawgit.com/mattdiamond/Recorderjs/master/dist/recorder.js"></script>
Run Code Online (Sandbox Code Playgroud)
如果你真的想要一个 mp3,我想你可以使用网络上可用的 javascript lame 库之一。