Mp4 streaming/seeking works from firefox (fedora) and not from firefox (windows) (nginx 1.9.3)

greetings!

i am seeing an unexplained malfunction here with nginx when serving
videos.
flv and mp4 files have different symptoms. mp4 streams correctly when i
view
the file in firefox 39 in fedora 22, but in windows 7 (firefox 39) the
file
cannot be ‘seeked’ and must be played linearly.
after speaking with the coders of video.js (the player i use), it was
determined that nginx is not returning byte range data appropriately (or
at
all) - so seeking would not work. however, this does not explain why
firefox
39 in fedora works perfectly and does not provide a solution as to how
to
get nginx to serve correctly.

the only advice i have seen is to change the value of the ‘max_ranges’
directive - but doing that has made no difference. i have left it as
‘unset’

  • which i understand to mean ‘unlimited’.

an example video from the server is here:
src=“https://www.ureka.org/file/play/17924/censored%20on%20google%202.mp4

any tips welcomed! thanks

Posted at Nginx Forum:

oh, so the solution here was to add: add_header Accept-Ranges bytes;
to the site’s config file.

Posted at Nginx Forum:

Be aware it doesn’t work either in Chrome on mac :slight_smile:

i have now created question on this topic on serverfault and on
stackexchange’s video site - but have not found the solution to the
problem.
i have looked into all the answers i have received so far and none have
made
any difference to the fact that my server is not reliably serving video.
all
my MP4s are now processed to relocate the moov atom.
anyone got any additional thoughts? is there a github issue i can open
or
some other bug tracker for nginx?

Posted at Nginx Forum:

i thought i had solved this by adding the header for accept-ranges -
since
when i did that i could then seek in firefox on windows 7. however,
after
testing further i found that the results are inconsistent and ultimately
it
is still somewhat broken.
i have added more details to this to a new question i have asked at
serverfault:

any input is still welcome!

Posted at Nginx Forum:

Hello!

On Thu, Aug 06, 2015 at 09:16:38AM -0400, tunist wrote:

i have now created question on this topic on serverfault and on
stackexchange’s video site - but have not found the solution to the problem.
i have looked into all the answers i have received so far and none have made
any difference to the fact that my server is not reliably serving video. all
my MP4s are now processed to relocate the moov atom.
anyone got any additional thoughts? is there a github issue i can open or
some other bug tracker for nginx?

Bugs in nginx are to be reported via trac.nginx.org. But please
note that for now nothing in this thread and/or in your serverfault
question indicate there is a bug in nginx.


Maxim D.
http://nginx.org/

i mentioned the possibility of a bug since i have already exhausted all
options presented to me via numerous channels of research and support. i
will post my server/site’s full config to serverfault shorly.

Posted at Nginx Forum:

i have now updated the serverfault question to include the nginx config
files.

Posted at Nginx Forum:

On Thu, Aug 06, 2015 at 07:26:34PM -0400, tunist wrote:

Hi there,

i have now updated the serverfault question to include the nginx config
files.

It looks like the question at video - why is partial content not being served in nginx (mp4)? - Server Fault
has been changed so most current comments now look broken.

That’s one downside of not using something like a mailing list where
the original context can be seen, even after the event.

Can I suggest you use a test server {} block, and strip that section of
your nginx.conf down to only what is essential to show the problem that
you are reporting?

(And post the smaller config here, so that people will be able to
copy-paste it into their test systems and reproduce exactly what you
are reporting.)

Right now, it looks to me as if your config says that a request for
/file.mp4 will be handled in “location / {}”, which will just serve the
file /usr/local/nginx/html/file.mp4.

Is that what you expect? If so, you can remove all of the other location
{} blocks and have an effectively identical config for this request,
which will be much easier to analyse without getting distracted.

Also, you seem to be testing with “curl -I -r”, and being surprised at
a HTTP 200 response. nginx returns HTTP 200 to HEAD requests for files.

Use something like “curl -i -r 5-10 http…file.mp4 | cat -v” to see
whether it sends a HTTP 206 with suitable headers. If it doesn’t, then
you may have found an nginx problem.

(Right now, your example url gives me HTTP 302 and indicates that PHP
is involved somehow. It’s hard to analyse things if they change
silently.)

Good luck with it,

f

Francis D. [email protected]

On Fri, Aug 07, 2015 at 01:18:48AM +0100, Francis D. wrote:

On Thu, Aug 06, 2015 at 07:26:34PM -0400, tunist wrote:

Hi there,

Also, you seem to be testing with “curl -I -r”, and being surprised at
a HTTP 200 response. nginx returns HTTP 200 to HEAD requests for files.

That last sentence is incorrect.

It can return 200 and it can return 206; it depends on the actual
request made.

For example, “Range:” and “Content-Range:” request headers can lead to
different responses.

f

Francis D. [email protected]

oh, so it seems likely that i need to add extra logic into the PHP page
that
handles the video stream to support range requests - as detailed here:

Posted at Nginx Forum:

yes, i removed some of the original question since it was shown to not
be
relevant to the issue. i appreciate that maybe it would be best to write
‘EDIT:’ when i edit there, but then the question might become huge… so
in
the interest of balance, i just cut some parts out.

“Right now, it looks to me as if your config says that a request for
/file.mp4 will be handled in “location / {}”, which will just serve the
file /usr/local/nginx/html/file.mp4.”

why do you think that?

there is a PHP application being served via this config that handles the
routing and serving of files, including mp4s. the video files are
accessible
at urls that are handled via a page handler programatically. the PHP
file
that serves the media files outputs the appropriate headers and feeds
the
file to the browser as a stream.

“Also, you seem to be testing with “curl -I -r”, and being surprised at
a HTTP 200 response. nginx returns HTTP 200 to HEAD requests for files.”

i have been testing with this format, as recommended here by a
contributor
to video.js on github (mp4 video can be 'seeked' in fedora firefox, but not in win 7 firefox · Issue #2385 · videojs/video.js · GitHub):

curl -sL -w “%{http_code} %{size_download} %{url_effective}\n”
https://www.ureka.org/file/download/17365/censored%20on%20google.mp4
-H
‘Accept-Encoding: identity;q=1, ;q=0’ -H ‘Accept-Language:
en-US,en;q=0.8’
-H ‘User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134
Safari/537.36’
-H ‘Range: bytes=0-’ -H ‘Accept: /’ -H ‘Referer:
https://www.ureka.org/file/view/17365/me-being-covertly-censored-on-google
-H 'Cookie: Elgg=htbujjg4khfj7qr1s9nbban653;
_pk_id.1.e8a2=30087d194778be65.1437418823.1.1437418823.1437418823.;
_pk_ses.1.e8a2=
’ -H ‘Connection: keep-alive’ -H ‘Cache-Control:
max-age=0’
–compressed -o /dev/null

i ran the curl command that you provided here and saw a continual stream
of
unreadable characters in the terminal. i am not experienced with curl in
the
terminal to the extent i can discern which would be the appropriate
flags to
use here.

i have removed the video that i posted as a test now. however, this one
will
remain available:

thanks for assisting!

Posted at Nginx Forum:

aha! yes, the cause of the problem was the lack of range handling in the
PHP
page i am using for streaming the files. i forgot that that is a
requirement
of the process! i have added the videostream class to the page and so
far
the streaming is working well in my tests :slight_smile:

Posted at Nginx Forum:

oh, so it seems likely that i need to add extra logic into the PHP page
that
handles the video stream to support range requests - as detailed here:

Posted at Nginx Forum:

On Fri, Aug 07, 2015 at 07:12:27AM -0400, tunist wrote:

Hi there,

so in the interest of balance, i just cut some parts out.

Yes, that’s usually a sensible thing to do. It just makes reading the
content a week later, a bit odd.

“Right now, it looks to me as if your config says that a request for
/file.mp4 will be handled in “location / {}”, which will just serve the
file /usr/local/nginx/html/file.mp4.”

why do you think that?

Given the request, and the location{} blocks in the config, “location
/{}”
looked like the best-match one to me.

That contains "try_files $uri " and then a fallback.

If you are not directly using nginx to serve the file from the
filesystem;
or using the nginx “mp4” directive to handle the file from the
filesystem;
it will probably be useful to explain what exactly you are doing, in
order to allow others reproduce the problem you are reporting.

there is a PHP application being served via this config that handles the
routing and serving of files, including mp4s.

To me, that says that it is not nginx that is sending the video, but
your php script.

So your php script is the place to look for any unexpected behaviour.

If you can start with “I make this request and I expect to get this
response”, then you will have a much easier time testing and seeing
where things fail.

On your test system, if you throw away all of the php stuff and just
serve
the file directly; or serve the file using the mp4 module does
everything
work as it should? If so, that points at where the problem probably is.

“Also, you seem to be testing with “curl -I -r”, and being surprised at
a HTTP 200 response. nginx returns HTTP 200 to HEAD requests for files.”

i have been testing with this format, as recommended here by a contributor
to video.js on github (mp4 video can be 'seeked' in fedora firefox, but not in win 7 firefox · Issue #2385 · videojs/video.js · GitHub):

That looks like it is a “please send me the whole file” request (Range:
bytes=0-), so I’d expect to get the whole file.

When I try a request like that against an nginx just serving the file, I
get back

HTTP/1.1 206 Partial Content
Content-Length: 4013
Content-Range: bytes 0-4012/4013

amongst the rest of the response.

i ran the curl command that you provided here and saw a continual stream of
unreadable characters in the terminal. i am not experienced with curl in the
terminal to the extent i can discern which would be the appropriate flags to
use here.

I suggest “-v” for verbose, “-H” with the one or two headers that you
actually care about, and then end the shell line with “2>&1 | cat -v |
less”, so that you can see a printable representation of the (binary)
body content.

All you really want to see are the headers, though.

i have removed the video that i posted as a test now. however, this one will
remain available:
https://www.ureka.org/file/play/7369/nasa%20mars%20anomalies%202010.mp4

I think that the problem is in the non-nginx complexity that has been
added.

Put that file in /usr/local/nginx/html/, and access is without using
php.

If that works, then you can choose whether to keep it that way, or to
reintroduce php.

thanks for assisting!

Good luck with it.

f

Francis D. [email protected]

thanks again for assisting. i have resolved this now since i realised
that
the php file i use to stream the files did not support partial content
:wink:
i thought that nginx had some kind of built in ‘magical’ support for
that
which meant that my application didn’t need to handle it. however, that
is
not the case and once i added in a PHP class to handle the partial
requests,
the files now seek correctly. i am seeing some zero buffer errors in the
nginx log for large files, which i haven’t debugged / resolved yet - but
the
major issue is resolved now.

Posted at Nginx Forum:

Hello,

If I understand well, you are streaming video files from PHP? Here PHP
will
kill your performance and you really should avoid that and stream
directly
from nginx.

Best Regards

Posted at Nginx Forum:

i did explore that possibility for several days, but did not achieve
success. part of the problem is that the videos have dynamic privacy
settings applied to them and so PHP is used to decide which videos the
present user can view and which ones they cannot view. i looked at using
various directives in nginx to bypass this but never found a way to do
it.

Posted at Nginx Forum: