Content-Range working in Safari but not in Chrome

1,375 views
Skip to first unread message

Loreto Parisi

unread,
Nov 12, 2018, 12:53:26 PM11/12/18
to Chromium-dev

I'm streaming audio files from a Node.js Express server with Content-Range headers plus no caching headers. This works ok in latest Safari instead, but it does not in Chrome.

While when streaming the full audio file with HTTP 200, my headers were

{ 'Content-Length': 4724126,
  'Content-Type': 'audio/mpeg',
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
  'Access-Control-Allow-Headers': 'POST, GET, OPTIONS',
  Expires: 0,
  Pragma: 'no-cache',
  'Cache-Control': 'no-cache, no-store, must-revalidate' }

and it works on both Chrome and Safari <audio> tag.

When streaming partial contents with HTTP 206 the headers were

{ 'Content-Length': 4724126,
  'Content-Type': 'audio/mpeg',
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
  'Access-Control-Allow-Headers': 'POST, GET, OPTIONS',
  Expires: 0,
  Pragma: 'no-cache',
  'Cache-Control': 'no-cache, no-store, must-revalidate',
  'Accept-Ranges': 'bytes',
  'Content-Range': 'bytes 120515-240260/4724126' }

This led to an error of the Chrome page where the <audio> or <video> tag was.

Even the embedded media tag created by Chrome when using the streaming url right in the browser it is not working, and led to this

Schermata 2018-11-12 alle 10.49.20.png


I have posted the server code here: https://stackoverflow.com/questions/53226595/streaming-audio-in-node-js-with-content-range

Loreto Parisi

unread,
Nov 13, 2018, 12:30:01 PM11/13/18
to acol...@chromium.org, chromi...@chromium.org
In the example you mention it is

HTTP/1.1 206 Partial content
       Date: Wed, 15 Nov 1995 06:25:24 GMT
       Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
       Content-Range: bytes 21010-47021/47022
       Content-Length: 26012
       Content-Type: image/gif

so I have 26012 = (21010-47021)  + 1

while I'm using the total bytes of the whole data that is in this example 
47022, right?




Il giorno mar 13 nov 2018 alle ore 18:20 Aaron Colwell <acol...@chromium.org> ha scritto:
Hi,
I'm not sure what exactly is going wrong in your case, but the Content-Length header in your example looks wrong to me. I'd expect it to be 120515 (i.e. 240260 + 1 - 120515) since that is how many bytes the range represents and how many bytes should be in the response body. Take a look at the Content-Range example in the HTTP spec for another data point on what the Content-Length should be in a range request.

Aaron

--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
---
You received this message because you are subscribed to the Google Groups "Chromium-dev" group.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/7f22b449-2c65-4261-aba1-aa5861c1ac20%40chromium.org.


--
Dott. Ing. Loreto Parisi
Parisi Labs

Company: in...@parisilabs.com

Loreto Parisi

unread,
Nov 13, 2018, 12:41:58 PM11/13/18
to Chromium-dev, acol...@chromium.org
As suggested and for the docs about Content-Length when there is a Content-Range I did

header['Accept-Ranges'] = 'bytes';
header['Content-Range'] = 'bytes ' + range[0] + '-' + range[1] + '/' + total;
//header['Content-Length'] = range[2];
header['Content-Length'] = parseInt(range[1]) - parseInt(range[0]) + 1;


so the headers this time were

{ 'Content-Length': 119746,

  'Content-Type': 'audio/mpeg',

  'Access-Control-Allow-Origin': '*',

  'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',

  'Access-Control-Allow-Headers': 'Range',

  Expires: 0,

  Pragma: 'no-cache',

  'Cache-Control': 'no-cache, no-store, must-revalidate',

  'Accept-Ranges': 'bytes',

  'Content-Range': 'bytes 120515-240260/4724126' }



but Chrome it still does not load the audio.

Asanka Herath

unread,
Nov 13, 2018, 12:49:48 PM11/13/18
to loreto...@gmail.com, acol...@chromium.org, net...@chromium.org
chromium-dev to BCC

Did Chrome send a range request in the absence of a strong validator (as I gather from your first message)?

If it did, does the requested range line up with the response range?

Aaron Colwell

unread,
Nov 13, 2018, 2:25:48 PM11/13/18
to loreto...@gmail.com, chromi...@chromium.org
Hi,
I'm not sure what exactly is going wrong in your case, but the Content-Length header in your example looks wrong to me. I'd expect it to be 120515 (i.e. 240260 + 1 - 120515) since that is how many bytes the range represents and how many bytes should be in the response body. Take a look at the Content-Range example in the HTTP spec for another data point on what the Content-Length should be in a range request.

Aaron

On Mon, Nov 12, 2018 at 9:52 AM Loreto Parisi <loreto...@gmail.com> wrote:
--

Aaron Colwell

unread,
Nov 13, 2018, 2:25:48 PM11/13/18
to loreto...@gmail.com, chromi...@chromium.org
Yes. Your example is returning the total size of the original file in the content-length header and it should only be returning the number of bytes described in the range.

Aaron

Loreto Parisi

unread,
Nov 14, 2018, 12:28:14 PM11/14/18
to Chromium-dev, loreto...@gmail.com, acol...@chromium.org, net...@chromium.org
So,
since my express server forward a request to the media server, the "range" header is sent from Express -> MediaServer.
Then the Media-Server will send back a "Content-Range" response to the client, i.e. Chrome in this case:

client (Chrome,Safari) -----> express ---- ("Range" header) -----> media server ----> ("Content-Range" header) -----> client (Chrome,Safari)

the media server takes the "Range" and create a node.js read stream from that, hence I calculate the range start and end as seen before, with the fix on the "Content-Length:"
Supposed that start= 120515, end= 240260 (in bytes)
I will get

Range : "bytes=120515-240260"
"Content-Range" :  "bytes 120515-240260/4724126"
"Content-Length": 119746

With these settings calling the audio streaming url directly into the browser search bar like: "localhost:3000//streams/12380193?start=5&end=10"
in Safari it will work and stream the audio in the right interval, while in Chrome it won't. So this is a Chromium issue for some reason.

Also the bytes range values are correct, because I get them from ffprobe:

ffprobe -i /audio/12380193.mp3 -show_frames -show_entries frame=pkt_pos -of default=noprint_wrappers=1:nokey=1 -hide_banner -loglevel panic -read_intervals 20%+#1

(here I have a start time of 20 seconds)
Reply all
Reply to author
Forward
0 new messages