Как обнаружить отключение от потока MJPEG в javascript

Я показываю поток MJPEG с IP-камеры на веб-странице. Поток отображается с использованием элемента изображения, который задается jQuery:

view = $('<img>');

view.load(function() {
     console.log('loaded');
});
view.error(function() {
     console.log('error');
});

view.attr('src', 'http://camera_ip/videostream.mjpeg');

Оба события запускаются аккуратно, когда возникает соответствующая ситуация. Пока не отключу камеру. Изображение зависает (конечно). Я хочу обнаружить это отключение, чтобы показать пользователю сообщение об ошибке. Я придумал решение, которое заключалось в копировании кадров с интервалом в несколько секунд от изображения на холст и сравнении содержимого.

Есть вариант проще?


person Supergrover    schedule 17.09.2013    source источник


Ответы (2)


Единственный способ сделать это на внешнем интерфейсе — это создать запрос AJAX именно тогда, когда вы устанавливаете атрибут src изображения. Запрос AJAX должен вызывать «полный» обратный вызов, когда поток mjpeg заканчивается.

Если вам удобно работать с node.js и/или веб-сокетами, вы можете в качестве альтернативы настроить серверную часть прокси-сервера mjpeg, которая обслуживает поток mjpeg и отправляет этому клиенту событие «закрыть» через веб-сокет, когда поток заканчивается. Таким образом, это будет выглядеть примерно так (имейте в виду, я до сих пор не понял, как именно bufferToJPEG будет анализировать один кадр jpeg из потока):

http.get('http://camera_ip/videostream.mjpeg', function(response) {
    var buffer = "";

    response.on('data', function(chunk) {
        buffer += chunk;
        clientSocket.emit('imageFrame', bufferToJPEG(buffer));
    });
    response.on('end', function() {
        clientSocket.emit('imageEnd');
    });
});

Проблема с этим (с которой я пытаюсь справиться в своем собственном проекте прямо сейчас) заключается в том, что вам нужно либо связать веб-сокет с каждым запросом изображения, либо испускать необработанные jpeg-файлы из потока mjpeg по мере их поступления через веб-сокеты ( вы можете визуализировать эти изображения с URI данных на внешнем интерфейсе).

Надеюсь, что немного помог - извините, что вам пришлось так долго ждать ответа.

редактировать: https://github.com/wilhelmbot/Paparazzo.js выглядит как хороший способ проксирование этого изображения так, как я описал выше.

person zigzackattack    schedule 01.11.2013

Вот что я придумал после прочтения ответа zigzackattack. Я использую пакет «datauri» для простоты, но для более точного контроля над окончательным изображением я также успешно протестировал пакет «node-canvas».

var mjpeg2jpegs = require('mjpeg2jpegs')
const Datauri = require('datauri')

var camURL = '/videostream.cgi?user=admin&pwd=password'
var camPort = 81
var camTimeout = 10000
var FPS_DIVIDER = 1

var options = {
  hostname: '192.168.1.241',
  port: camPort,
  path: camURL,
  timeout: camTimeout
}

function startCamStream (camName, options) {
  var http = require('http')
  var req = http.request(options, mjpeg2jpegs(function (res) {
    var data
    var pos = 0
    var count = 0
    res.on('imageHeader', function (header) {
    // console.log('Image header: ', header)
      data = new Buffer(parseInt(header['content-length'], 10))
      pos = 0
    })
    res.on('imageData', function (chunk) {
    // console.log('Image data: ', data.length)
      chunk.copy(data, pos)
      pos += chunk.length
    })
    res.on('imageEnd', function () {
    // console.log('Image end')
      if (count++ % FPS_DIVIDER === 0) {
        const datauri = new Datauri()
        datauri.format('.jpeg', data)
        socket.emit(camName, datauri.content) // Send the image uri via websockets. 
      }
    })
  })).on('timeout', function () {
    console.log('timeout')
    startCamStream(camName, options)
  }).end()
}

startCamStream('ipcam1', options)

Используя vue.js (необязательно), я просто вставляю uri изображения с тегом img.

<img :src="ipcam1"  alt="ipcam1" />

Увеличение переменной FPS_DIVIDER уменьшит количество кадров в секунду. Если вы хотите изменить изображение, когда есть тайм-аут, вы можете отправить «автономное» изображение, когда оно достигнет обратного вызова «тайм-аут».

person 01BTC10    schedule 20.01.2017