Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ricoh Theta S - live preview in javascript

Tags:

I am trying to create an app that talks to the Ricoh Theta S camera using HTTP requests ... they are compliant with Open Spherical Camera API Version 1.0 ... here is their api reference

So I am trying to implement the live preview they say the camera supports ... I am doing this in javascript so I tried every possible combination to get the binary data they say the api call returns ... tried vanilla js, jquery, angular ... nothing ... here is a print screen of the request ... the debugger shows it in red although the status code is 200

enter image description here

the response is empty ... so my question is ... is there a way I can implement a Motion JPEG (10 fps) in javascript, over HTTP, using a POST request that sends an object?

thanks, Rares

like image 540
Wowzaaa Avatar asked Nov 04 '15 09:11

Wowzaaa


1 Answers

There are a couple of things you could try here. A lot of server side technologies (including .NET and Java) are much stricter about what they consider to be valid JSON than Javascript is. Many have been adapted from earlier tech like SOAP that relied on validated XML and consider JSON to be a similar strict set of rules.

Also, the API you're connecting to was probably written by specialist embedded camera firmware engineers who've never written code for the web before. They're used to C++ and Java, which are a lot less forgiving than JS.

Firstly their API specifies that they expect the HTTP headers to be:

Content-Type: application/json;charset=utf-8 Accept: application/json 

However, in the screenshot you're sending:

Content-Type: text/plain;charset=utf-8 

This tells the server that the content you're sending is text, not JSON. Even though they only expect JSON that will cause a lot of out-of-the-box server side JSON implementations to fail.

The next thing to try is that a lot of JSON parsers that aren't actually Javascript add some quite specific rules to what they consider to be valid JSON.

You're sending:

{name:camera._getLivePreview, parameters:{sessionId:SID_0001}} 

This is valid JS, but not actually valid JSON by the strict XML-like rules because they expect everything to be quoted (the only value types you don't quote are booleans and numbers).

So try:

{     "name": "camera._getLivePreview",      "parameters": {         "sessionId": "SID_0001"     } } 

If you look at their getting started guide they format every request in this way - quote the properties and quote the values.

One way to ensure that you get this stricter JSON is to build your request JS object and then use JSON.stringify to set the body of the request, like this:

const content = {name:'camera._getLivePreview', parameters:{sessionId:'SID_0001'}};  const response = await fetch('.../osc/commands/execute', {     method: 'POST',      body: JSON.stringify(content),     headers:{ 'Content-Type': 'application/json' } }); 

Finally what you're getting back is a video stream - support for this in fetch is fairly bleeding edge and basically missing from XMLHttpRequest. The server is going to keep sending you content and you keep piping it to something that can render it, and if you stop you'll see that target_closed error.

You need to keep iterating through the stream:

// Get the fetch response as a stream  const reader = await response.body.getReader();  // Async loop the stream let chunk = await reader.read(); while (chunk && !chunk.done) {     for (let index = 0; index < chunk.value.length; index++) {          // parse the response in chunks            }     chunk = await reader.read(); } 

There are plenty of JS MJPEG implementations already out there, here's a fairly simple one

like image 75
Keith Avatar answered Oct 15 '22 18:10

Keith