{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"VIF Custom Event Listener API Reference","description":"Developer documentation for Wowza","siteUrl":"https://developer.wowza.com","keywords":"wowza video developer portal, api reference docs","lang":"en-US","image":"https://www.wowza.com/wp-content/uploads/Graphics-Social-Profile-Images-Docs-Resources-1024x512-1.jpg","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"vif-custom-event-listener-api-reference","__idx":0},"children":["VIF Custom Event Listener API Reference"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["VIF delivers detection results to event listeners which are Java classes that implement ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IVifEventListener"]},". This"," ","reference documents that interface and the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DetectionResponse"]}," class hierarchy passed to it. For a guided"," ","walkthrough with a worked example, see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://www.wowza.com/docs/create-a-video-intelligence-event-listener"},"children":["Create a custom VIF event listener"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"interface-ivifeventlistener","__idx":1},"children":["Interface ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IVifEventListener"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"package com.wowza.wms.plugin.videointelligence.api;\n\npublic interface IVifEventListener {\n    static String getVersion();\n    default void onInit(IApplicationInstance appInstance, IMediaStream stream,\n                         Set<String> methods, HashMap<String, Object> properties);\n    default void onShutdown();\n    default boolean immediate(DetectionResponse response);\n    default boolean batch(ArrayList<DetectionResponse> responses);\n    default boolean rollup(DetectionResponse response);\n}\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["All five instance methods are ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["default"]}]},". An implementation only needs to override the ones relevant"," ","to it. A listener that only uses ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["immediate"]}," delivery, for example, doesn't need to provide ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["batch"]}," or"," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["rollup"]}," overrides at all; the interface's defaults cover the rest."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"method-summary","__idx":2},"children":["Method summary"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Modifier and type"},"children":["Modifier and type"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Method"},"children":["Method"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["static String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#getversion"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["getVersion()"]}]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Returns the plugin API version."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["void"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#oninit"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onInit(...)"]}]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Called once when the listener is attached to a stream."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["void"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#onshutdown"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onShutdown()"]}]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Called once when the listener is detached or the stream stops."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["boolean"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#immediate"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["immediate(DetectionResponse)"]}]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Called per detection response, if ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["methods"]}," includes ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["immediate"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["boolean"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#batch"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["batch(ArrayList&lt;DetectionResponse&gt;)"]}]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Called periodically with a batch of accumulated responses, if ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["methods"]}," includes ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["batch"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["boolean"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#rollup"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["rollup(DetectionResponse)"]}]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Called on a rollup interval with a response, if ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["methods"]}," includes ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["rollup"]},"."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"method-detail","__idx":3},"children":["Method detail"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"getversion","__idx":4},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["getVersion"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"static String getVersion()\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Returns the version string of the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IVifEventListener"]}," API your listener was compiled against — useful for"," ","logging or diagnostics when multiple listener versions may be in play."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"oninit","__idx":5},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onInit"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"default void onInit(IApplicationInstance appInstance,\n                     IMediaStream stream,\n                     Set<String> methods,\n                     HashMap<String, Object> properties)\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Called once, when VIF attaches this listener to a stream."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Parameters:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["appInstance"]}," — the WSE application instance the stream belongs to."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["stream"]}," — the media stream this listener instance is attached to."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["methods"]}," — the delivery modes configured for this listener (any combination of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"immediate\""]},","," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"batch\""]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"rollup\""]}," — see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"#enum-eventmethodtype"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["EventMethodType"]}]},")."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["properties"]}," — the listener's configured ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["properties"]}," map from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["video-intelligence.json"]},", passed through"," ","as a raw ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["HashMap<String, Object>"]},". There's no schema enforcement at this layer — implementations read"," ","and type-convert each expected key themselves. Before calling ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onInit"]},", VIF also writes a set of standard"," ","keys into this same map (see below)."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Standard properties injected by VIF:"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Before ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onInit"]}," is called, VIF adds the following keys to the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["properties"]}," map, on top of whatever you"," ","configured. They're written ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["after"]}," your configured entries, so these names are reserved — a configured"," ","property that reuses one of these names is overwritten by VIF's value."]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Key"},"children":["Key"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Value type in map"},"children":["Value type in map"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["stream_name"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Source stream name (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["stream.getName()"]},")."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["width"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Source video width in pixels (from the stream's codec config)."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["height"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Source video height in pixels."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["vif_width"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Width of the frame VIF sends to the detector — the inference resolution, derived from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["inference_video_height"]}," and the source aspect ratio."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["vif_height"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Height of the frame VIF sends to the detector."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["frame_rate"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Source frame rate in fps (rounded to a whole number)."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["detector_type"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The detector running on the stream: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["object"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["scene"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["vlm"]},", or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["synthetic"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["confidence_threshold"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Double"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["This listener's configured ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["confidence_threshold"]}," (default ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["0.0"]},", meaning no filtering) — the per-listener value, not the detector's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["object_analysis"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["scene_analysis"]}," threshold."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Every value is inserted as a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["String"]}," ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["except"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["confidence_threshold"]},", which is a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Double"]},". Because the"," ","map is typed ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["<String, Object>"]},", read the values defensively:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"String streamName = (String) properties.get(\"stream_name\");\nint    srcWidth   = Integer.parseInt(properties.get(\"width\").toString());\nint    srcHeight  = Integer.parseInt(properties.get(\"height\").toString());\nint    vifWidth   = Integer.parseInt(properties.get(\"vif_width\").toString());\nint    vifHeight  = Integer.parseInt(properties.get(\"vif_height\").toString());\nint    frameRate  = Integer.parseInt(properties.get(\"frame_rate\").toString());\nString detector   = (String) properties.get(\"detector_type\");\ndouble confidence = ((Number) properties.get(\"confidence_threshold\")).doubleValue();\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Typical use:"]}," parse ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["properties"]}," into typed fields, store ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["appInstance"]},"/",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["stream"]}," references, and set up"," ","any external resources (for example, obtaining a shared singleton like ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["WebhookListener"]},")."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"onshutdown","__idx":6},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onShutdown"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"default void onShutdown()\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Called once, when the listener is detached from its stream or the stream stops. Release anything acquired"," ","in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onInit"]}," here — timers, connections, in-progress work tied to this listener instance."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"immediate","__idx":7},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["immediate"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"default boolean immediate(DetectionResponse response)\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Called for each individual detection response, only if ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"immediate\""]}," is in this listener's configured"," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["methods"]},". Lowest-latency delivery path."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Returns:"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]}," if the response was consumed/acted on; ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["false"]}," otherwise."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"batch","__idx":8},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["batch"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"default boolean batch(ArrayList<DetectionResponse> responses)\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Called periodically with a group of accumulated responses, only if ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"batch\""]}," is in this listener's"," ","configured ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["methods"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Returns:"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]}," if the batch was consumed/acted on; ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["false"]}," otherwise."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"rollup","__idx":9},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["rollup"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"default boolean rollup(DetectionResponse response)\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Called on a rollup interval with a response, only if ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"rollup\""]}," is in this listener's configured ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["methods"]},"."," ","For object detections, the rollup response carries statistical summaries (average, min, max, standard"," ","deviation) rather than raw per-frame values — see"," ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"#class-objectdetectionrollupdata"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ObjectDetectionRollupData"]}]}," below."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Returns:"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]}," if the rollup was consumed/acted on; ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["false"]}," otherwise."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"enum-eventmethodtype","__idx":10},"children":["Enum ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["EventMethodType"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"package com.wowza.wms.plugin.videointelligence.event;\n\npublic enum EventMethodType {\n    DISABLED, IMMEDIATE, BATCH, ROLLUP\n}\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The four values a listener's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["methods"]}," configuration maps to."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"class-detectionresponse","__idx":11},"children":["Class ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DetectionResponse"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"package com.wowza.wms.plugin.videointelligence.message;\n\npublic class DetectionResponse extends Message {\n    public String createdAt;\n    public DetectionWindowData detectionWindow;\n    public Integer preprocessTimeMs;\n    public Integer inferenceTimeMs;\n    public Integer postprocessTimeMs;\n    public Integer totalProcessingTimeMs;\n    public String detectionsType;\n    public Long sequenceId;\n\n    public <T> ArrayList<T> getDetections();\n    public void setDetections(ArrayList detections);\n    public DetectionResponse clone();\n}\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The base class delivered to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["immediate"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["batch"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["rollup"]},". Fields are ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["public"]},", not"," ","getter-accessed — there's no ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["getCreatedAt()"]},"/",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["getSequenceId()"]},", you read the fields directly."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["At runtime, the object passed to your listener is always one of the concrete subclasses below, never a bare"," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DetectionResponse"]}," — check ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["detectionsType"]}," or use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["instanceof"]}," to determine which."]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Field"},"children":["Field"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Type"},"children":["Type"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["createdAt"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Timestamp the response was created."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["detectionWindow"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DetectionWindowData"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The frame/time range this response covers — see below."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["preprocessTimeMs"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["inferenceTimeMs"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["postprocessTimeMs"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["totalProcessingTimeMs"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Integer"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Per-stage processing time in milliseconds."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["detectionsType"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Discriminates which concrete subclass this is."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sequenceId"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Long"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Monotonically increasing sequence number for ordering responses."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"subclass-objectdetectionresponse","__idx":12},"children":["Subclass ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ObjectDetectionResponse"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"public class ObjectDetectionResponse extends DetectionResponse {\n    public ArrayList<ObjectDetectionData> detections;\n}\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"subclass-scenedetectionresponse","__idx":13},"children":["Subclass ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SceneDetectionResponse"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"public class SceneDetectionResponse extends DetectionResponse {\n    // detections field is package-private; use getDetections()\n    public ArrayList<SceneDetectionData> getDetections();\n}\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"subclass-vlmdetectionresponse","__idx":14},"children":["Subclass ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["VlmDetectionResponse"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"public class VlmDetectionResponse extends DetectionResponse {\n    public boolean isStructured;\n    public String modelName;\n    public String content;\n    public Integer tokenCount;\n    public Boolean truncated;\n    public static final String FREEFORM_CLASS_NAME;\n\n    public void parseContent();\n    public ArrayList<VlmDetectionData> getDetections();\n}\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["isStructured"]}," distinguishes ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Custom"]}," mode (a JSON schema response, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["isStructured = true"]},") from"," ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Detect"]},"/",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Describe"]}," mode (free-text, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["isStructured = false"]},"). ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["content"]}," holds the raw model output"," ","before parsing; ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["parseContent()"]}," populates ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["detections"]}," from it. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["FREEFORM_CLASS_NAME"]}," is the sentinel class"," ","name used for ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Describe"]}," mode results, which have no real class name."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"class-detectiondata-and-subclasses","__idx":15},"children":["Class ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DetectionData"]}," (and subclasses)"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"package com.wowza.wms.plugin.videointelligence.message;\n\npublic class DetectionData {\n    public String className;\n    public Double confidence;\n    public String reasoning;\n\n    public String toJsonStr();\n}\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The per-item entries inside ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["getDetections()"]},". ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["reasoning"]}," is populated for VLM results (the model's stated"," ","justification for the class) and generally null for object/scene detections."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"subclass-objectdetectiondata","__idx":16},"children":["Subclass ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ObjectDetectionData"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"public class ObjectDetectionData extends DetectionData {\n    public Integer trackId;\n    public int frameId;\n    public BoundingBoxData bbox;\n}\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["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)."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"subclass-scenedetectiondata--vlmdetectiondata","__idx":17},"children":["Subclass ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SceneDetectionData"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["VlmDetectionData"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Both currently add no additional public fields beyond the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DetectionData"]}," base (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["className"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["confidence"]},","," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["reasoning"]},")."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"class-boundingboxdata","__idx":18},"children":["Class ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["BoundingBoxData"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"public class BoundingBoxData {\n    public int x;\n    public int y;\n    public int w;\n    public int h;\n\n    public int getX2();  // x + w\n    public int getY2();  // y + h\n}\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Pixel coordinates in the analyzed frame. Not present at all for scene or VLM detections, since those aren't"," ","spatially localized."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"class-detectionwindowdata","__idx":19},"children":["Class ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DetectionWindowData"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"public class DetectionWindowData {\n    public Long fromFrameId;\n    public Long toFrameId;\n    public Long frameCount;\n    public String fromFrame;\n    public String toFrame;\n    public Long fromTimeCode;\n    public Long toTimeCode;\n    public Long behindLiveMs;\n    public Boolean caughtUp;\n    public Long skippedFrames;\n    public Long skippedMs;\n}\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["behindLiveMs"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["caughtUp"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["skippedFrames"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["skippedMs"]}," relate to VIF's catch-up-to-live behavior (see"," ","the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["catch_up_to_live"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"class-objectdetectionrollupdata--objectdetectionrollupvalue","__idx":20},"children":["Class ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ObjectDetectionRollupData"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ObjectDetectionRollupValue"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Delivered inside ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["rollup()"]}," responses for object detections — statistical summaries instead of raw"," ","per-frame values."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"public class ObjectDetectionRollupData {\n    public Integer trackId;\n    public String className;\n    public ObjectDetectionRollupValue confidence, x, y, x2, y2, h, w;\n    public Integer firstFrameId;\n    public Integer lastFrameId;\n    public Double duration;\n    public Long samples;\n}\n\npublic class ObjectDetectionRollupValue {\n    public Double avg, stdDev, min, max, first, last, sum;\n    public Long sampleSize;\n}\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"see-also","__idx":21},"children":["See also"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://www.wowza.com/docs/create-a-video-intelligence-event-listener"},"children":["Create a custom VIF event listener"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://www.wowza.com/docs/access-vif-logs-in-wowza-streaming-engine"},"children":["Access VIF logs in WSE"]}]}]}]},"headings":[{"value":"VIF Custom Event Listener API Reference","id":"vif-custom-event-listener-api-reference","depth":1},{"value":"Interface IVifEventListener","id":"interface-ivifeventlistener","depth":2},{"value":"Method summary","id":"method-summary","depth":3},{"value":"Method detail","id":"method-detail","depth":3},{"value":"getVersion","id":"getversion","depth":4},{"value":"onInit","id":"oninit","depth":4},{"value":"onShutdown","id":"onshutdown","depth":4},{"value":"immediate","id":"immediate","depth":4},{"value":"batch","id":"batch","depth":4},{"value":"rollup","id":"rollup","depth":4},{"value":"Enum EventMethodType","id":"enum-eventmethodtype","depth":2},{"value":"Class DetectionResponse","id":"class-detectionresponse","depth":2},{"value":"Subclass ObjectDetectionResponse","id":"subclass-objectdetectionresponse","depth":3},{"value":"Subclass SceneDetectionResponse","id":"subclass-scenedetectionresponse","depth":3},{"value":"Subclass VlmDetectionResponse","id":"subclass-vlmdetectionresponse","depth":3},{"value":"Class DetectionData (and subclasses)","id":"class-detectiondata-and-subclasses","depth":2},{"value":"Subclass ObjectDetectionData","id":"subclass-objectdetectiondata","depth":3},{"value":"Subclass SceneDetectionData / VlmDetectionData","id":"subclass-scenedetectiondata--vlmdetectiondata","depth":3},{"value":"Class BoundingBoxData","id":"class-boundingboxdata","depth":2},{"value":"Class DetectionWindowData","id":"class-detectionwindowdata","depth":2},{"value":"Class ObjectDetectionRollupData / ObjectDetectionRollupValue","id":"class-objectdetectionrollupdata--objectdetectionrollupvalue","depth":2},{"value":"See also","id":"see-also","depth":2}],"frontmatter":{"seo":{"title":"VIF Custom Event Listener API Reference"}},"lastModified":"2026-07-24T01:53:46.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/docs/wowza-video-intelligence-framework/vif-custom-event-listener-api-reference","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}