Search code examples
javascripthtmlgoogle-chromejplayericecast

Audio from Icecast server not playing in Chrome


I'm having trouble getting static content (mp3 files) served by an Icecast server to play in Google Chrome browser with HTML5. The reason we're serving the mp3s via Icecast is policy: the CPB requires they be "streamed" and not "downloaded" since we're public radio. Our live audio streams play just fine in Chrome.

If you put the URL for an MP3 served by my Icecast 2.4.3 server straight into the URL bar in google Chrome, it does not play. Do the same thing in Firefox, IE, Safari, etc.. it plays! Try it:

https://streaming.kansaspublicradio.org:8001/mp3/First_0713886.mp3

(The temporary solution I'm using is Flash but the latest update to Chrome (v60.0) makes Flash blocked by default, the "Always allow for this website" option does not seem to be working, and the little icon showing that Flash is blocked is much more discrete. Try it here: http://kansaspublicradio.org/kpr-news/midwest-farmers-hope-boost-online-grocery-shopping )

My best guess as to why this is happening is that it has something to do with this: https://developers.google.com/web/updates/2016/03/play-returns-promise?hl=en

So I tried to reproduce their code example, in which they monkey with HTML5 Media Capture to get audio to play without user interaction. But with this URL for the audio, it fails to play and throws this error: Uncaught (in promise) DOMException: The element has no supported sources. Try it: https://jsfiddle.net/wo94xohr/2/ It only fails in Chrome and not Firefox or others.

I tried again but without the HTML5 Media Capture stuff. Still no dice. Try it: https://jsfiddle.net/yrhets74/

Also, if you look at the response headers, you see "Content-Range:bytes 0-0/0"... could this mean something?


UPDATE: I'm testing to see if this is a CORS (cross origin resource sharing) issue. I've updated the jsfiddle to:

var audioElement = document.querySelector('#music');
audioElement.crossOrigin = "anonymous"; // CORS access restriction. Worth a shot but no dice
audioElement.type = "audio/mpeg"; // just in case? idk
audioElement.src = "https://streaming.kansaspublicradio.org:8001/mp3/First_0713886.mp3";

function startPlayback() {
  // .play() is a Promise
  return audioElement.play().then(function(x){console.log('yay!')}, function(reason){
      console.log('Error: ' + reason);
  });
}
var playButton = document.querySelector('#play');
playButton.addEventListener('click', startPlayback);

It hasn't changed the end result on Chrome, but on Firefox it doesn't play now and it gives the warning: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://streaming.kansaspublicradio.org:8001/mp3/First_0713886.mp3. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

Do you think the Icecast server needs the 'Access-Control-Allow-Origin' header set to 'allow' or something?

Here's the full response from the Icecast server:

Request URL:https://streaming.kansaspublicradio.org:8001/mp3/First_0713886.mp3
Request Method:GET
Status Code:206 Partial Content
Remote Address:129.237.213.244:8001
Referrer Policy:no-referrer-when-downgrade

Response Headers
view source
Accept-Ranges:bytes
Cache-Control:no-cache
Content-Length:526408
Content-Range:bytes 0-0/0
Content-Type:audio/mpeg
Date:Tue, 15 Aug 2017 19:34:23 GMT
Expires:Mon, 26 Jul 1997 05:00:00 GMT
Pragma:no-cache
Server:Icecast 2.4.3

Request Headers
view source
Accept:*/*
Accept-Encoding:identity;q=1, *;q=0
Accept-Language:en-US,en;q=0.8,ms;q=0.6
Cache-Control:no-cache
Connection:keep-alive
DNT:1
Host:streaming.kansaspublicradio.org:8001
Origin:https://fiddle.jshell.net
Pragma:no-cache
Range:bytes=0-
Referer:https://fiddle.jshell.net/_display/
User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36

UPDATE 2: We've added the CORS header Access-Control-Allow-Origin:* to the icecast server's response headers and now the jsfiddle works in Firefox - no CORS header ‘Access-Control-Allow-Origin’ missing warning. Still does not play in Chrome though :(

I also tested WAV files and M3U files and neither will play in Chrome. Firefox could play the wav file (with the JSfiddle code) but no the m3u file


Solution

  • I think the issue is with your stream. Here is a slightly modified example with another streaming URL:

    audioElement.src = "http://novazz.ice.infomaniak.ch/novazz-128.mp3";
    

    https://jsfiddle.net/yrhets74/5/

    This works on my machine with Firefox 55 and Chrome 60.

    VLC tells me the codec used is MPEG Audio 1/2 (mpga).

    Regarding the CORS policy, you may be interested in this question: DOMException: Failed to load because no supported source was found