可以使用 Web Audio API 和 createMediaElementSource 分析来自 Icecast 的流式音频吗?

Posted

技术标签:

【中文标题】可以使用 Web Audio API 和 createMediaElementSource 分析来自 Icecast 的流式音频吗?【英文标题】:Possible to analyze streaming audio from Icecast using Web Audio API and createMediaElementSource? 【发布时间】:2016-07-16 05:43:39 【问题描述】:

使用 Web Audio API 和 createMediaElement 方法,您可以使用类型化数组从 <audio> 元素中的音频播放中获取频率数据,只要源 URL 是本地的(非流式传输),它就可以在大多数浏览器中使用。见 Codepen:http://codepen.io/soulwire/pen/Dscga

实际代码:

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var audioElement = new Audio('http://crossorigin.me/http://87.230.103.9:80/top100station.mp3'); // example stream

audioElement.crossOrigin = 'anonymous';
audioElement.type = 'audio/mpeg';

var analyser = audioCtx.createAnalyser();

audioElement.addEventListener('canplay', function() 
  var audiosrc = audioCtx.createMediaElementSource(audioElement);
  // Bind our analyser to the media element source.
  audioSrc.connect(analyser);
  audioSrc.connect(audioCtx.destination);
);

var frequencyData = new Uint8Array(20);

var svgHeight = ($window.innerHeight / 2) - 20;
var svgWidth = $window.innerWidth - 20;
var barPadding = '2';

function createSvg(parent, height, width) 
  return d3.select(parent).append('svg').attr('height', height).attr('width', width);


var svg = createSvg('.visualizer', svgHeight, svgWidth);

// Create our initial D3 chart.
svg.selectAll('rect')
   .data(frequencyData)
   .enter()
   .append('rect')
   .attr('x', function (d, i) 
      return i * (svgWidth / frequencyData.length);
   )
   .attr('width', svgWidth / frequencyData.length - barPadding);

// Continuously loop and update chart with frequency data.
function renderChart() 
   requestAnimationFrame(renderChart);

   // Copy frequency data to frequencyData array.
   analyser.getByteFrequencyData(frequencyData);

   console.log(frequencyData);

   // Update d3 chart with new data.
   svg.selectAll('rect')
      .data(frequencyData)
      .attr('y', function(d) 
         return svgHeight - d;
      )
      .attr('height', function(d) 
        return d;
      )
      .style('opacity', function(d) 
        return d / 255;
      )
      .attr('fill', function() 
         return 'rgb(255, 255, 255)';
      );


// Run the loop
renderChart();

其中.visualizer 是一个空的<div>

我正在使用 Ionic/Angular 为广播电台开发一个混合应用程序,音频流通过 Icecast (http://dir.xiph.org/),我遇到了以下问题:本地 mp3 被分析和可视化没有问题但是如果您使用流式 URL,analyzer.getByteFrequencyData 在 iOS Safari 中全为零,但播放正常。

回顾一下:

我知道在早期版本的 Safari 中存在一个错误,其中 createMediaElementSource() 会失败,但如果仍然如此,那么它将无法在本地文件上运行?

有什么想法吗?

【问题讨论】:

【参考方案1】:

仍然无法使用 Safari 和 iOS Chrome(使用 Apple WebKit?)。其他浏览器现在似乎没问题。音频播放正常,CORS 正常 - 但分析器无法正常工作。

This fiddle(不是我的)很好地展示了这种行为。后一个 uri 被分析,前一个不被分析:

  const url = useStream
  ? 'https://c2.radioboss.fm:18071/stream'
  : 'https://twgljs.org/examples/sounds/DOCTOR%20VOX%20-%20Level%20Up.mp3';

Related question in Apple forum(没有答案)

【讨论】:

【参考方案2】:

它只是没有根据 Safari 中的规范实现,并且将返回一个零数组而不是流的频率。许多人都观察到了这种行为,例如http://isflashdeadyet.com/tests/web-audio-visualization/index-analyser.html 和 https://github.com/Okazari/Rythm.js/issues/7

应该按照https://browsersupport.io/AnalyserNode.prototype.getByteFrequencyData工作

在这里,您会发现“在 AnalyserNode 上请求字节数据时,Safari [is] 似乎全面报告无信号(值 128)”: http://fourthof5.com/audio-visualisation-with-the-web-audio-api

在此处测试演示以查看当前状态:http://fourthof5.com/assets/posts/audio-visualisation-with-the-web-audio-api/index.html

【讨论】:

您指的是哪个“Safari 中的规范”?

以上是关于可以使用 Web Audio API 和 createMediaElementSource 分析来自 Icecast 的流式音频吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何下载我刚刚使用 Web Audio API 创建的声音?

使用 Web Audio API 为声音的开头添加静音 [关闭]

在 Web Audio API 中使用 ChannelSplitter 和 MergeSplitter 节点

关于Web Audio API的入门

Web Audio Api 与 Web Speech Api 集成 - 将扬声器/声卡输出流式传输到语音识别 api

是否有抽象 Web Audio API 和 Mozilla Audio Data API 以读取原始音频(MP3,ogg)的库