zoukankan      html  css  js  c++  java
  • Html5 播放实时音频流

         项目需求 Web端播放实时音频流,折腾了两天后问题得以解决。记录下开发调试过程,方便后来者。

    首次想到是利用Audio标签,Audio标签可以直接播放MP3格式,服务端将实时音频流编码成MP3格式

    通过Http方式传给Web端即可,前端代码如下所示:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script>
        </script>
    </head>
    <body>
    	<audio controls="controls" autoplay="autoplay">
    	<source src="http://127.0.0.1:12345/cgmedia/28181/getaudio?id=34020000001310000001@192.168.1.108:5060&format=mp3&transporttype=udp&transportport=22000" type="audio/mpeg">
    	</audio>
    </body>
    </html>
    

      通过Audio标签 实现音频流播放 代码比较简单,但有缓冲过大问题,粗略测试了下延时 20-30s左右,这显然

    不满足实时播放实时播放需求。开始调试时怀疑是后台服务端传输过来的流有问题,于是将流保存成MP3文件进行

    测试 ,结果正常未出现缓冲一段时间后开始播放。分析Audio标签发出的Http报文,发现Http请求Head中有Range字段,

    尝试做了相应Response,结果未发生变化。猜想Audio标签可能只适合于MP3文件(一次性将Audio数据加载完成再处

    理)。如这个猜测不对,欢迎指正(本人主要从事后台媒体服务开发,前端经验很少)。

          Audio标签的方式不行,想到利用Web Audio API是实现,基本的思路是:通过WebSocket 接收服务端推送过来的音

    频流(MP3格式)调用decodeAudioData进行解码,最后将解码数据推送到AudioContext最后一个Node,代码如下:

     
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script>
      
          function WebSocketTest()
             {
         var wsUrl = "ws://127.0.0.1:12345/cgmedia/28181/getaudio?id=34020000001310000001@192.168.1.108:5060&format=mp3&transporttype=udp&transportport=22000";
                  ws = new WebSocket(wsUrl);
         ws.binaryType = 'arraybuffer'; //arraybuffer
         ws.onmessage = function(msg) {
         var data =  msg.data;
        var datalen = msg.data.size;
        var reader = new FileReader();
            var audioContext = new AudioContext({
            sampleRate:8000,
            });
         
         reader.onload = function(evt)
          {
           if(evt.target.readyState == FileReader.DONE)
           {
              audioContext.decodeAudioData(data, function(buffer) {
             console.log("decode success");
             var bufferSource = audioContext.createBufferSource();
             bufferSource.connect(audioContext.destination);
             bufferSource.buffer = buffer;
             bufferSource.start(0);
            }, function(e) {
             console.log("decode failed" + e);
            });
            
           }
          }
        reader.readAsArrayBuffer(new Blob([data]));
         
       };
       ws.onopen = function(evt) {
        if(self.verbose) {
         console.log("Connection open......");
        } 
       };
       ws.onclose = function(evt) {
        if(self.verbose) {
         console.log("Connection closed......");
        }
       };
             }
        </script>
    </head>
    <body>
     <button onclick="WebSocketTest()">发送请求</button>
    </body>
    </html>

       采用Audio Web API方式播放实时流会出现卡顿现象,以上方法一次性解码的数据可以连续播放,每次解码后要重新

    创建BufferSource,显而易见这种播放模式播放实时流效率很低,查阅了Audio Web API 文档 播放网络流似乎要利用

     基于AudioWorkletProcessor的自定义节点,文档也给了一个简单的例子,那个例子不符合我们的使用场景。没有

    更多的时间研究Audio Web API,这种方案只好作罢,单看Audio Web API接口有些无语, 这有可能跟Web端处理能力有关。

       可行的方法

         条条大路通罗马,毕竟项目不是科研,可以实现需求就行。一种可行的方法是服务端输出Rtmp音频流 通过video.js播放

    实际应该是用了flash。项目开始已经想到了这个方案可行只是觉得有些绕(需要将音频流封装后推送到rtmp server)。

    另外一个可行的方案就是利用H5 MSE实现,这个方案也有开源的库可以用,例如flv.js 这需要 服务端将音频打包成flv格式

    推送给Web前端,Web端接收到音频数据后调用flv.js进行播放。video.js 及flv.js github都有下载 代码就不贴出来了。

    如需交流可加QQ群766718184,1038388075 或者QQ3501870

    视频下载地址:http://www.chungen90.com/?news_3/

     Demo下载地址: http://www.chungen90.com/?news_2

  • 相关阅读:
    java代码读取yarn聚合目录日志
    Java内存区域的划分和异常
    Hbase restFul API
    Sql Server函数全解(一)字符串函数
    Sql Server之数据类型详解
    Sql Server之使用T_SQL创建,修改,查看数据库信息
    《Java编程思想》笔记 第一章 对象导论
    spring之Autowire
    spring之scope作用域
    spring之注入类型
  • 原文地址:https://www.cnblogs.com/wanggang123/p/12316895.html
Copyright © 2011-2022 走看看