Javascriptでマイクから録音、オシロスコープ表示、ダウンロード、POST、再生
「マイクの使用を開始」ボタンを押すと、マイクをアクティブにし、マイクから音を拾ってオシロスコープのように現在の音声を表示します。
次に「録音の開始」ボタンを押すと録音を開始します。
ソースコード
<div style="display:flex;flex-wrap:wrap;">
<div>
<button id="MicOn" style="font-size:20px;">マイクの使用を開始</button>
</div>
<div>
<button id="RecStart" style="font-size:20px;">録音開始</button>
<button id="RecStop" style="font-size:20px;">録音停止</button>
</div>
<div style="width:100%;max-width:400px;min-width:280px;">
<audio id="AudioPlay" controls playsinline style="width:100%;"></audio>
</div>
<div style="width:100%;max-width:800px;min-width:280px;">
<div style="width:80%;padding-top:20%;padding-bottom:0;padding-left:0;padding-right:0;margin:0;position:relative;box-sizing:border-box;">
<div style="top:0;right:0;bottom:0;left:0;position:absolute;margin:0;display:block;box-sizing:border-box;">
<canvas id="AudioWave" style="margin:0;padding:0;width:100%;height:100%;display:block;box-sizing:border-box;"></canvas>
</div>
</div>
</div>
</div>
<script>
var TMamMicRec=function(micOnBtn,recStartBtn,recStopBtn,audioPlay,audioWave){
this.micOnBtn =micOnBtn; //マイク使用許可ボタン
this.recStartBtn=recStartBtn;//録音開始ボタン
this.recStopBtn =recStopBtn; //録音停止ボタン
this.audioPlay=audioPlay; //audioタグ
this.audioWave=audioWave; //wave表示用canvas
this.audioWaveCtx=this.audioWave.getContext('2d', {willReadFrequently:true});
this.stream=null;
this.mediaRecorder=null;
this.chunks=[];
this.recStartBtn.setAttribute("disabled",true);
this.recStopBtn.setAttribute("disabled",true);
this.type=null;
this.audioCtx=null;
this.audioSource=null;
this.audioAnalyser=null;
this.audioBufLen=0;
this.audioBuf=null;
this.drawWave=function(){ //波形を描く
let drawVisual=window.requestAnimationFrame(this.drawWave.bind(this));
this.audioAnalyser.getByteTimeDomainData(this.audioBuf);
//0~255 128(無音)
//console.log(this.audioBuf);
this.audioWaveCtx.fillStyle='rgb(200,200,200)';
this.audioWaveCtx.fillRect(0,0,this.audioBufLen,this.audioBufLen/4);
this.audioWaveCtx.lineWidth=this.audioBufLen/256;
this.audioWaveCtx.StrokeStyle='rgb(0,0,0)';
this.audioWaveCtx.beginPath();
let y=this.audioBufLen/4/256;
for(let i=0;i<this.audioBufLen;i++){
if(i===0){
this.audioWaveCtx.moveTo(i,this.audioBuf[i]*y);
}else{
this.audioWaveCtx.lineTo(i,this.audioBuf[i]*y);
}
}
this.audioWaveCtx.stroke();
}
this.micOnBtn.addEventListener("click",function(){
if(navigator.mediaDevices==undefined){
alert('未対応ブラウザ 又は HTTPS接続していません');
return;
}
navigator.mediaDevices.getUserMedia({audio:true})
.then(function(stream){
this.stream=stream;
if(this.audioCtx==null){
let AudioContext = window.AudioContext || window.webkitAudioContext;
this.audioCtx=new AudioContext;
this.audioSource=this.audioCtx.createMediaStreamSource(this.stream);
this.audioAnalyser=this.audioCtx.createAnalyser();
this.audioAnalyser.fftSize=2048;
this.audioSource.connect(this.audioAnalyser);
this.audioBufLen=this.audioAnalyser.fftSize;
this.audioWave.setAttribute("width",this.audioBufLen+'px');
this.audioWave.setAttribute("height",this.audioBufLen/4+'px');
this.audioBuf=new Uint8Array(this.audioBufLen);
this.audioAnalyser.getByteTimeDomainData(this.audioBuf);
this.drawWave();
}
this.mediaRecorder=new MediaRecorder(this.stream);
this.mediaRecorder.addEventListener("dataavailable",function(event){
this.chunks.push(event.data);
}.bind(this));
this.mediaRecorder.addEventListener("stop",function(e){
// audio/webm;codecs=opus , audio/ogg; codecs=opus 等
this.type=this.chunks[0].type;
//console.log(this.type);
let blob=new Blob(this.chunks,{"type":this.type});
this.chunks=[];
/*
//ファイルのダウンロードを行う場合
let aTag=document.createElement("a");
aTag.href=URL.createObjectURL(blob);
aTag.download="a.mp4";
aTag.click();
*/
/*
//DataURI変換して<input type="hidden">のvalueに入れてPOSTでサーバーに送る場合
let fileReaderPost=new FileReader();
fileReaderPost.addEventListener("load",function(event){
let formTag=document.createElement('form');
formTag.method="post";
formTag.action="post.php";//POST先URL
let inputTag=document.createElement('input');
inputTag.type="hidden";
inputTag.name="record";//POST時の名前
inputTag.value=event.target.result;//POST時の値
formTag.appendChild(inputTag);
document.body.appendChild(formTag);
formTag.submit();//POST実行する
}.bind(this));
fileReaderPost.readAsDataURL(blob);
*/
//録音したblobをDataURIスキームに変換して<audio>タグでそのまま再生する場合
let fileReaderAudio=new FileReader();
fileReaderAudio.addEventListener("load",function(event){
this.audioPlay.pause();
this.audioPlay.currentTime=0;
this.audioPlay.setAttribute("src",event.target.result);
this.audioPlay.load();
this.audioPlay.play();
}.bind(this));
fileReaderAudio.readAsDataURL(blob);
this.recStartBtn.removeAttribute("disabled");
this.recStopBtn.setAttribute("disabled",true);
}.bind(this));
this.recStartBtn.removeAttribute("disabled");
this.micOnBtn.setAttribute("disabled",true);
}.bind(this)).catch(function(e){
console.log(e);
document.getElementById("alert").innerHTML=e;
}.bind(this));
}.bind(this));
this.recStartBtn.addEventListener("click",function(){
this.recStartBtn.setAttribute("disabled", true);
this.recStopBtn.removeAttribute("disabled");
this.mediaRecorder.start();
}.bind(this));
this.recStopBtn.addEventListener("click",function(){
this.mediaRecorder.stop();
}.bind(this));
}
window.addEventListener("DOMContentLoaded",function(){
mamMicRec=new TMamMicRec(
document.getElementById("MicOn"),
document.getElementById("RecStart"),
document.getElementById("RecStop"),
document.getElementById("AudioPlay"),
document.getElementById("AudioWave"),
);
});
</script>
