javascript - Possible to analyze streaming audio from Icecast using Web Audio API and createMediaElementSource? - Stack Overflow

Using the Web Audio API and createMediaElement method you can use a typed array to get frequency data f

Using the Web Audio API and createMediaElement method you can use a typed array to get frequency data from audio playback in an <audio> element and it works in most browsers as long as the source URL is local (not streaming). See Codepen:

Actual Code:

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var audioElement = new Audio('://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();

Where .visualizer is an empty <div>

I'm developing a hybrid app for a radio station using Ionic/Angular and the audio stream is through Icecast (/) and I've run into the following issue: local mp3s are analyzed and visualized no problem however if you use the streaming URL, analyser.getByteFrequencyData is all zeroes in iOS Safari but it plays fine.

So to recap:

I know there was a bug in earlier versions of Safari where createMediaElementSource() would fail but if that were still the case then it wouldn't work on the local file?

Any ideas?

Using the Web Audio API and createMediaElement method you can use a typed array to get frequency data from audio playback in an <audio> element and it works in most browsers as long as the source URL is local (not streaming). See Codepen: http://codepen.io/soulwire/pen/Dscga

Actual Code:

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();

Where .visualizer is an empty <div>

I'm developing a hybrid app for a radio station using Ionic/Angular and the audio stream is through Icecast (http://dir.xiph/) and I've run into the following issue: local mp3s are analyzed and visualized no problem however if you use the streaming URL, analyser.getByteFrequencyData is all zeroes in iOS Safari but it plays fine.

So to recap:

I know there was a bug in earlier versions of Safari where createMediaElementSource() would fail but if that were still the case then it wouldn't work on the local file?

Any ideas?

Share Improve this question asked Mar 28, 2016 at 21:10 Geoff EllerbyGeoff Ellerby 1706 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

Still not working with Safari and iOS Chrome (which is using Apple WebKit?). Other browsers seem to be fine now. Audio plays fine, CORS is ok - yet Analyser is not working.

This fiddle (not mine) demonstrates the behavior well. Latter uri gets analysed, former not:

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

Related question in Apple forum (no answers)

It just is not implemented according to the specs in Safari and will return an array of zeroes instead of frequencies for streams. Many people have observed this behaviour, e.g. http://isflashdeadyet./tests/web-audio-visualization/index-analyser.html and https://github./Okazari/Rythm.js/issues/7

It is supposted to work according to https://browsersupport.io/AnalyserNode.prototype.getByteFrequencyData

Here you will find that "Safari [is] seemingly reporting no signal (a value of 128) across the board when requesting byte data on an AnalyserNode": http://fourthof5./audio-visualisation-with-the-web-audio-api

Test the demo here to see the current status: http://fourthof5./assets/posts/audio-visualisation-with-the-web-audio-api/index.html

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745328099a4622750.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信