Skip to content
Last updated

VIF Custom Event Listener API Reference

VIF delivers detection results to event listeners which are Java classes that implement IVifEventListener. This reference documents that interface and the DetectionResponse class hierarchy passed to it. For a guided walkthrough with a worked example, see Create a custom VIF event listener.

Interface IVifEventListener

package com.wowza.wms.plugin.videointelligence.api;

public interface IVifEventListener {
    static String getVersion();
    default void onInit(IApplicationInstance appInstance, IMediaStream stream,
                         Set<String> methods, HashMap<String, Object> properties);
    default void onShutdown();
    default boolean immediate(DetectionResponse response);
    default boolean batch(ArrayList<DetectionResponse> responses);
    default boolean rollup(DetectionResponse response);
}

All five instance methods are default. An implementation only needs to override the ones relevant to it. A listener that only uses immediate delivery, for example, doesn't need to provide batch or rollup overrides at all; the interface's defaults cover the rest.

Method summary

Modifier and typeMethodDescription
static StringgetVersion()Returns the plugin API version.
voidonInit(...)Called once when the listener is attached to a stream.
voidonShutdown()Called once when the listener is detached or the stream stops.
booleanimmediate(DetectionResponse)Called per detection response, if methods includes immediate.
booleanbatch(ArrayList&lt;DetectionResponse&gt;)Called periodically with a batch of accumulated responses, if methods includes batch.
booleanrollup(DetectionResponse)Called on a rollup interval with a response, if methods includes rollup.

Method detail

getVersion

static String getVersion()

Returns the version string of the IVifEventListener API your listener was compiled against — useful for logging or diagnostics when multiple listener versions may be in play.

onInit

default void onInit(IApplicationInstance appInstance,
                     IMediaStream stream,
                     Set<String> methods,
                     HashMap<String, Object> properties)

Called once, when VIF attaches this listener to a stream.

Parameters:

  • appInstance — the WSE application instance the stream belongs to.
  • stream — the media stream this listener instance is attached to.
  • methods — the delivery modes configured for this listener (any combination of "immediate", "batch", "rollup" — see EventMethodType).
  • properties — the listener's configured properties map from video-intelligence.json, passed through as a raw HashMap<String, Object>. There's no schema enforcement at this layer — implementations read and type-convert each expected key themselves. Before calling onInit, VIF also writes a set of standard keys into this same map (see below).

Standard properties injected by VIF:

Before onInit is called, VIF adds the following keys to the properties map, on top of whatever you configured. They're written after your configured entries, so these names are reserved — a configured property that reuses one of these names is overwritten by VIF's value.

KeyValue type in mapDescription
stream_nameStringSource stream name (stream.getName()).
widthStringSource video width in pixels (from the stream's codec config).
heightStringSource video height in pixels.
vif_widthStringWidth of the frame VIF sends to the detector — the inference resolution, derived from inference_video_height and the source aspect ratio.
vif_heightStringHeight of the frame VIF sends to the detector.
frame_rateStringSource frame rate in fps (rounded to a whole number).
detector_typeStringThe detector running on the stream: object, scene, vlm, or synthetic.
confidence_thresholdDoubleThis listener's configured confidence_threshold (default 0.0, meaning no filtering) — the per-listener value, not the detector's object_analysis / scene_analysis threshold.

Every value is inserted as a String except confidence_threshold, which is a Double. Because the map is typed <String, Object>, read the values defensively:

String streamName = (String) properties.get("stream_name");
int    srcWidth   = Integer.parseInt(properties.get("width").toString());
int    srcHeight  = Integer.parseInt(properties.get("height").toString());
int    vifWidth   = Integer.parseInt(properties.get("vif_width").toString());
int    vifHeight  = Integer.parseInt(properties.get("vif_height").toString());
int    frameRate  = Integer.parseInt(properties.get("frame_rate").toString());
String detector   = (String) properties.get("detector_type");
double confidence = ((Number) properties.get("confidence_threshold")).doubleValue();

Typical use: parse properties into typed fields, store appInstance/stream references, and set up any external resources (for example, obtaining a shared singleton like WebhookListener).

onShutdown

default void onShutdown()

Called once, when the listener is detached from its stream or the stream stops. Release anything acquired in onInit here — timers, connections, in-progress work tied to this listener instance.

immediate

default boolean immediate(DetectionResponse response)

Called for each individual detection response, only if "immediate" is in this listener's configured methods. Lowest-latency delivery path.

Returns: true if the response was consumed/acted on; false otherwise.

batch

default boolean batch(ArrayList<DetectionResponse> responses)

Called periodically with a group of accumulated responses, only if "batch" is in this listener's configured methods.

Returns: true if the batch was consumed/acted on; false otherwise.

rollup

default boolean rollup(DetectionResponse response)

Called on a rollup interval with a response, only if "rollup" is in this listener's configured methods. For object detections, the rollup response carries statistical summaries (average, min, max, standard deviation) rather than raw per-frame values — see ObjectDetectionRollupData below.

Returns: true if the rollup was consumed/acted on; false otherwise.


Enum EventMethodType

package com.wowza.wms.plugin.videointelligence.event;

public enum EventMethodType {
    DISABLED, IMMEDIATE, BATCH, ROLLUP
}

The four values a listener's methods configuration maps to.


Class DetectionResponse

package com.wowza.wms.plugin.videointelligence.message;

public class DetectionResponse extends Message {
    public String createdAt;
    public DetectionWindowData detectionWindow;
    public Integer preprocessTimeMs;
    public Integer inferenceTimeMs;
    public Integer postprocessTimeMs;
    public Integer totalProcessingTimeMs;
    public String detectionsType;
    public Long sequenceId;

    public <T> ArrayList<T> getDetections();
    public void setDetections(ArrayList detections);
    public DetectionResponse clone();
}

The base class delivered to immediate, batch, and rollup. Fields are public, not getter-accessed — there's no getCreatedAt()/getSequenceId(), you read the fields directly.

At runtime, the object passed to your listener is always one of the concrete subclasses below, never a bare DetectionResponse — check detectionsType or use instanceof to determine which.

FieldTypeDescription
createdAtStringTimestamp the response was created.
detectionWindowDetectionWindowDataThe frame/time range this response covers — see below.
preprocessTimeMs / inferenceTimeMs / postprocessTimeMs / totalProcessingTimeMsIntegerPer-stage processing time in milliseconds.
detectionsTypeStringDiscriminates which concrete subclass this is.
sequenceIdLongMonotonically increasing sequence number for ordering responses.

Subclass ObjectDetectionResponse

public class ObjectDetectionResponse extends DetectionResponse {
    public ArrayList<ObjectDetectionData> detections;
}

Subclass SceneDetectionResponse

public class SceneDetectionResponse extends DetectionResponse {
    // detections field is package-private; use getDetections()
    public ArrayList<SceneDetectionData> getDetections();
}

Subclass VlmDetectionResponse

public class VlmDetectionResponse extends DetectionResponse {
    public boolean isStructured;
    public String modelName;
    public String content;
    public Integer tokenCount;
    public Boolean truncated;
    public static final String FREEFORM_CLASS_NAME;

    public void parseContent();
    public ArrayList<VlmDetectionData> getDetections();
}

isStructured distinguishes Custom mode (a JSON schema response, isStructured = true) from Detect/Describe mode (free-text, isStructured = false). content holds the raw model output before parsing; parseContent() populates detections from it. FREEFORM_CLASS_NAME is the sentinel class name used for Describe mode results, which have no real class name.


Class DetectionData (and subclasses)

package com.wowza.wms.plugin.videointelligence.message;

public class DetectionData {
    public String className;
    public Double confidence;
    public String reasoning;

    public String toJsonStr();
}

The per-item entries inside getDetections(). reasoning is populated for VLM results (the model's stated justification for the class) and generally null for object/scene detections.

Subclass ObjectDetectionData

public class ObjectDetectionData extends DetectionData {
    public Integer trackId;
    public int frameId;
    public BoundingBoxData bbox;
}

trackId is null for detections without a confirmed tracking ID yet (VIF interleaves these with tracked detections — see the wall-clock-not-response-cadence guidance in the how-to article).

Subclass SceneDetectionData / VlmDetectionData

Both currently add no additional public fields beyond the DetectionData base (className, confidence, reasoning).


Class BoundingBoxData

public class BoundingBoxData {
    public int x;
    public int y;
    public int w;
    public int h;

    public int getX2();  // x + w
    public int getY2();  // y + h
}

Pixel coordinates in the analyzed frame. Not present at all for scene or VLM detections, since those aren't spatially localized.


Class DetectionWindowData

public class DetectionWindowData {
    public Long fromFrameId;
    public Long toFrameId;
    public Long frameCount;
    public String fromFrame;
    public String toFrame;
    public Long fromTimeCode;
    public Long toTimeCode;
    public Long behindLiveMs;
    public Boolean caughtUp;
    public Long skippedFrames;
    public Long skippedMs;
}

behindLiveMs, caughtUp, skippedFrames, and skippedMs relate to VIF's catch-up-to-live behavior (see the catch_up_to_live / catch_up_max_behind_seconds config fields) — useful if your listener needs to know whether a given response reflects real-time analysis or catch-up-skipped frames.


Class ObjectDetectionRollupData / ObjectDetectionRollupValue

Delivered inside rollup() responses for object detections — statistical summaries instead of raw per-frame values.

public class ObjectDetectionRollupData {
    public Integer trackId;
    public String className;
    public ObjectDetectionRollupValue confidence, x, y, x2, y2, h, w;
    public Integer firstFrameId;
    public Integer lastFrameId;
    public Double duration;
    public Long samples;
}

public class ObjectDetectionRollupValue {
    public Double avg, stdDev, min, max, first, last, sum;
    public Long sampleSize;
}

Each spatial/confidence value is summarized (average, min, max, standard deviation, first, last) over the rollup interval rather than delivered as a single point-in-time value.


See also