Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 自定义媒体流_Javascript_Html_Webkitaudiocontext - Fatal编程技术网

Javascript 自定义媒体流

Javascript 自定义媒体流,javascript,html,webkitaudiocontext,Javascript,Html,Webkitaudiocontext,我正在通过WebSocket接收原始float32音频,并希望在浏览器中播放此音频。据我所知,我需要为此使用MediaStreamAPI。但是,我找不到一种方法来创建可以附加数据缓冲区的媒体流 实现这一目标的正确方法是什么 我正在尝试这样的事情: var context = new AudioContext(); context.sampleRate = 48000; var stream = null; // ???? var source = conte

我正在通过WebSocket接收原始float32音频,并希望在浏览器中播放此音频。据我所知,我需要为此使用MediaStreamAPI。但是,我找不到一种方法来创建可以附加数据缓冲区的媒体流

实现这一目标的正确方法是什么

我正在尝试这样的事情:

    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();
}