HTML5 Progressive Streaming -- no follow-up range requests - ffmpeg

I'm working on an embedded device that is recording video on the fly. I'd like to stream that to an HTML5 video element, using our own custom server. I have this almost working and would like some help.
So far as I can tell, I've got libav / ffmpeg doing their job right. I encoded an mp4 in RAM with the moov atom at the start of the file. I've written this file to disk and it plays everywhere it should.
The problem, I think, lies with how I'm responding to HTTP range requests. When I try to do a live stream, I get an initial range request from the browser / player (currently tried Chrome, Firefox, and VLC) for bytes:0-. I responded with some initial bytes. The browser / player actually plays this fine, but never asks again. So the live stream doesn't work, just the first 3 seconds or whatever.
I've looked at the RFC spec of partial content, and my understanding is I'm doing what I should be... Clearly I'm not though. Here is an example of a request / response with Chrome as the requester:
get /live.mp4 HTTP/1.1
host: localhost:1235
connection: keep-alive
accept-encoding: identity;q=1, *;q=0
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.167 Safari/537.36
accept: */*
dnt: 1
accept-language: en-GB,en-US;q=0.9,en;q=0.8
range: bytes=0-
HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Type: video/mp4
Content-Length: 182400
Content-Range: bytes 0-182399/*
Again, with that request / response pair, Chrome plays the first 182400 bytes but never makes a second request. I thought having the '*' in Content-Range would make this happen...

Progressive download doesn’t work that way. It browser assumes the file will never change. To play a live stream you need to use fragmented MP4 and media source extensions.

This was the problem. I needed media extensions, it wasn't clear to me that progressive streaming wasn't for live feeds of unknown length. Media extensions and a websocket solved the issue. Also needed to use -dash for libav to make it work in Chrome.

I came across a similar issue where it was working perfectly on Firebox but only plays the first fragment of the video in Chrome and does not request any other. My case was solved simply by making the very first response return nothing with a 200 status code and Accept-Ranges: bytes header.
Looks like it is common, check the update part for the following question: Content-Range working in Safari but not in Chrome

Related

How to detect webp file behind .png link?

I have some tricky link:
https://www.pwc.com.tr/tr/sektorler/Perakende-T%C3%BCketici/kuresel-tuketicileri-tanima-arastirmasi/kuresel-tuketici-gorusleri-arastirmasi-info-5en.png
The last 4 characters in the link implies that we will get image in png format, and even GET HTTP request to that link brings the content-type ‘image/png’.
But if you’ll try to save it in browser, you will end up with webp file format
So, question is - how one can detect that it really webp image 'hidden' behind the link that looks like and act (remember headers!) like png file via program that can use only http protocol?
Update: I want to point out that I did http get request from different environments and get 'image/png' type in headers content-type. For example using node.js and axios
https://youtu.be/KiRrAVl67uQ
Update: The server will detect client type by request's User-Agent header, and return different Content-Type correspondingly. It makes sense, because not all client support webp.
Thus, to get image/webp type resource, you can send custom User-Agent header and simulate as Chrome etc. For example, in Node.js and axios:
const axios = require('axios');
axios.request({
url: 'https://www.pwc.com.tr/tr/sektorler/Perakende-T%C3%BCketici/kuresel-tuketicileri-tanima-arastirmasi/kuresel-tuketici-gorusleri-arastirmasi-info-5en.png',
method: 'get',
headers: {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
}
}).then(function(res) {
console.log(res.headers); // content-type header is image/webp now.
}).catch(function(err) {
console.log(err);
});
Browser try to save this picture as .webp format because: in HTTP response headers, the Content-Type header's value is image/webp:
how one can detect that it really webp image 'hidden' behind the link that looks like and act like png file...?
You can check HTTP response header and find what Content-Type it is.

Invalid-Content-Type error when trying to send GIF through Twilio SMS

I have this bit of code to send an MMS message with a GIF. (using Ruby with Sinatra, hosted on Heroku).
client.messages.create(
to: to,
from: phone,
body: message,
media_url: 'http://media.giphy.com/media/zl170rmVMCpEY/giphy.gif'
)
It fails, and Twilio's debug console shows a 12300 invalid content-type error. I'm certain I'm missing something simple here, but I cannot figure out what.
The URL you are using is returns a different type of content based on the Accept header of the request.
In Chrome a response with a "Content-Type" header of "text/html". Which is surprising given the .gif suffix on the URL.
Chrome accept headers look like: Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
However if I use curl -I http://media.giphy.com/media/zl170rmVMCpEY/giphy.gif I get Content-Type: image/gif
If you look at the image URL on the HTML page, in Chrome, it is actually: https://i.giphy.com/zl170rmVMCpEY.webp
webp is an alternative format to gif, I suspect it is served instead of gif if the browser supports it.
If Twilio supports webp format images you could use that instead.
Gify also seem to use mp4 format, it looks like they brand as gif, but don't actually serve gif's to clients which can accept HTML or WebP content.

Correct HTTP Headers for Images?

I'm writing a web server in C#, just for the fun of it, and I am able to serve basic text files to my browser. However, when serving up an image (say, image.png), all browsers that I test my server on (IE, Firefox, and Chrome) show some kind of placeholder thumbnail for the image, as if the image is corrupted or invalid.
The response that I am sending to the browser looks like
HTTP/1.0 200 Ok
Content-Type: image/png
Content-Length: 14580053
{image data here}
Am I using the correct HTTP headers? Or, if I am, why else would browsers not accept the image?
Ah, figured it out... my code forgot to add an extra \n before the response body. It wasn't a problem with the headers at all, just incorrect response syntax.

Why does requests library fail on this URL?

I have a url. When I try to access it programmatically, the backend server fails (I don't run the server):
import requests
r = requests.get('http://www.courts.wa.gov/index.cfm?fa=controller.managefiles&filePath=Opinions&fileName=875146.pdf')
r.status_code # 200
print r.content
When I look at the content, it's an error page, though the status code is 200. If you click the link, it'll work in your browser -- you'll get a PDF -- which is what I expect in r.content. So it works in my browser, but fails in Requests.
To diagnose, I'm trying to eliminate differences between my browser and Requests library. So far I've:
Disabled Javascript
Disabled (and deleted) cookies
Set the User-Agent to be the same in each
But I can't get the thing to work properly in Requests or fail in my browser due to disabling something. Can somebody with a better idea of browser-magic help me diagnose and solve this?
Does the request work in Chrome? If so, you can open the web inspector and right-click the request to copy it as a curl command. Then you'll have access to all the headers, params, and request body, which you can play around with to see which are triggering the failure you're seeing with the requests library.
You're probably running into a server that discriminates based on User-Agent. This works:
import requests
S = requests.Session()
S.headers.update({'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)'})
r = S.get('http://www.courts.wa.gov/index.cfm?fa=controller.managefiles&filePath=Opinions&fileName=875146.pdf')
with open('dl.pdf', 'wb') as f:
f.write(r.content)

Asian characters in IE 8 get garbled in Server; is this due to HTTP header Content-Type?

One of the request parameters in an http request made by the client contains Japanese characters. If I make this request in Firefox and look at the parameter as soon as it reaches the server by debugging in Eclipse, the characters look fine. If I do the same request using IE 8, the characters get garbled when I look at them at the same point in the server code (they are fine in both browsers, though). I have examined the POST requests made by both browsers, and they both pass the same sequence of characters, which is:
%2C%E3%81%9D%E3%81%AE%E4%BB%96
I am therefore thinking that this has to do with the encoding. If I look at the HTTP headers of the request, I notice the following differences. In IE:
Content-Type: application/x-www-form-urlencoded
Accept: */*
In Firefox:
Content-Type application/x-www-form-urlencoded; charset=UTF-8
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
I'm thinking that the IE 8 header doesn't state the UTF-8 encoding explicitly, even though it's specified in the meta tag of the HTML document. I am not sure if this is the problem. I would appreciate any help, and please do let me know if you need more information.
Make sure the page that contains the form has UTF-8 as charset. In IE's case, the best thing to make sure of this is by sending a HTTP header ('Content-Type: text/html; charset=utf-8') and adding a meta http-equiv tag with the content type/charset to your html (I've seen this actually matter, even when the appropriate header was sent).
Second, your form can also specify the content type:
<form enctype="application/x-www-form-urlencoded; charset=utf-8>

Resources