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>