简体   繁体   English

HTML 5实时音频流播放器

[英]Player for live audio streaming in HTML 5

First of all, I know the <audio> tag, but I would like to write my own live audio player for further experiments. 首先,我知道<audio>标签,但是我想编写自己的现场音频播放器以进行进一步的实验。

Basically, I am trying to stream a simple MP3 file from a node.js server to a HTML5 client script that receives the stream using websockets, append the chunks, and finally play the file. 基本上,我试图将一个简单的MP3文件从node.js服务器流传输到HTML5客户端脚本,该脚本使用websockets接收流,附加块,最后播放该文件。

Since I am talking about streaming, I start playing the file before the end of the download process. 因为我在谈论流,所以我在下载过程结束之前开始播放文件。

My main concern is: I can't hear anything. 我主要担心的是:我听不到任何声音。 There is no error, everything seems to work fine, but actually nothing happen. 没有错误,一切似乎都正常,但实际上什么也没发生。

I supposed the tricky part was about the chunk sizes, but the decodeAudioData function does not seem to use the optional error callback. 我以为棘手的部分是关于块大小的,但是encodeAudioData函数似乎并未使用可选的错误回调。

The server side script is really simple: 服务器端脚本非常简单:

var fs = require('fs');

var WebSocketServer = require('ws').Server;

var wss = new WebSocketServer({port: 9090,host:"192.168.0.253"});
var readStream = fs.createReadStream("test.mp3",
                                     {
                                        'flags': 'r',
                                        'mode': 0666,
                                        'bufferSize': 64 * 1024
                                     }
                                    );

wss.on('connection', function(ws) {
                                    readStream.on('data', function(data)
                                                                {
                                                                    ws.send(data,     {binary: true, mask: false});
                                                                }
                                                );
                                    }
        );

The client side script is: 客户端脚本是:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset=utf-8>
<meta name="viewport" content="width=620">
<title>Test stream HTML5</title>

<script>
var numberOfChannels = 2;
function decode(node)
{
    try
    {
        audioCtx.decodeAudioData(
                                    node.buf,
                                    function(decoded)
                                    {
                                        for (var i=0; i<numberOfChannels; i++)
                                        {
                                            var channel = node.source.buffer.getChannelData(i);
                                            channel.set(decoded, node.cursor );
                                        }

                                        node.cursor += decoded.length;
                                        if (!node.started)
                                        {
                                            node.source.start();
                                            node.started = true;
                                        }
                                   }
                                );
    }
    catch(e)
    {
        console.log('decode exception',e.message);
    }
}

function onOpen(evt)
{
    console.log("CONNECTED");
}

function onClose(evt)
{
    console.log("DISCONNECTED");
}

function errorHandler(e)
{
  var msg = '';

  switch (e.code) {
    case FileError.QUOTA_EXCEEDED_ERR:
      msg = 'QUOTA_EXCEEDED_ERR';
      break;
    case FileError.NOT_FOUND_ERR:
      msg = 'NOT_FOUND_ERR';
      break;
    case FileError.SECURITY_ERR:
      msg = 'SECURITY_ERR';
      break;
    case FileError.INVALID_MODIFICATION_ERR:
      msg = 'INVALID_MODIFICATION_ERR';
      break;
    case FileError.INVALID_STATE_ERR:
      msg = 'INVALID_STATE_ERR';
      break;
    default:
      msg = 'Unknown Error';
      break;
  };

  console.log('Error: ' + msg);
}

var ws = new WebSocket("ws://192.168.0.253:9090");
ws.onopen = function(evt) {onOpen(evt)};
ws.onclose = function(evt) { onClose(evt) };
ws.onerror = function(evt) { errorHandler(evt) };
ws.binaryType = 'arraybuffer';

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();

node={};
node.source  = audioCtx.createBufferSource();
node.source.connect(audioCtx.destination);
node.cursor = 0;
node.started=false;

// 9693654 is the size of the mp3 file: just a magic number used for the prototype :)
node.source.buffer = audioCtx.createBuffer( numberOfChannels, 9693654, 44100);

ws.onmessage = function (evt)
               {
                    node.buf=evt.data;
                    decode(node);
               };


</script>

</html>

By the way, I tried to play the file even at the end of the download part, and it still does not work. 顺便说一句,即使在下载部分结束时,我也尝试播放该文件,但仍然无法正常工作。

Thanks for your advises! 感谢您的建议!

I don't think you can split mp3 into multiple part and play / decode them partially. 我不认为您可以将mp3分成多个部分,然后部分播放/解码。 Haven't tried it myself and am not an expert on mp3 though. 我自己还没有尝试过,但不是mp3专家。

You basically need to stream audio in PCM (raw audio) or use other mechanism in order to compress data. 基本上,您需要以PCM(原始音频)流式传输音频或使用其他机制来压缩数据。

Here's an example audio streaming code I've written while back: https://github.com/agektmr/AudioStreamer 这是我回写的音频流代码示例: https : //github.com/agektmr/AudioStreamer

I'm not sure if it still works but at least before Web Audio API change. 我不确定它是否仍然有效,但至少在Web Audio API更改之前。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM