Html HTML5 将音频录制到文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16413063/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
HTML5 record audio to file
提问by Fibericon
What I ultimately want to do is record from the user's microphone, and upload the file to the server when they're done. So far, I've managed to make a stream to an element with the following code:
我最终想要做的是从用户的麦克风录音,并在完成后将文件上传到服务器。到目前为止,我已经设法使用以下代码为元素创建了一个流:
var audio = document.getElementById("audio_preview");
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
navigator.getUserMedia({video: false, audio: true}, function(stream) {
audio.src = window.URL.createObjectURL(stream);
}, onRecordFail);
var onRecordFail = function (e) {
console.log(e);
}
How do I go from that, to recording to a file?
我如何从那开始录制到文件?
采纳答案by Brad Montgomery
There is a fairly complete recording demo available at: http://webaudiodemos.appspot.com/AudioRecorder/index.html
有一个相当完整的录音演示:http: //webaudiodemos.appspot.com/AudioRecorder/index.html
It allows you to record audio in the browser, then gives you the option to export and download what you've recorded.
它允许您在浏览器中录制音频,然后您可以选择导出和下载您录制的内容。
You can view the source of that page to find links to the javascript, but to summarize, there's a Recorder
object that contains an exportWAV
method, and a forceDownload
method.
您可以查看该页面的源代码以查找指向 javascript 的链接,但总而言之,有一个Recorder
包含exportWAV
方法和forceDownload
方法的对象。
回答by Ankit Aranya
The code shown below is copyrighted to Matt Diamond and available for use under MIT license. The original files are here:
下面显示的代码版权归 Matt Diamond 所有,可在 MIT 许可下使用。原始文件在这里:
- http://webaudiodemos.appspot.com/AudioRecorder/index.html
- http://webaudiodemos.appspot.com/AudioRecorder/js/recorderjs/recorderWorker.js
- http://webaudiodemos.appspot.com/AudioRecorder/index.html
- http://webaudiodemos.appspot.com/AudioRecorder/js/recorderjs/recorderWorker.js
Save this files and use
保存此文件并使用
(function(window){
var WORKER_PATH = 'recorderWorker.js';
var Recorder = function(source, cfg){
var config = cfg || {};
var bufferLen = config.bufferLen || 4096;
this.context = source.context;
this.node = this.context.createScriptProcessor(bufferLen, 2, 2);
var worker = new Worker(config.workerPath || WORKER_PATH);
worker.postMessage({
command: 'init',
config: {
sampleRate: this.context.sampleRate
}
});
var recording = false,
currCallback;
this.node.onaudioprocess = function(e){
if (!recording) return;
worker.postMessage({
command: 'record',
buffer: [
e.inputBuffer.getChannelData(0),
e.inputBuffer.getChannelData(1)
]
});
}
this.configure = function(cfg){
for (var prop in cfg){
if (cfg.hasOwnProperty(prop)){
config[prop] = cfg[prop];
}
}
}
this.record = function(){
recording = true;
}
this.stop = function(){
recording = false;
}
this.clear = function(){
worker.postMessage({ command: 'clear' });
}
this.getBuffer = function(cb) {
currCallback = cb || config.callback;
worker.postMessage({ command: 'getBuffer' })
}
this.exportWAV = function(cb, type){
currCallback = cb || config.callback;
type = type || config.type || 'audio/wav';
if (!currCallback) throw new Error('Callback not set');
worker.postMessage({
command: 'exportWAV',
type: type
});
}
worker.onmessage = function(e){
var blob = e.data;
currCallback(blob);
}
source.connect(this.node);
this.node.connect(this.context.destination); //this should not be necessary
};
Recorder.forceDownload = function(blob, filename){
var url = (window.URL || window.webkitURL).createObjectURL(blob);
var link = window.document.createElement('a');
link.href = url;
link.download = filename || 'output.wav';
var click = document.createEvent("Event");
click.initEvent("click", true, true);
link.dispatchEvent(click);
}
window.Recorder = Recorder;
})(window);
//ADDITIONAL JS recorderWorker.js
var recLength = 0,
recBuffersL = [],
recBuffersR = [],
sampleRate;
this.onmessage = function(e){
switch(e.data.command){
case 'init':
init(e.data.config);
break;
case 'record':
record(e.data.buffer);
break;
case 'exportWAV':
exportWAV(e.data.type);
break;
case 'getBuffer':
getBuffer();
break;
case 'clear':
clear();
break;
}
};
function init(config){
sampleRate = config.sampleRate;
}
function record(inputBuffer){
recBuffersL.push(inputBuffer[0]);
recBuffersR.push(inputBuffer[1]);
recLength += inputBuffer[0].length;
}
function exportWAV(type){
var bufferL = mergeBuffers(recBuffersL, recLength);
var bufferR = mergeBuffers(recBuffersR, recLength);
var interleaved = interleave(bufferL, bufferR);
var dataview = encodeWAV(interleaved);
var audioBlob = new Blob([dataview], { type: type });
this.postMessage(audioBlob);
}
function getBuffer() {
var buffers = [];
buffers.push( mergeBuffers(recBuffersL, recLength) );
buffers.push( mergeBuffers(recBuffersR, recLength) );
this.postMessage(buffers);
}
function clear(){
recLength = 0;
recBuffersL = [];
recBuffersR = [];
}
function mergeBuffers(recBuffers, recLength){
var result = new Float32Array(recLength);
var offset = 0;
for (var i = 0; i < recBuffers.length; i++){
result.set(recBuffers[i], offset);
offset += recBuffers[i].length;
}
return result;
}
function interleave(inputL, inputR){
var length = inputL.length + inputR.length;
var result = new Float32Array(length);
var index = 0,
inputIndex = 0;
while (index < length){
result[index++] = inputL[inputIndex];
result[index++] = inputR[inputIndex];
inputIndex++;
}
return result;
}
function floatTo16BitPCM(output, offset, input){
for (var i = 0; i < input.length; i++, offset+=2){
var s = Math.max(-1, Math.min(1, input[i]));
output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
}
}
function writeString(view, offset, string){
for (var i = 0; i < string.length; i++){
view.setUint8(offset + i, string.charCodeAt(i));
}
}
function encodeWAV(samples){
var buffer = new ArrayBuffer(44 + samples.length * 2);
var view = new DataView(buffer);
/* RIFF identifier */
writeString(view, 0, 'RIFF');
/* file length */
view.setUint32(4, 32 + samples.length * 2, true);
/* RIFF type */
writeString(view, 8, 'WAVE');
/* format chunk identifier */
writeString(view, 12, 'fmt ');
/* format chunk length */
view.setUint32(16, 16, true);
/* sample format (raw) */
view.setUint16(20, 1, true);
/* channel count */
view.setUint16(22, 2, true);
/* sample rate */
view.setUint32(24, sampleRate, true);
/* byte rate (sample rate * block align) */
view.setUint32(28, sampleRate * 4, true);
/* block align (channel count * bytes per sample) */
view.setUint16(32, 4, true);
/* bits per sample */
view.setUint16(34, 16, true);
/* data chunk identifier */
writeString(view, 36, 'data');
/* data chunk length */
view.setUint32(40, samples.length * 2, true);
floatTo16BitPCM(view, 44, samples);
return view;
}
<html>
<body>
<audio controls autoplay></audio>
<script type="text/javascript" src="recorder.js"> </script>
<fieldset><legend>RECORD AUDIO</legend>
<input onclick="startRecording()" type="button" value="start recording" />
<input onclick="stopRecording()" type="button" value="stop recording and play" />
</fieldset>
<script>
var onFail = function(e) {
console.log('Rejected!', e);
};
var onSuccess = function(s) {
var context = new webkitAudioContext();
var mediaStreamSource = context.createMediaStreamSource(s);
recorder = new Recorder(mediaStreamSource);
recorder.record();
// audio loopback
// mediaStreamSource.connect(context.destination);
}
window.URL = window.URL || window.webkitURL;
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
var recorder;
var audio = document.querySelector('audio');
function startRecording() {
if (navigator.getUserMedia) {
navigator.getUserMedia({audio: true}, onSuccess, onFail);
} else {
console.log('navigator.getUserMedia not present');
}
}
function stopRecording() {
recorder.stop();
recorder.exportWAV(function(s) {
audio.src = window.URL.createObjectURL(s);
});
}
</script>
</body>
</html>
回答by mido
Updatenow Chrome also supports MediaRecorderAPI from v47. The same thing to do would be to use it( guessing native recording method is bound to be faster than work arounds), the API is really easy to use, and you would find tons of answers as to how to upload a blob for the server.
立即更新Chrome 还支持v47 中的 MediaRecorderAPI。同样的事情是使用它(猜测原生记录方法肯定比变通方法更快),API 真的很容易使用,你会找到很多关于如何为服务器上传 blob 的答案.
Demo- would work in Chrome and Firefox, intentionally left out pushing blob to server...
演示- 可以在 Chrome 和 Firefox 中工作,故意省略将 blob 推送到服务器......
Currently, there are three ways to do it:
目前,有以下三种方法:
- as
wav
[ all code client-side, uncompressed recording], you can check out --> Recorderjs. Problem: file size is quite big, more upload bandwidth required. - as
mp3
[ all code client-side, compressed recording], you can check out --> mp3Recorder. Problem: personally, I find the quality bad, also there is this licensing issue. as
ogg
[ client+ server(node.js
) code, compressed recording, infinite hours of recording without browser crash ], you can check out --> recordOpus, either only client-side recording, or client-server bundling, the choice is yours.ogg recording example( only firefox):
var mediaRecorder = new MediaRecorder(stream); mediaRecorder.start(); // to start recording. ... mediaRecorder.stop(); // to stop recording. mediaRecorder.ondataavailable = function(e) { // do something with the data. }
Fiddle Demofor ogg recording.
- 作为
wav
[所有代码客户端,未压缩录制],您可以查看--> Recorderjs。问题:文件很大,需要更多的上传带宽。 - 作为
mp3
[所有代码客户端,压缩录音],您可以查看--> mp3Recorder。问题:我个人觉得质量不好,还有这个授权问题。 作为
ogg
[客户端+服务器(node.js
)代码,压缩录音,无限小时录音,浏览器不崩溃],您可以查看--> recordOpus,要么只做客户端录音,要么客户端-服务器捆绑,选择权在您。ogg 录制示例(仅限 Firefox):
var mediaRecorder = new MediaRecorder(stream); mediaRecorder.start(); // to start recording. ... mediaRecorder.stop(); // to stop recording. mediaRecorder.ondataavailable = function(e) { // do something with the data. }
ogg 录制的小提琴演示。
回答by mido
This is a simple JavaScript sound recorder and editor. You can try it.
这是一个简单的 JavaScript 录音机和编辑器。你可以试试看。
https://www.danieldemmel.me/JSSoundRecorder/
https://www.danieldemmel.me/JSSoundRecorder/
Can downloadfrom here
可以从这里下载
回答by Remus Negrota
Here's a gitHub project that does just that.
这是一个 gitHub 项目,就是这样做的。
It records audio from the browser in mp3 format, and it automatically saves it to the webserver. https://github.com/Audior/Recordmp3js
它以 mp3 格式记录来自浏览器的音频,并自动将其保存到网络服务器。 https://github.com/Audior/Recordmp3js
You can also view a detailed explanation of the implementation: http://audior.ec/blog/recording-mp3-using-only-html5-and-javascript-recordmp3-js/
也可以查看详细的实现说明:http: //audior.ec/blog/recording-mp3-using-only-html5-and-javascript-recordmp3-js/
回答by Adithya Kumaranchath
You can use Recordmp3jsfrom GitHub to achieve your requirements. You can record from user's microphone and then get the file as an mp3. Finally upload it to your server.
您可以使用来自 GitHub 的Recordmp3js来实现您的要求。您可以从用户的麦克风录音,然后将文件作为 mp3 获取。最后上传到你的服务器。
I used this in my demo. There is a already a sample available with the source code by the author in this location : https://github.com/Audior/Recordmp3js
我在我的演示中使用了它。作者在这个位置已经有一个带有源代码的示例:https: //github.com/Audior/Recordmp3js
The demo is here: http://audior.ec/recordmp3js/
演示在这里:http: //audior.ec/recordmp3js/
But currently works only on Chrome and Firefox.
但目前仅适用于 Chrome 和 Firefox。
Seems to work fine and pretty simple. Hope this helps.
似乎工作正常而且非常简单。希望这可以帮助。
回答by noamtcohen
Stream audio in realtime without waiting for recording to end: https://github.com/noamtcohen/AudioStreamer
无需等待录制结束即可实时流式传输音频:https: //github.com/noamtcohen/AudioStreamer
This streams PCM data but you could modify the code to stream mp3 or Speex
这会传输 PCM 数据,但您可以修改代码以传输 mp3 或Speex