Ricoh Theta S - live preview in javascript Ricoh Theta S - live preview in javascript javascript javascript

Ricoh Theta S - live preview in javascript


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-8Accept: 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 streamlet 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