LoginSignup
82
68

More than 5 years have passed since last update.

getUserMediaで録音したデータをWAVファイルとして保存する

Posted at

1. 録音する

以下のように作った関数 startRecording を呼ぶと
変数 audioData に録音した音声データが取得できます。

        var localMediaStream = null;
        var localScriptProcessor = null;
        audioData = []; // 録音データ

        var onAudioProcess = function(e) {
          var input = e.inputBuffer.getChannelData(0);
          var bufferData = new Float32Array(bufferSize);
          for (var i = 0; i < bufferSize; i++) {
            bufferData[i] = input[i];
          }

          audioData.push(bufferData);
        };
        var startRecording = function() {
          navigator.getUserMedia(
            { audio: true },
            function(stream) {
              localMediaStream = stream;
              var scriptProcessor = audioContext.createScriptProcessor(bufferSize, 1, 1);
              localScriptProcessor = scriptProcessor;
              var mediastreamsource = audioContext.createMediaStreamSource(stream);
              mediastreamsource.connect(scriptProcessor);
              scriptProcessor.onaudioprocess = onAudioProcess;
              scriptProcessor.connect(audioContext.destination);
            },
            function(e) {
              console.log(e);
            }
          );
        };

2. WAVファイルに変換する

以下のように作った関数 exportWAV に 1 で作成した audioData を引数にわたして呼び出すと
WAVファイルを作成して、その url を返却してくれます。

        var exportWAV = function(audioData) {

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

            var writeString = function(view, offset, string) {
              for (var i = 0; i < string.length; i++){
                view.setUint8(offset + i, string.charCodeAt(i));
              }
            };

            var floatTo16BitPCM = function(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);
              }
            };

            writeString(view, 0, 'RIFF');  // RIFFヘッダ
            view.setUint32(4, 32 + samples.length * 2, true); // これ以降のファイルサイズ
            writeString(view, 8, 'WAVE'); // WAVEヘッダ
            writeString(view, 12, 'fmt '); // fmtチャンク
            view.setUint32(16, 16, true); // fmtチャンクのバイト数
            view.setUint16(20, 1, true); // フォーマットID
            view.setUint16(22, 1, true); // チャンネル数
            view.setUint32(24, sampleRate, true); // サンプリングレート
            view.setUint32(28, sampleRate * 2, true); // データ速度
            view.setUint16(32, 2, true); // ブロックサイズ
            view.setUint16(34, 16, true); // サンプルあたりのビット数
            writeString(view, 36, 'data'); // dataチャンク
            view.setUint32(40, samples.length * 2, true); // 波形データのバイト数
            floatTo16BitPCM(view, 44, samples); // 波形データ

            return view;
          };

          var mergeBuffers = function(audioData) {
            var sampleLength = 0;
            for (var i = 0; i < audioData.length; i++) {
              sampleLength += audioData[i].length;
            }
            var samples = new Float32Array(sampleLength);
            var sampleIdx = 0;
            for (var i = 0; i < audioData.length; i++) {
              for (var j = 0; j < audioData[i].length; j++) {
                samples[sampleIdx] = audioData[i][j];
                sampleIdx++;
              }
            }
            return samples;
          };

          var dataview = encodeWAV(mergeBuffers(audioData), audioContext.sampleRate);
          var audioBlob = new Blob([dataview], { type: 'audio/wav' });

          var myURL = window.URL || window.webkitURL;
          var url = myURL.createObjectURL(audioBlob);
          return url;
        };

参考サイト

82
68
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
82
68