2016-07-14 5 views
1

웹 페이지에 녹음하기위한 테스트 코드를 작성했는데 내 보낸 wav 파일을 재생할 수 있지만 완전히 잘못되었거나 몇 가지 의미없는 소리가 들었고 VLC의 재생 시간이 올바르지 않습니다. 코드에 오류가 있는지 확인하십시오.HTML5 녹음이 작동하지 않습니다.

<html> 

<head></head> 

<body> 
    <script src="https://code.jquery.com/jquery-3.1.0.min.js"></script> 
    <button id='start'>Start</button> 
    <button id='stop'>Stop</button> 
    <button id='export'>Export</button> 
    <script> 
    var isRecording = false; 
    var buf = []; 
    var totalLen = 0; 
    var channelNum = 1; 
    var sampleRate = 48000; 

    $('#start').click(function() 
    { 
    window.AudioContext = window.AudioContext || window.webkitAudioContext; 
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia; 
    window.URL = window.URL || window.webkitURL; 

    var cxt = new AudioContext(); 
    isRecording = true; 

    navigator.getUserMedia({audio:true}, function(stream){ 
     var streamNode = cxt.createMediaStreamSource(stream); 
     var processNode = (cxt.createScriptProcessor || cxt.createJavaScriptNode).call(cxt, 1024 * 2, channelNum, channelNum); 
     processNode.onaudioprocess = function(e){ 
     if(!isRecording) return; 

     var f = e.inputBuffer; 
     var cdata = f.getChannelData(channelNum -1); 
     buf.push(cdata); 
     totalLen += cdata.length; 
     }; 
     streamNode.connect(processNode); 
     processNode.connect(cxt.destination); 

    }, function(){}); 
    }); 

    $('#stop').click(function(){ 
    isRecording = false; 
    }); 

    $('#export').click(function(){ 
    var oneBuf = new Float32Array(totalLen); 
    var offset = 0; 
    for(var i=0;i<buf.length;++i){ 
     oneBuf.set(buf[i], offset); 
     offset += buf[i].length; 
    } 

    var encodedBuf = encodeWAV(oneBuf); 
    var blob = new Blob([encodedBuf], {type:'audio/wav'}); 
    console.log(encodedBuf); 

    var url = URL.createObjectURL(blob); 
    var hf = document.createElement('a'); 
    hf.download = '1.wav'; 
    hf.innerHTML = hf.download; 
    hf.href = url; 
    $('body').append(hf); 
    }); 

    function encodeWAV(samples){ 
    var arr = new ArrayBuffer(44 + samples.length * 2); 
    var view = new DataView(arr); 

    /* RIFF identifier */ 
    writeString(view, 0, 'RIFF'); 
    /* RIFF chunk length */ 
    view.setUint32(4, 36 + 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, channelNum, 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, channelNum * 2, 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); 
    console.log('my samplerate:%d', sampleRate); 
    return view; 
    } 

    function floatTo16BitPCM(view, offset, input) { 
     for (var i = 0; i < input.length; i++, offset += 2) { 
      var s = Math.max(-1, Math.min(1, input[i])); 
      view.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)); 
     } 
    } 

    </script> 
</body> 

</html> 

답변

1

몇 가지 조사를 수행 한 후. 나는 그 문제를 발견했다.

var cdata = f.getChannelData(channelNum -1); 
buf.push(cdata); 

변수 buf은 오디오 버퍼의 사운드 데이터를 저장하지만 버퍼 참조 만 저장합니다. 버퍼는 하위 레벨 코드에 의해 지속적으로 업데이트됩니다. 따라서 buf 스토어에는 동일한 버퍼의 배열이 저장됩니다. 이것이 VLC가 의미없는 사운드를 재생하는 이유입니다.

var cdata = f.getChannelData(channelNum -1); 
buf.push(cdata.slice()); 

을하지만 여전히 시간 값이 현재 VLC에서 잘못된 이유를 알고하지 않습니다

아래로 변경 한 후, 코드는 잘 작동합니다.

관련 문제