ブラウザで録音した音源とアップロードした音源を合成する

ブラウザで録音した音源とアップロードした音源を合成する

こんにちわ。kyamashitaです。

前回はブラウザから録音させてみましたので、今回は録音した音源とアップロードした音源を合成させてみます。

アップロードした音源を保持

audioContext.decodeAudioData()を使ってデコードした音源を保持します。
const audioContext = new (window.AudioContext || window.webkitAudioContext);
let audioBuffer = null;
document.querySelector('#file').addEventListener('change', function () {
    const file = this.files[0];
    const reader = new FileReader();
    reader.readAsArrayBuffer(file);
    reader.onload = function () {
        audioContext.decodeAudioData(reader.result, function (buffer) {
            audioBuffer = buffer;
        });
    };
});

録音した音源とアップロードした音源を合成

下記にて合成しています。 アップロードした音源の方はループ設定しておきます。 合成したstreamをMediaRecorderに渡します。
// record
const deviceSource = audioContext.createMediaStreamSource(stream);
const deviceGain = audioContext.createGain();
deviceGain.gain.value = 0.5;
deviceSource.connect(deviceGain);

// upload file
const audioSource = audioContext.createBufferSource();
audioSource.buffer = audioBuffer;
audioSource.loop = true;
const audioGain = audioContext.createGain();
audioGain.gain.value = 0.5;
audioSource.connect(audioGain);

// mix
const mixedOutput = audioContext.createMediaStreamDestination();
deviceGain.connect(mixedOutput);
audioGain.connect(mixedOutput);
const mediaStream = mixedOutput.stream;

サンプル全文

今回のサンプルはこちら

<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>sample</title>
</head>
<body>
<input type="file" id="file">
<hr>
<button id="start">録音</button>
<button id="stop">停止</button>
<hr>
<audio id="player" controls></audio>
<script>
    window.onload = function () {
        const audioContext = new (window.AudioContext || window.webkitAudioContext);

        let audioBuffer = null;
        document.querySelector('#file').addEventListener('change', function () {
            const file = this.files[0];
            const reader = new FileReader();
            reader.readAsArrayBuffer(file);
            reader.onload = function () {
                audioContext.decodeAudioData(reader.result, function (buffer) {
                    audioBuffer = buffer;
                });
            };
        });

        const start = document.querySelector('#start');
        const stop = document.querySelector('#stop');
        const player = document.querySelector('#player');

        let mediaRecorder = null;
        let mimeType = '';
        let chunks = [];
        start.addEventListener('click', function () {
            navigator.mediaDevices.getUserMedia({"video": false, "audio": true})
                .then(function (stream) {

                    // record
                    const deviceSource = audioContext.createMediaStreamSource(stream);
                    const deviceGain = audioContext.createGain();
                    deviceGain.gain.value = 0.5;
                    deviceSource.connect(deviceGain);

                    // upload file
                    const audioSource = audioContext.createBufferSource();
                    audioSource.buffer = audioBuffer;
                    audioSource.loop = true;
                    const audioGain = audioContext.createGain();
                    audioGain.gain.value = 0.5;
                    audioSource.connect(audioGain);

                    // mix
                    const mixedOutput = audioContext.createMediaStreamDestination();
                    deviceGain.connect(mixedOutput);
                    audioGain.connect(mixedOutput);
                    const mediaStream = mixedOutput.stream;

                    mediaRecorder = new MediaRecorder(mediaStream);
                    mediaRecorder.ondataavailable = function (e) {
                        mimeType = e.data.type;
                        chunks.push(e.data);
                    };
                    mediaRecorder.onstop = function () {
                        const blob = new Blob(chunks, { 'type' : mimeType });
                        chunks = [];
                        player.src = window.URL.createObjectURL(blob);
                    };

                    audioSource.start(0);
                    mediaRecorder.start();
                })
                .catch(function (e) {
                    alert(e);
                });
        });

        stop.addEventListener('click', function () {
            mediaRecorder.stop();
        });
    };
</script>

</body>
</html>
  • このエントリーをはてなブックマークに追加

この記事を読んだ人にオススメ