Skip to content

External video analytics integration

Flussonic Watcher allows for the integration of third-party video analytics. This enables:

  • Storage of video episodes with desired events using the standard DVR mechanism.
  • Search, view, and export external events alongside standard Watcher analytics events.
  • Transmission of external events to other systems on par with other data.

Overall, events from third-party analytics are integrated on an equal footing with internal events.

To achieve this, it is necessary to:

  • Retrieve the video stream via RTSP (if the analytics are indeed based on video and not the operation of another sensor).
  • Identify the required events within the video.
  • Based on the timestamps in RTSP, send episodes containing these events to Watcher.

RTSP for video analytics

Video can be retrieved using various protocols, but the RTSP protocol supports absolute time addressing, suitable for frame identification, and is the standard for IP video surveillance; hence, we recommend its use.

Our experience with RTSP from surveillance cameras indicates that the accuracy of this protocol suffices for frame-by-frame synchronization of different cameras.

To allow the analytics system to retrieve video, an API token must be obtained for Watcher.


Watcher utilizes the data model episode instead of event for analytics events, and this distinction is crucial.

An episode has the following important characteristics:

  • The identifier is generated by the source. You need to generate an ID yourself and use it, which is no more complicated than a uuid.
  • An episode has a flexible start and end. This approach is more natural for video than a discrete event.
  • You can adjust the boundaries of an episode if you manage to refine it further in the process.

The lifecycle of an episode is as follows:

  • When analytics first detects something useful in the image at moment T1, an episode is created with a generated episode_id, media equal to the stream name, opened_at=T1, and updated_at=T1. The opened_at field is set once and then never changes.
  • The created episode is immediately sent to Watcher via the episode_save call. Since the ID is generated by the source, there is no separate episode_create method.
  • If the object detection extends over time, then updated_at in the episode is updated, which must always increase with any change in the episode. Otherwise, Watcher will ignore the changes.
  • If it is conclusively known that the event registration in the frame has ended (for example, a car has left the scene), then the closed_at field can be set, and it cannot be changed afterwards.
  • The preview field of an episode is for providing an exact screenshot of the detection, possibly cropped to the required dimensions. Feel free to update it if you manage to get a better picture. This field will be displayed in Watcher in the list of detections.
  • The entire episode will be overwritten each time, so send all fields during updates. This isn't a partial update but a complete rewrite of the record.

Snowflake ID

It appears you might have intended to describe the structure of the 64-bit identifier you use instead of a UUID but didn't provide the details of its structure. Could you please provide the specifics of how this 64-bit identifier is constructed or any other details you need assistance with?

42 bits 10 bits 12 bits
millisecond timestamp machine-id sequence

The significance of using a 64-bit identifier that exceeds JavaScript's 53-bit precision is crucial for system interoperability. This limitation necessitates parsing such identifiers as strings within JavaScript to avoid precision loss. For this purpose, libraries like json-bigint can be employed as an alternative to the native JSON parsing mechanism.

This approach facilitates the creation of identifiers across different systems without relying on a single point of failure, while also ensuring that the identifiers remain sortable. It underscores the importance of designing system architectures that can accommodate large-scale, distributed environments by employing robust data handling practices to maintain the integrity and order of identifiers across various platforms.

How to check


In the current Watcher API, the creation of episodes is not implemented, so a temporary solution involves creating them through Central. This approach is planned to be changed in the near future.

To create episodes in Central, the following are required:

  • The server address where Central is located.
  • An API KEY, which can be obtained from /etc/central/central.conf.

If Central is running behind Flussonic, requests will be proxied, so there is no need to directly access port 9019 (the default port for Central).

curl \
  -H 'Authorization: Bearer 08926CEA-3B54-4C77-99E2-A1F5FE54B11F' \
  -H 'Content-Type: application-json' \
  -d '{"episode_id":1722279170848854016,"media":"cam0","opened_at":1699458327000,"updated_at":1699458327000}'

This call is sufficient to create a discrete event where the start and end times coincide.

To update it later, the same request can be made again but with updated fields:

curl \
  -H 'Authorization: Bearer 08926CEA-3B54-4C77-99E2-A1F5FE54B11F' \
  -H 'Content-Type: application-json' \
  -d '{"episode_id":1722279170848854016,"media":"cam0","opened_at":1699458327000,"updated_at":1699458338399,"preview":"..."}'

preview must be filled with actual base64(jpeg) of your picture.

Now you can see new episode in the Watcher.