是否可以将多个音频文件混合在一起,最好是用javascript

时间:2016-11-13 02:58:58

标签: javascript audio mix

我希望将音频剪辑组合在一起,相互叠加,以便它们同步播放并保存在新的音频文件中。任何帮助将非常感激。我已经在线进行了一些挖掘工作,但是无法找到关于Javascript音频编辑库(例如Mix.js)可用的许多工具是否具备的确切答案。

1 个答案:

答案 0 :(得分:5)

是的,可以使用OfflineAudioContext()AudioContext.createChannelMerger()并创建MediaStream。请参阅Phonegap mixing audio filesWeb Audio API

您可以使用fetch()XMLHttpRequest()作为ArrayBufferAudioContext.decodeAudioData()来检索音频资源,以便从响应中创建AudioBufferSourceNode; OfflineAudioContext()将合并后的音频,AudioContextAudioContext.createBufferSource()AudioContext.createMediaStreamDestination()MediaRecorder()呈现给记录流; Promise.all()Promise()构造函数,.then()处理对fetch()AudioContext.decodeAudioData()的异步请求,在Blob传递生成的混合音频stop事件为MediaRecorder

将每个AudioContext AudioBufferSourceNode连接到OfflineAudioContext.destination,在每个节点上调用.start();致电OfflineAudioContext.startRendering();创建新的AudioContext节点,连接renderedBuffer;在.createMediaStreamDestination()上拨打AudioContext,从合并的音频缓冲区创建MediaStream,在.stream MediaRecorder()事件stop处传递MediaRecorderBlob URL },使用Blob创建记录的音频混合的URL.createObjectURL() <a>,可以使用download元素下载,href属性和Blob URL设置到var sources = ["https://upload.wikimedia.org/wikipedia/commons/b/be/" + "Hidden_Tribe_-_Didgeridoo_1_Live.ogg" , "https://upload.wikimedia.org/wikipedia/commons/6/6e/" + "Micronesia_National_Anthem.ogg"]; var description = "HiddenTribeAnthem"; var context; var recorder; var div = document.querySelector("div"); var duration = 60000; var chunks = []; var audio = new AudioContext(); var mixedAudio = audio.createMediaStreamDestination(); var player = new Audio(); player.controls = "controls"; function get(src) { return fetch(src) .then(function(response) { return response.arrayBuffer() }) } function stopMix(duration, ...media) { setTimeout(function(media) { media.forEach(function(node) { node.stop() }) }, duration, media) } Promise.all(sources.map(get)).then(function(data) { var len = Math.max.apply(Math, data.map(function(buffer) { return buffer.byteLength })); context = new OfflineAudioContext(2, len, 44100); return Promise.all(data.map(function(buffer) { return audio.decodeAudioData(buffer) .then(function(bufferSource) { var source = context.createBufferSource(); source.buffer = bufferSource; source.connect(context.destination); return source.start() }) })) .then(function() { return context.startRendering() }) .then(function(renderedBuffer) { return new Promise(function(resolve) { var mix = audio.createBufferSource(); mix.buffer = renderedBuffer; mix.connect(audio.destination); mix.connect(mixedAudio); recorder = new MediaRecorder(mixedAudio.stream); recorder.start(0); mix.start(0); div.innerHTML = "playing and recording tracks.."; // stop playback and recorder in 60 seconds stopMix(duration, mix, recorder) recorder.ondataavailable = function(event) { chunks.push(event.data); }; recorder.onstop = function(event) { var blob = new Blob(chunks, { "type": "audio/ogg; codecs=opus" }); console.log("recording complete"); resolve(blob) }; }) }) .then(function(blob) { console.log(blob); div.innerHTML = "mixed audio tracks ready for download.."; var audioDownload = URL.createObjectURL(blob); var a = document.createElement("a"); a.download = description + "." + blob.type.replace(/.+\/|;.+/g, ""); a.href = audioDownload; a.innerHTML = a.download; document.body.appendChild(a); a.insertAdjacentHTML("afterend", "<br>"); player.src = audioDownload; document.body.appendChild(player); }) }) .catch(function(e) { console.log(e) });

<!DOCTYPE html>
<html>

<head>
</head>

<body>
  <div>loading audio tracks.. please wait</div>
</body>

</html>
AudioContext.createChannelMerger()

您也可以使用AudioContext.createChannelSplitter()var sources = ["/path/to/audoi1", "/path/to/audio2"]; var description = "mix"; var chunks = []; var channels = [[0, 1], [1, 0]]; var audio = new AudioContext(); var player = new Audio(); var merger = audio.createChannelMerger(2); var splitter = audio.createChannelSplitter(2); var mixedAudio = audio.createMediaStreamDestination(); var duration = 60000; var context; var recorder; var audioDownload; player.controls = "controls"; function get(src) { return fetch(src) .then(function(response) { return response.arrayBuffer() }) } function stopMix(duration, ...media) { setTimeout(function(media) { media.forEach(function(node) { node.stop() }) }, duration, media) } Promise.all(sources.map(get)).then(function(data) { return Promise.all(data.map(function(buffer, index) { return audio.decodeAudioData(buffer) .then(function(bufferSource) { var channel = channels[index]; var source = audio.createBufferSource(); source.buffer = bufferSource; source.connect(splitter); splitter.connect(merger, channel[0], channel[1]); return source }) })) .then(function(audionodes) { merger.connect(mixedAudio); merger.connect(audio.destination); recorder = new MediaRecorder(mixedAudio.stream); recorder.start(0); audionodes.forEach(function(node) { node.start(0) }); stopMix(duration, ...audionodes, recorder); recorder.ondataavailable = function(event) { chunks.push(event.data); }; recorder.onstop = function(event) { var blob = new Blob(chunks, { "type": "audio/ogg; codecs=opus" }); audioDownload = URL.createObjectURL(blob); var a = document.createElement("a"); a.download = description + "." + blob.type.replace(/.+\/|;.+/g, ""); a.href = audioDownload; a.innerHTML = a.download; player.src = audioDownload; document.body.appendChild(a); document.body.appendChild(player); }; }) }) .catch(function(e) { console.log(e) });

        letterValue = (char) (rand.nextInt(5) + 'A');
        if (rand.nextBoolean()) {
            letterValue = Character.toLowerCase(letterValue);
        }
        System.out.print(letterValue);