2

IP カメラからの MJPEG ストリームを Web ページに表示しています。ストリームは、jQuery によって設定されるイメージ要素を使用して表示されます。

view = $('<img>');

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

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

どちらのイベントも、それぞれの状況が発生したときにきちんと発生します。カメラを外すまで。画像がフリーズします(もちろん)。この切断を検出して、ユーザーにエラー メッセージを表示したいと考えています。画像から数秒離れたフレームをキャンバスにコピーし、内容を比較するという解決策を考えました。

もっと簡単なオプションはありますか?

4

2 に答える 2

1

フロントエンドでこれを行う唯一の方法は、画像の src 属性を設定したときに正確に AJAX リクエストを作成することです。AJAX 要求は、mjpeg ストリームが終了したときに「完了」コールバックを呼び出す必要があります。

node.js や websocket に慣れている場合は、mjpeg ストリームを提供し、ストリームが終了したときに websocket を介してそのクライアントに「close」イベントを発行する mjpeg プロキシ バックエンドを設定することもできます。したがって、次のようになります (bufferToJPEG がストリームから 1 つの 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');
    });
});

これに関する問題 (私は今、自分のプロジェクトで対処しようとしています) は、websocket を各画像要求に関連付けるか、mjpeg ストリームから生の jpeg を送信する必要があることです (これらの画像は、フロント エンドのデータ uris でレンダリングできます)。

少しお役に立てば幸いです -- 返信をお待たせして申し訳ありません。

編集: https://github.com/wilhelmbot/Paparazzo.jsは、上で説明した方法でその画像をプロキシする良い方法のようです。

于 2013-11-01T18:46:42.437 に答える
0

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 変数を増やすと、fps 出力が減少します。タイムアウトが発生したときに画像を変更したい場合は、「タイムアウト」コールバックに達したときに「オフライン」画像を送信できます。

于 2017-01-20T16:46:27.977 に答える