-
-
Save mason276752/57bc202dddb08ed14117c699d4fee702 to your computer and use it in GitHub Desktop.
一个使用 HTML5 录音的例子(网上看到的,收藏下)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html xmlns="http://www.w3.org/1999/xhtml"> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
<title></title> | |
</head> | |
<body> | |
<div> | |
<audio controls autoplay></audio> | |
<input onclick="startRecording()" type="button" value="录音" /> | |
<input onclick="stopRecording()" type="button" value="停止" /> | |
<input onclick="playRecording()" type="button" value="播放" /> | |
<input onclick="uploadAudio()" type="button" value="提交" /> | |
</div> | |
<script type="text/javascript" src="HZRecorder.js"></script> | |
<script> | |
var recorder; | |
var audio = document.querySelector('audio'); | |
function startRecording() { | |
HZRecorder.get(function (rec) { | |
recorder = rec; | |
recorder.start(); | |
}); | |
} | |
function stopRecording() { | |
recorder.stop(); | |
} | |
function playRecording() { | |
recorder.play(audio); | |
} | |
function uploadAudio() { | |
recorder.upload("Handler1.ashx", function (state, e) { | |
switch (state) { | |
case 'uploading': | |
//var percentComplete = Math.round(e.loaded * 100 / e.total) + '%'; | |
break; | |
case 'ok': | |
//alert(e.target.responseText); | |
alert("上传成功"); | |
break; | |
case 'error': | |
alert("上传失败"); | |
break; | |
case 'cancel': | |
alert("上传被取消"); | |
break; | |
} | |
}); | |
} | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (window) { | |
//兼容 | |
window.URL = window.URL || window.webkitURL; | |
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; | |
var HZRecorder = function (stream, config) { | |
config = config || {}; | |
config.sampleBits = config.sampleBits || 8; //采样数位 8, 16 | |
config.sampleRate = config.sampleRate || (44100 / 6); //采样率(1/6 44100) | |
var context = new (window.webkitAudioContext || window.AudioContext)(); | |
var audioInput = context.createMediaStreamSource(stream); | |
var createScript = context.createScriptProcessor || context.createJavaScriptNode; | |
var recorder = createScript.apply(context, [4096, 1, 1]); | |
var audioData = { | |
size: 0 //录音文件长度 | |
, buffer: [] //录音缓存 | |
, inputSampleRate: context.sampleRate //输入采样率 | |
, inputSampleBits: 16 //输入采样数位 8, 16 | |
, outputSampleRate: config.sampleRate //输出采样率 | |
, oututSampleBits: config.sampleBits //输出采样数位 8, 16 | |
, input: function (data) { | |
this.buffer.push(new Float32Array(data)); | |
this.size += data.length; | |
} | |
, compress: function () { //合并压缩 | |
//合并 | |
var data = new Float32Array(this.size); | |
var offset = 0; | |
for (var i = 0; i < this.buffer.length; i++) { | |
data.set(this.buffer[i], offset); | |
offset += this.buffer[i].length; | |
} | |
//压缩 | |
var compression = parseInt(this.inputSampleRate / this.outputSampleRate); | |
var length = data.length / compression; | |
var result = new Float32Array(length); | |
var index = 0, j = 0; | |
while (index < length) { | |
result[index] = data[j]; | |
j += compression; | |
index++; | |
} | |
return result; | |
} | |
, encodeWAV: function () { | |
var sampleRate = Math.min(this.inputSampleRate, this.outputSampleRate); | |
var sampleBits = Math.min(this.inputSampleBits, this.oututSampleBits); | |
var bytes = this.compress(); | |
var dataLength = bytes.length * (sampleBits / 8); | |
var buffer = new ArrayBuffer(44 + dataLength); | |
var data = new DataView(buffer); | |
var channelCount = 1;//单声道 | |
var offset = 0; | |
var writeString = function (str) { | |
for (var i = 0; i < str.length; i++) { | |
data.setUint8(offset + i, str.charCodeAt(i)); | |
} | |
} | |
// 资源交换文件标识符 | |
writeString('RIFF'); offset += 4; | |
// 下个地址开始到文件尾总字节数,即文件大小-8 | |
data.setUint32(offset, 36 + dataLength, true); offset += 4; | |
// WAV文件标志 | |
writeString('WAVE'); offset += 4; | |
// 波形格式标志 | |
writeString('fmt '); offset += 4; | |
// 过滤字节,一般为 0x10 = 16 | |
data.setUint32(offset, 16, true); offset += 4; | |
// 格式类别 (PCM形式采样数据) | |
data.setUint16(offset, 1, true); offset += 2; | |
// 通道数 | |
data.setUint16(offset, channelCount, true); offset += 2; | |
// 采样率,每秒样本数,表示每个通道的播放速度 | |
data.setUint32(offset, sampleRate, true); offset += 4; | |
// 波形数据传输率 (每秒平均字节数) 单声道×每秒数据位数×每样本数据位/8 | |
data.setUint32(offset, channelCount * sampleRate * (sampleBits / 8), true); offset += 4; | |
// 快数据调整数 采样一次占用字节数 单声道×每样本的数据位数/8 | |
data.setUint16(offset, channelCount * (sampleBits / 8), true); offset += 2; | |
// 每样本数据位数 | |
data.setUint16(offset, sampleBits, true); offset += 2; | |
// 数据标识符 | |
writeString('data'); offset += 4; | |
// 采样数据总数,即数据总大小-44 | |
data.setUint32(offset, dataLength, true); offset += 4; | |
// 写入采样数据 | |
if (sampleBits === 8) { | |
for (var i = 0; i < bytes.length; i++, offset++) { | |
var s = Math.max(-1, Math.min(1, bytes[i])); | |
var val = s < 0 ? s * 0x8000 : s * 0x7FFF; | |
val = parseInt(255 / (65535 / (val + 32768))); | |
data.setInt8(offset, val, true); | |
} | |
} else { | |
for (var i = 0; i < bytes.length; i++, offset += 2) { | |
var s = Math.max(-1, Math.min(1, bytes[i])); | |
data.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true); | |
} | |
} | |
return new Blob([data], { type: 'audio/wav' }); | |
} | |
}; | |
//开始录音 | |
this.start = function () { | |
audioInput.connect(recorder); | |
recorder.connect(context.destination); | |
} | |
//停止 | |
this.stop = function () { | |
recorder.disconnect(); | |
} | |
//获取音频文件 | |
this.getBlob = function () { | |
this.stop(); | |
return audioData.encodeWAV(); | |
} | |
//回放 | |
this.play = function (audio) { | |
audio.src = window.URL.createObjectURL(this.getBlob()); | |
} | |
//上传 | |
this.upload = function (url, callback) { | |
var fd = new FormData(); | |
fd.append("audioData", this.getBlob()); | |
var xhr = new XMLHttpRequest(); | |
if (callback) { | |
xhr.upload.addEventListener("progress", function (e) { | |
callback('uploading', e); | |
}, false); | |
xhr.addEventListener("load", function (e) { | |
callback('ok', e); | |
}, false); | |
xhr.addEventListener("error", function (e) { | |
callback('error', e); | |
}, false); | |
xhr.addEventListener("abort", function (e) { | |
callback('cancel', e); | |
}, false); | |
} | |
xhr.open("POST", url); | |
xhr.send(fd); | |
} | |
//音频采集 | |
recorder.onaudioprocess = function (e) { | |
audioData.input(e.inputBuffer.getChannelData(0)); | |
//record(e.inputBuffer.getChannelData(0)); | |
} | |
}; | |
//抛出异常 | |
HZRecorder.throwError = function (message) { | |
alert(message); | |
throw new function () { this.toString = function () { return message; } } | |
} | |
//是否支持录音 | |
HZRecorder.canRecording = (navigator.getUserMedia != null); | |
//获取录音机 | |
HZRecorder.get = function (callback, config) { | |
if (callback) { | |
if (navigator.getUserMedia) { | |
navigator.getUserMedia( | |
{ audio: true } //只启用音频 | |
, function (stream) { | |
var rec = new HZRecorder(stream, config); | |
callback(rec); | |
} | |
, function (error) { | |
switch (error.code || error.name) { | |
case 'PERMISSION_DENIED': | |
case 'PermissionDeniedError': | |
HZRecorder.throwError('用户拒绝提供信息。'); | |
break; | |
case 'NOT_SUPPORTED_ERROR': | |
case 'NotSupportedError': | |
HZRecorder.throwError('浏览器不支持硬件设备。'); | |
break; | |
case 'MANDATORY_UNSATISFIED_ERROR': | |
case 'MandatoryUnsatisfiedError': | |
HZRecorder.throwError('无法发现指定的硬件设备。'); | |
break; | |
default: | |
HZRecorder.throwError('无法打开麦克风。异常信息:' + (error.code || error.name)); | |
break; | |
} | |
}); | |
} else { | |
HZRecorder.throwErr('当前浏览器不支持录音功能。'); return; | |
} | |
} | |
} | |
window.HZRecorder = HZRecorder; | |
})(window); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment