设置getChannelData导致socket.io在Web音频中崩溃

时间:2014-11-06 14:06:54

标签: html5 ffmpeg socket.io html5-audio web-audio

我遇到了一个问题,每当我对音频文件进行转码并通过socket.io将音频缓冲区发送到客户端以便通过网络音频播放时,我的连接会在我执行时立即死亡

source.buffer.getChannelData(0).set(audio);

我假设这不是Socket.IO问题而且我只是因为真正的问题而看到了Socket.IO问题。在客户端我将音频文件传送到ffmpeg的stdin并监听ffmpeg的stderr以确定何时发送缓冲区是安全的。客户端正在接收缓冲区并正在正确地执行所有操作,直到上述行。以下是一些重现问题的示例测试代码。

服务器端:

var express = require('express');
var http = require('http');
var spawn = require('child_process').spawn;

var app       = express();
var webServer = http.createServer(app);
var io        = require('socket.io').listen(webServer, {log: false});

app.use(express.static(__dirname + '/public'));

app.get('/', function(req, res){
    res.send(
    "<script src='/socket.io/socket.io.js'></script>\n"+
    "<script>var socket=io.connect('http://127.0.0.1:3000');</script>\n"+
    "<script src='/webaudio_file_cli.js'></script>"
    );
});
webServer.listen(3000);

io.sockets.on('connection', function(webSocket) {

    var disconnect = '0';
    var count = 0;
    var audBuf = new Buffer([]);

    if (disconnect == '0') {
        console.log('new connection...');

        var inputStream = spawn('wget', ['-O','-','http://www.noiseaddicts.com/samples/4353.mp3']);

        var ffmpeg = spawn('ffmpeg', [
            '-i', 'pipe:0', // Input on stdin
            '-acodec', 'pcm_s16le', // PCM 16bits, little-endian
            '-ar', '24000', // Sampling rate
            '-ac', 1, // Mono
            '-f', 'wav',
            'pipe:1' // Output on stdout
        ], {stdio: ['pipe','pipe','pipe']});

            inputStream.stdout.pipe(ffmpeg.stdin);

            ffmpeg.stdout.on('data', function(data) {
                audBuf = Buffer.concat([audBuf,data]);
            });

            ffmpeg.stderr.on('data', function(data) {
            var _line = data.toString('utf8');
            if (_line.substring(0,5) == 'size=' && _line.indexOf('headers:') > -1) {
                console.log('completed...');
                webSocket.emit('audio',audBuf);
            }
        });
    }

    webSocket.on('disconnect', function() {
        console.log('disconnecting...');
            disconnect=1;
    });
});

客户端(webaudio_file_cli.js):

window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
var source = context.createBufferSource();

var audioStack = [], audio = [];

socket.on('audio', function(data) {
    playAudio(data);
});

function playAudio(data) {
    // playback starting...
    audioStack = Int16Array(data);
    for (var i = 0; i < audioStack.length; i++) {
        audio[i] = (audioStack[i]>0)?audioStack[i]/32767:audioStack[i]/32768; // convert buffer to within the range -1.0 -> +1.0
    }

    var audioBuffer = context.createBuffer(1, audio.length, 24000);
    source.buffer.getChannelData(0).set(audio);
    source.buffer = audioBuffer;
    source.connect(context.destination);
    source.start(0);
}

1 个答案:

答案 0 :(得分:2)

在此示例中,您在设置source.Buffer = audioBuffer之前访问source.buffer.getChannelData。翻转这两行的顺序,可能吗?