decodeAudioData在连续流上出现空错误而失败

时间:2013-12-03 19:53:43

标签: html5 node.js google-chrome ffmpeg web-audio

在我的下面的代码中,ffmpeg对输入流进行转码,并成功将块发送到客户端。在客户端,客户端正在解码来自socket.io的base64响应,并将响应转换为数组缓冲区。从那时起,decodeAudioData无法处理数组缓冲区并返回null错误。有谁知道为什么decodeAudioData不工作?

./ webaudio_svr.js:

var express = require('/usr/local/lib/node_modules/express');
var http = require('http');
var spawn = require('child_process').spawn;
var util = require('util');
var fs = require('fs');

var app       = express();
var webServer = http.createServer(app);
var audServer = http.createServer(app);
var io        = require('/usr/local/lib/node_modules/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_cli.js'></script>"
    );
});
webServer.listen(3000);

var inputStream = spawn('/usr/bin/wget', ['-O','-','http://nprdmp.ic.llnwd.net/stream/nprdmp_live01_mp3']);

var ffmpeg = spawn('ffmpeg', [
    '-i', 'pipe:0', // Input on stdin
    '-ar', '44100', // Sampling rate
    '-ac', 2, // Stereo
    '-f', 'mp3',
    'pipe:1' // Output on stdout
]);

io.sockets.on('connection', function(webSocket) {
    var disconnect = '0';

    if (disconnect == '0') {
        inputStream.stdout.pipe(ffmpeg.stdin);
        ffmpeg.stdout.on('data', function(data) {
            var data64 = data.toString('base64');
            webSocket.emit('stream',data64);
        });
    }

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

./公共/ webaudio_cli.js:

function str2ab(str) {
    var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
    var bufView = new Uint16Array(buf);
    for (var i=0, strLen=str.length; i<strLen; i++) {
        bufView[i] = str.charCodeAt(i);
    }
    return buf;
}

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

socket.on('stream', function(data) {
        var data=str2ab(atob(data));
        context.decodeAudioData(data, function(buffer) {
            source.connect(context.destination);
            source.buffer = buffer;
            source.start(0);
        }, function(err) {
            console.log("err(decodeAudioData): "+err);
        });
});

1 个答案:

答案 0 :(得分:0)

如果您阅读原帖的备注部分,您会看到我最终使用binaryjs,但在Kevin的帮助下,我能够使用socket.io。请注意,这仍然是一个巨大的问题,不稳定播放。如果有人可以提供一些帮助清理音频,请做。除非音频按预期工作,否则这个解决方案毫无意义,所以我需要弄明白。

问题与浏览器如何编码/解码base64字符串有关。在此更改之前,您必须从https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding提供自己的功能。

webaudio_svr.js:

var express = require('/usr/local/lib/node_modules/express');
var http = require('http');
var spawn = require('child_process').spawn;
var util = require('util');
var fs = require('fs');

var app       = express();
var webServer = http.createServer(app);
var io        = require('/usr/local/lib/node_modules/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='/base64.js'></script>\n"+
    "<script src='/webaudio_cli.js'></script>"
    );
});
webServer.listen(3000);

var inputStream = spawn('/usr/bin/wget', ['-O','-','http://nprdmp.ic.llnwd.net/stream/nprdmp_live01_mp3']);

var ffmpeg = spawn('ffmpeg', [
    '-i', 'pipe:0', // Input on stdin
    '-ar', '44100', // Sampling rate
    '-ac', 2, // Stereo
    '-f', 'mp3',
    'pipe:1' // Output on stdout
]);

io.sockets.on('connection', function(webSocket) {
    var disconnect = '0';

    if (disconnect == '0') {
        inputStream.stdout.pipe(ffmpeg.stdin);
        ffmpeg.stdout.on('data', function(data) {
            var data64 = data.toString('base64');
            webSocket.emit('stream',data64);
        });
    }

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

公共/ webaudio_cli.js:

window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
var startTime = context.currentTime;

// buffer to arraybuffer
function toArrayBuffer(buffer) {
    var ab = new ArrayBuffer(buffer.length);
    var view = new Uint8Array(ab);
    for (var i = 0; i < buffer.length; ++i) {
    view[i] = buffer[i];
    }
    return ab;
}
socket.on('stream', function(data) {
        var data=toArrayBuffer(base64DecToArr(data));
        context.decodeAudioData(data, function(buffer) {
            playBuffer(buffer);
        }, function(err) {
            console.log("decodeAudioData err: "+err);
        });
});

function playBuffer(buf) {
    var source    = context.createBufferSource();
    source.buffer = buf;
    source.connect(context.destination);
    source.start(startTime);
    startTime = startTime+source.buffer.duration;
}

公共/ base64.js: