HTML5将音频记录到文件中

我最终想要做的是从用户的麦克风记录,并上传文件到服务器时,他们完成。到目前为止,我已经使用以下代码创建了一个到元素的流:

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);
}

我该怎么做,从那个,到记录到一个文件?

287541 次浏览

有一个相当完整的录音演示可在: http://webaudiodemos.appspot.com/AudioRecorder/index.html

它允许你在浏览器中录制音频,然后你可以选择导出和下载你录制的内容。

您可以查看该页面的源代码以找到到 javascript 的链接,但是总的来说,有一个包含 exportWAV方法和 forceDownload方法的 Recorder对象。

这是一个简单的 JavaScript 声音记录器和编辑器,你可以试试。

Https://www.danieldemmel.me/jssoundrecorder/

可以从这里 下载

Https://github.com/daaain/jssoundrecorder

下面显示的代码是 Matt Diamond 的版权代码,可以在 MIT 许可下使用。原始文件在这里:

保存此文件并使用

(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>

这里有一个 gitHub 项目就是这样做的。

它以 mp3格式记录来自浏览器的音频,并自动保存到网络服务器。 Https://github.com/audior/recordmp3js

你亦可浏览有关实施的详细说明: Http://audior.ec/blog/recording-mp3-using-only-html5-and-javascript-recordmp3-js/

无需等待录制结束的实时流音频: Https://github.com/noamtcohen/audiostreamer

这个流 PCM 数据,但您可以修改代码流 mp3或 Speex

您可以使用来自 GitHub 的 唱片公司来实现您的需求。您可以从用户的麦克风记录,然后得到的文件作为一个 mp3。最后上传到你的服务器。

我在小样里用过这个。作者已经在这个位置提供了一个源代码示例: Https://github.com/audior/recordmp3js

演示在这里: Http://audior.ec/recordmp3js/

但目前只能在 Chrome 和 Firefox 上使用。

看起来效果很好,也很简单,希望这个能帮上忙。

更新 现在 Chrome 也支持来自 v47的 MediaRecorder API。同样要做的事情就是使用它(猜测本地记录方法一定比其他方法更快) ,这个 API 真的很容易使用,而且你会找到大量关于如何为服务器上传一个 blob 的答案。

演示 -可以在 Chrome 和 Firefox 中工作,故意省略了将 blob 推送到服务器..。

代码来源


目前,有三种方法可以做到这一点:

  1. 作为 wav[所有代码客户端,未压缩录制] ,您可以检出—— > 录音机。问题: 文件大小相当大,需要更多的上传带宽。
  2. 作为 mp3[所有代码客户端,压缩录制] ,您可以签出—— > Mp3Recorder。问题: 个人来说,我觉得质量不好,还有这个许可证的问题。
  3. 作为 ogg[客户端 + 服务器(node.js)代码,压缩录制,无限小时的录制没有浏览器崩溃] ,你可以检出—— > 记录作品,要么只客户端录制,或客户端-服务器捆绑,选择是你的。

    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 录制的小提琴演示。

这个问题非常古老,许多答案在当前版本的浏览器中不受支持。我试图使用简单的 htmlcssjs来创建音频录音机。我进一步使用电子中的相同代码来制作一个跨平台应用程序。

 <html>
<head>
<title>Recorder App</title>
    

</head>
<h2>Recorder App</h2>
<p>
<button type="button" id="record">Record</button>
<button type="button" id="stopRecord" disabled>Stop</button>
</p>
<p>
<audio id=recordedAudio></audio>
</p>


<script>
navigator.mediaDevices.getUserMedia({audio:true})
.then(stream => {handlerFunction(stream)})


function handlerFunction(stream) {
rec = new MediaRecorder(stream);
rec.ondataavailable = e => {
audioChunks.push(e.data);
if (rec.state == "inactive"){
let blob = new Blob(audioChunks,{type:'audio/mp3'});
recordedAudio.src = URL.createObjectURL(blob);
recordedAudio.controls=true;
recordedAudio.autoplay=true;
sendData(blob)
}
}
}
    

function sendData(data) {}
record.onclick = e => {
record.disabled = true;
record.style.backgroundColor = "blue"
stopRecord.disabled=false;
audioChunks = [];
rec.start();
}
stopRecord.onclick = e => {
record.disabled = false;
stop.disabled=true;
record.style.backgroundColor = "red"
rec.stop();
}
</script>
</html>

上面的代码可以在 Windows10,Mac,Linux 上运行,当然,也可以在 google chrome 和 firefox 上运行。