Ответ 1
Есть несколько вещей, которые вы можете попробовать здесь. Многие технологии на стороне сервера (включая .NET и Java) гораздо строже относительно того, что они считают допустимым JSON, чем Javascript. Многие были адаптированы из более ранних технологий, таких как SOAP, которые основывались на проверенном XML и считают JSON аналогичным строгим набором правил.
Кроме того, API, к которому вы подключаетесь, вероятно, был написан специалистами по прошивке встроенных камер, которые раньше никогда не писали код для Интернета. Они привыкли к C++ и Java, которые гораздо менее прощающие, чем JS.
Во-первых, их API указывает, что они ожидают, что заголовки HTTP будут:
Content-Type: application/json;charset=utf-8
Accept: application/json
Однако на скриншоте вы отправляете:
Content-Type: text/plain;charset=utf-8
Это сообщает серверу, что отправляемый вами текст - это текст, а не JSON. Даже если они ожидают только JSON, это приведет к сбою многих готовых реализаций JSON на стороне сервера.
Следующее, что нужно попробовать, это то, что многие парсеры JSON, которые на самом деле не являются Javascript, добавляют некоторые вполне определенные правила к тому, что они считают допустимым JSON.
Вы отправляете:
{name:camera._getLivePreview, parameters:{sessionId:SID_0001}}
Это допустимый JS, но на самом деле не действительный JSON по строгим XML-подобным правилам, потому что они ожидают, что все будет заключено в кавычки (единственные типы значений, которые вы не цитируете - это булевы и числа).
Так что постарайтесь:
{
"name": "camera._getLivePreview",
"parameters": {
"sessionId": "SID_0001"
}
}
Если вы посмотрите на их руководство по началу работы, они отформатируют каждый запрос таким образом - процитируйте свойства и укажите значения.
Один из способов убедиться в том, что вы получите этот более строгий JSON, - это построить JS-объект вашего запроса и затем использовать JSON.stringify
чтобы установить тело запроса, например:
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' }
});
Наконец, вы получаете видеопоток - поддержка этого в процессе fetch
довольно слабая и практически отсутствует в XMLHttpRequest
. Сервер будет продолжать посылать вам контент, а вы продолжаете направлять его во что-то, что может его визуализировать, и если вы остановитесь, вы увидите ошибку target_closed
.
Вы должны продолжать перебирать поток:
// 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();
}
Уже существует множество реализаций JS MJPEG, здесь довольно простая