Javascript 自定义媒体流
我正在通过WebSocket接收原始float32音频,并希望在浏览器中播放此音频。据我所知,我需要为此使用MediaStreamAPI。但是,我找不到一种方法来创建可以附加数据缓冲区的媒体流 实现这一目标的正确方法是什么 我正在尝试这样的事情:Javascript 自定义媒体流,javascript,html,webkitaudiocontext,Javascript,Html,Webkitaudiocontext,我正在通过WebSocket接收原始float32音频,并希望在浏览器中播放此音频。据我所知,我需要为此使用MediaStreamAPI。但是,我找不到一种方法来创建可以附加数据缓冲区的媒体流 实现这一目标的正确方法是什么 我正在尝试这样的事情: var context = new AudioContext(); context.sampleRate = 48000; var stream = null; // ???? var source = conte
var context = new AudioContext();
context.sampleRate = 48000;
var stream = null; // ????
var source = context.createMediaStreamSource(stream);
source.connect(context.destination);
source.start(0);
socket.onmessage = function (event) {
stream.appendBuffer(new Float32Array(event.data)); // ????
};
您应该使用从websocket的缓冲区读取声音并播放
var context = new AudioContext();
var sampleRate = 48000;
var startAt = 0;
socket.onmessage = function (event) {
var floats = new Float32Array(event.data);
var source = context.createBufferSource();
var buffer = context.createBuffer(1, floats.length, sampleRate);
buffer.getChannelData(0).set(floats);
source.buffer = buffer;
source.connect(context.destination);
startAt = Math.max(context.currentTime, startAt);
source.start(startAt);
startAt += buffer.duration;
};
这将播放来自websocket的音乐
要将音频缓冲区转换为媒体流,请使用AudioContext.createMediaStreamDestination()
。将BufferSource连接到它以根据缓冲区的数据生成自定义媒体流
var data = getSound(); // Float32Array;
var sampleRate = 48000;
var context = new AudioContext();
var streamDestination = context.createMediaStreamDestination();
var buffer = context.createBuffer(1, data.length, sampleRate);
var source = context.createBufferSource();
buffer.getChannelData(0).set(data);
source.buffer = buffer;
source.connect(streamDestination);
source.loop = true;
source.start();
var stream = streamDestination.stream;
这将从数据阵列读取音频并将其转换为媒体流 关于解码,来自窗口对象的audioContext应该完成这项工作
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
然后
audioCtx.decodeAudioData(audioData, function(buffer) {
直接在二进制数组上
关于通信,我宁愿使用XMLHttpRequest(一个低级函数和旧函数)并直接使用响应
这是MDM开发人员开发的一个非常好的函数(我更新了ogg文件的url,因此您可以直接测试它):
完整的源代码如下:
几年后你有什么反馈吗?试图做同样的事情,但目前似乎仍然无法在流上“附加缓冲区”…@ronag我给这个问题添加了一个悬赏,因为我想知道答案。我还对代码进行了一些编辑,以使其更新。你知道2018年的答案吗。context.sampleRate是只读属性。2.流必须是MediaStream对象。您可以使用构造函数来创建它<代码>流=新媒体流()。我认为这有点帮助。如果你想对媒体内容进行分块解码,我的意思是当你需要多次调用decodeAudioData()时,这种方法效果不好。每个decodeAudioData()在第一个解码帧(至少在MP3中)上产生短暂的静音。所以decodeAudioData()是一个很好的解决方案,而且只有当您想一次解码所有内容时才可以。event.data的数据类型是什么?
function getData() {
source = audioCtx.createBufferSource();
request = new XMLHttpRequest();
request.open('GET', 'https://raw.githubusercontent.com/mdn/webaudio-examples/master/decode-audio-data/viper.ogg', true);
request.responseType = 'arraybuffer';
request.onload = function() {
var audioData = request.response;
audioCtx.decodeAudioData(audioData, function(buffer) {
myBuffer = buffer;
songLength = buffer.duration;
source.buffer = myBuffer;
source.playbackRate.value = playbackControl.value;
source.connect(audioCtx.destination);
source.loop = true;
loopstartControl.setAttribute('max', Math.floor(songLength));
loopendControl.setAttribute('max', Math.floor(songLength));
},
function(e){"Error with decoding audio data" + e.error});
}
request.send();
}