import { StreamStatisticsSampling } from "@norskvideo/norsk-api/lib/media_pb"; import { AutoProcessorMediaNode, AutoSinkMediaNode, ProcessorNodeSettings, SinkNodeSettings } from "./common"; import { AudioGraphMeasurement } from "./processor"; import { Interval, PlainMessage, StreamKey, SubtitleFragment, TeletextLine } from "./types"; import { MqaAudioWeights, MqaConfig } from "./mqa"; /** * @public * Settings to control stream timestamp report * see {@link NorskInspect.streamTimestampReport} */ export interface StreamTimestampReportSettings extends SinkNodeSettings { onTimestamp?: (streamKey: StreamKey, timestamp: Interval, info: { duration?: Interval; }) => void; } /** * @public * see: {@link NorskInspect.streamTimestampReport} */ export declare class StreamTimestampReportNode extends AutoSinkMediaNode { } /** * @public */ export type Cta608Command = string | { type: string; text: string; }; /** * @public */ export interface InspectSubtitleChunk { streamKey: StreamKey; startTimestamp: Interval; endTimestamp: Interval; /** The full text contained in this chunk, which may not be split or formatted as for final output yet - to observe this insert a SubtitleConvert */ text: string; /** Whether the subtitle chunk is "complete" or may later be revised. The chunk need not be a full sentence/utterance to be complete, but a partial chunk is one which may later be extended/revised a number of times */ isComplete: boolean; /** When the subtitle has individually timed fragments (words or short chunks) such as a transcription result, the result fragments */ fragments: SubtitleFragment[]; /** If the stream is a Teletext caption/subtitle, this is a representation of the source page containing some layout, colouring, ect info */ teletext: TeletextLine[]; /** If the stream is TTML - full source of that TTML document. Note this will generally represent a single cue or ISD */ ttml?: { text: string; mediatime_ms: number; }; /** If the stream is CTA-608 (CEA-608), a representation of the 608 commands */ cta608: Cta608Command[]; } /** * @public * Settings to subtitles inspect node * see {@link NorskInspect.subtitles} */ export interface InspectSubtitlesSettings extends SinkNodeSettings { /** * Callback to observe subtitle chunks/cues in the subscribed stream. * * Timestamps are not directly related to cue timings, but Norsk timestamps as per timestamp report. * * @param cue * @returns */ onCue?: (chunk: InspectSubtitleChunk) => void; } /** * @public * see: {@link NorskInspect.subtitles} */ export declare class InspectSubtitlesNode extends AutoSinkMediaNode { } /** * @public * Settings for metrics node * see {@link NorskInspect.metrics} */ export interface MetricsSettings extends SinkNodeSettings { name: string; includeTimestamps: boolean; includeStreams: boolean; streamStatistics?: { statsSampling?: PlainMessage; }; labels: { [k: string]: string; }; } /** * @public * see: {@link NorskInspect.metrics} */ export declare class MetricsNode extends AutoSinkMediaNode { } /** * @public * Black-frame detection configuration for the QualityMonitoring node. * Only operational parameters live here; hysteresis thresholds have moved * to {@link QualityReportingVideoSettings}. */ export interface QualityMonitoringBlackDetectSettings { /** Pixels with luma below this normalised value are considered "black". Default 0.063 (~ 16/255). */ pixelThreshold?: number; } /** * @public * Frozen-frame detection configuration for the QualityMonitoring node. * Presence enables freeze-detect processing; all hysteresis configuration * has moved to {@link QualityReportingVideoSettings}. */ export interface QualityMonitoringFreezeDetectSettings { } /** * @public * Per-architecture knobs for NR-IQA models on the QualityMonitoring node. * Only the sampling cadence lives here; hysteresis thresholds have moved to * {@link QualityReportingVideoSettings}. */ export interface NrIqaModelSettings { /** * Minimum media wall-clock between inferences, in milliseconds — the * analysis cadence, invariant to the source frame rate. `0` = every frame * (still latency-gated). Omit for the per-model default: 200ms for the * still-image models (DBCNN/MUSIQ/LAR-IQA), 1000ms for UVQ (video-native at * full 1080p, so much heavier). */ sampleEveryMs?: number; } /** * @public * NR-IQA (no-reference image quality assessment) configuration. Pick exactly * one model. The Spectrum preprocessor builds whatever per-scale * ImageNet-normalised RGB float32 tensors the chosen model needs (DBCNN: a * single 224²; LAR-IQA: 384² + 1280²; MUSIQ: 224² + 384² + 640²). * * scoreThreshold is interpreted on the common normalised [0..100] scale, * regardless of the model's native output range. */ export type QualityMonitoringNrIqaSettings = { kind: "larIqa"; config: NrIqaModelSettings; } | { kind: "dbcnn"; config: NrIqaModelSettings; } | { kind: "musiq"; config: NrIqaModelSettings; } | { kind: "uvq"; config: NrIqaModelSettings; }; /** * @public * Video-side quality monitoring configuration. Each detection is individually * configurable; omit to disable. */ export interface QualityMonitoringVideoSettings { blackDetect?: QualityMonitoringBlackDetectSettings; freezeDetect?: QualityMonitoringFreezeDetectSettings; nrIqa?: QualityMonitoringNrIqaSettings; /** * Analysis latency budget in milliseconds: a frame is never held awaiting * its measurements for longer than this. On expiry it ships with the most * recent completed analysis (analysisLagMs set) and onAnalysisLagging * fires. Default 1000. */ latencyBudgetMs?: number; } /** * @public * Silence detection operational params. The threshold + analysis window live * here; the duration-based hysteresis is configured on the QualityReporting node. */ export interface QualityMonitoringSilenceDetectSettings { /** A window is silent when its loudest channel's RMS is below this (dB). Default -60. */ thresholdDb?: number; /** RMS analysis window in milliseconds. Default 20. */ windowMs?: number; } /** * @public * Audio monitoring configuration. Each detector carries only operational params * (threshold / window); the duration-based hysteresis is configured on the * QualityReporting node. */ export interface QualityMonitoringAudioSettings { /** Silence detection — omit to disable. */ silenceDetect?: QualityMonitoringSilenceDetectSettings; /** Clipping / digital-overs detection — omit to disable. */ clipDetect?: { /** Sample level (0..1 FS) counted as "clipped". Default 0.99. */ threshold?: number; /** Analysis window in milliseconds. Default 20. */ windowMs?: number; }; /** DC-offset detection — omit to disable. */ dcDetect?: { /** Analysis window in milliseconds. Default 100. */ windowMs?: number; }; /** Stereo inter-channel correlation (phase) — omit to disable. */ correlationDetect?: { /** Analysis window in milliseconds. Default 100. */ windowMs?: number; }; /** Dead-channel (a dropped L/R) detection — omit to disable. */ deadChannelDetect?: { /** A channel below this RMS (dB) while another is above counts as dropped. Default -60. */ floorDb?: number; /** Analysis window in milliseconds. Default 100. */ windowMs?: number; }; /** * Enables the FFT tap that feeds the tone / static-noise / mains-hum alerts. * The individual alerts are configured on the QualityReporting node; enable * this here if you use any of them. Omit to disable. */ spectralDetect?: { /** FFT window in milliseconds (becomes the FFT size). Default 85 (~4096 @ 48k). */ windowMs?: number; }; /** * Enables the EBU R128 loudness tap that feeds the loudness-range and * true-peak alerts (configured on QualityReporting). Omit to disable. */ loudnessDetect?: { /** Reporting cadence in milliseconds (ebur128 gates internally). Default 100. */ windowMs?: number; }; /** * Stuck/frozen-feed detector: flags consecutive bit-identical analysis * windows (a wedged capture card or decoder repeating its last buffer). * Pure digital silence is not flagged — that's silenceDetect's job. The * sustained alert is configured on QualityReporting (`stuckDetect`). */ stuckDetect?: { /** Comparison window in milliseconds. Default 500. */ windowMs?: number; }; /** * Per-channel level meter (RMS + peak) — the VU-meter substrate. Enabling it * adds a meter tap whose per-channel readings stream out via * {@link QualityMonitoringSettings.onAudioMeasurement}. Omit to disable (the * detector readings still stream; there are just no per-channel levels). */ meterDetect?: { /** RMS/peak integration window in milliseconds. Default 100. */ windowMs?: number; /** Peak-hold time before decay, in milliseconds. Default 0. */ holdMs?: number; /** Oversampled inter-sample true-peak (vs sample peak). Default false. */ truePeak?: boolean; }; } /** * @public * Dynamic configuration update for the QualityMonitoring node. * Only NR-IQA sample cadence, the latency budget, and the black-detect * threshold can be changed at runtime. */ export interface QualityMonitoringDynamicConfig { /** * New NR-IQA sample interval in milliseconds (0 = every frame). Omit to * leave the sample cadence unchanged. */ sampleEveryMs?: number; /** New analysis latency budget (ms). Omit to leave unchanged. */ latencyBudgetMs?: number; /** * Black detector config. `pixelThreshold` is a runtime Halide Param, so it * rebinds live with no recompile. Omit `blackDetect` to leave it unchanged. */ blackDetect?: { pixelThreshold: number; }; } /** * @public * Settings for the QualityMonitoring node. * see {@link NorskInspect.qualityMonitoring} */ export interface QualityMonitoringSettings extends ProcessorNodeSettings { /** Video monitoring configuration — omit to disable video monitoring entirely. */ video?: QualityMonitoringVideoSettings; /** Audio monitoring configuration — omit to disable audio monitoring entirely. */ audio?: QualityMonitoringAudioSettings; /** * Analysis fell behind: frames are shipping at the latency budget without * their own measurements (scores carry forward with analysisLagMs set). */ onAnalysisLagging?: (event: { lagMs: number; }) => void; /** Analysis caught back up within the latency budget. */ onAnalysisRecovered?: () => void; /** * Analysis degraded to pure passthrough (e.g. the decode child died and is * being respawned). MQA write should cease while degraded. */ onAnalysisDegraded?: (event: { reason: string; }) => void; /** Analysis restored after a degrade. */ onAnalysisRestored?: () => void; /** * The adaptive NR-IQA sampler changed the effective sample interval (ms) to * stay within the latency budget. `0` = sampling suspended (overloaded). */ onSamplingAdapted?: (event: { previousSampleEveryMs: number; sampleEveryMs: number; }) => void; /** * How long an NR-IQA inference took (submit → complete) — the analysis * latency, distinct from the decode-pipeline hold (analysisLagMs). Reported * once per completed inference. */ onAnalysisLatency?: (event: { latencyMs: number; }) => void; /** * The (off-loop) Spectrum/NR-IQA pipeline compilation has finished and * analysis is now running against decoded frames. Until this fires, encoded * frames pass straight through unanalysed, so wait for it before expecting * measurements for a specific event. Raised once, on the compressed-input path. */ onAnalysisRunning?: () => void; /** * Called once per analysis window with that window's audio measurements — * whole-stream detector readings (silence/clip/dc/…) plus, when * {@link QualityMonitoringAudioSettings.meterDetect} is enabled, per-channel * meter levels (`channel` set). Decoded with the same machinery as * {@link AudioGraphSettings.onMeasurement}. Use this for a per-channel VU meter. */ onAudioMeasurement?: (measurements: AudioGraphMeasurement[]) => void; /** * Convenience view of the same event: the window's whole-stream readings * folded by metric family (`{ silence: { rms_db, silent }, clip: { clip_ratio }, … }`), * last-value-wins per source — the shape the detector-value box consumes * directly. Per-channel meter levels are omitted here; use * {@link QualityMonitoringSettings.onAudioMeasurement} for those. */ onAudioReadings?: (readings: Record>) => void; } /** * @public * see: {@link NorskInspect.qualityMonitoring} * * QualityMonitoring is a ProcessorNode — it analyses incoming video frames, * annotates them with quality decisions, and forwards the annotated frames * to downstream subscribers (e.g. a QualityReporting node). */ export declare class QualityMonitoringNode extends AutoProcessorMediaNode<"video"> { /** * Dynamically update the NR-IQA sampling rate while the node is running. * @param config - Partial config; only provided fields are updated. */ updateConfig(config: QualityMonitoringDynamicConfig): void; } /** * @public * Video-side quality reporting configuration. Each detection carries its * own hysteresis thresholds; omit to disable that detection. */ /** * @public * Audio reporting configuration. Silence hysteresis is duration-based (ms), * since audio frames are variable-size; the level threshold is set on the * QualityMonitoring node. */ export interface QualityReportingAudioSettings { /** Silence detection with duration-based hysteresis — omit to disable. */ silenceDetect?: { minSilenceMs?: number; minClearMs?: number; }; /** Clipping alert: clip_ratio above `threshold` sustained — omit to disable. */ clipDetect?: { threshold?: number; minActiveMs?: number; minClearMs?: number; }; /** DC-offset alert: |dc_offset| above `threshold` sustained — omit to disable. */ dcDetect?: { threshold?: number; minActiveMs?: number; minClearMs?: number; }; /** Phase alert: correlation below `threshold` (e.g. < 0 = out of phase) — omit to disable. */ correlationDetect?: { threshold?: number; minActiveMs?: number; minClearMs?: number; }; /** Dead-channel alert: the dropout flag sustained — omit to disable. */ deadChannelDetect?: { minActiveMs?: number; minClearMs?: number; }; /** Tone/test-tone alert: peak_ratio above `threshold` sustained — requires spectralDetect on QM. */ toneDetect?: { threshold?: number; minActiveMs?: number; minClearMs?: number; }; /** Static-noise alert: spectral_flatness above `threshold` sustained — requires spectralDetect on QM. */ noiseDetect?: { threshold?: number; minActiveMs?: number; minClearMs?: number; }; /** Mains-hum alert: hum_energy above `threshold` sustained — requires spectralDetect on QM. */ humDetect?: { threshold?: number; minActiveMs?: number; minClearMs?: number; }; /** Loudness alert: short-term loudness outside `target` ± `tolerance` LUFS — requires loudnessDetect on QM. */ loudnessRangeDetect?: { target?: number; tolerance?: number; minActiveMs?: number; minClearMs?: number; }; /** True-peak alert: true peak above `maxDbtp` — requires loudnessDetect on QM. */ truePeakDetect?: { maxDbtp?: number; minActiveMs?: number; minClearMs?: number; }; /** * Emit MqaAudioScore events whenever the aggregated SVTA MQA-AUDIO * composite score (integer [0..100]) changes. */ reportMqaAudio?: boolean; /** Optional MQA-AUDIO aggregation weights. When omitted, server defaults are used. */ mqaAudioWeights?: MqaAudioWeights; /** Signal-lost alert: no audio frames for `timeoutMs` on a still-advertised stream — omit to disable. */ signalLostDetect?: { timeoutMs?: number; }; /** Dual-mono alert: correlation ABOVE `threshold` (default 0.99) sustained — * "stereo" that is actually mono. Requires correlationDetect on QM. */ dualMonoDetect?: { threshold?: number; minActiveMs?: number; minClearMs?: number; }; /** Stuck/frozen-feed alert sustained — requires stuckDetect on QM. */ stuckDetect?: { minActiveMs?: number; minClearMs?: number; }; } export interface QualityReportingVideoSettings { /** Black-frame detection with hysteresis — omit to disable. */ blackDetect?: { frameThreshold?: number; minBlackFrames?: number; minClearFrames?: number; }; /** Freeze-frame detection with hysteresis — omit to disable. */ freezeDetect?: { freezeThreshold?: number; minFrozenFrames?: number; minMovingFrames?: number; }; /** NR-IQA quality detection with hysteresis — omit to disable. */ nrIqa?: { scoreThreshold: number; minPoorFrames?: number; minGoodFrames?: number; }; /** * Emit MqaVideoScore events whenever the aggregated SVTA MQA-VIDEO * composite score (integer [0..100]) changes. Uses the default aggregation * weights defined in the PureScript QualityMetrics module. */ reportMqaVideo?: boolean; /** Optional MQA quality-metric aggregation weights. When omitted, server defaults are used. */ mqaConfig?: MqaConfig; /** Signal-lost alert: no video frames for `timeoutMs` on a still-advertised stream — omit to disable. */ signalLostDetect?: { timeoutMs?: number; }; } /** * @public * Dynamic configuration update for the QualityReporting node. * All fields are optional -- only provided fields are updated; omitted * fields keep their current values. */ export interface QualityReportingDynamicConfig { /** Black-frame detection thresholds. */ blackDetect?: { frameThreshold?: number; minBlackFrames?: number; minClearFrames?: number; }; /** Freeze-frame detection thresholds. */ freezeDetect?: { freezeThreshold?: number; minFrozenFrames?: number; minMovingFrames?: number; }; /** NR-IQA quality detection thresholds. */ nrIqa?: { scoreThreshold: number; minPoorFrames?: number; minGoodFrames?: number; }; /** Enable/disable MQA-VIDEO composite score reporting. */ reportMqaVideo?: boolean; /** Optional MQA aggregation weights. */ mqaConfig?: MqaConfig; /** Signal-lost detection timeout; omit to disable. */ signalLostDetect?: { timeoutMs?: number; }; /** * Audio alert configuration. Omit to leave the audio alerts unchanged; * provide to replace them in full (an omitted detector is disabled) — so * every audio alert is individually enable/disable-able at runtime. */ audio?: QualityReportingAudioSettings; } /** * @public * Settings for the QualityReporting node. * see {@link NorskInspect.qualityReporting} */ export interface QualityReportingSettings extends SinkNodeSettings { /** Video reporting configuration — omit to disable video reporting entirely. */ video?: QualityReportingVideoSettings; /** Audio reporting configuration — omit to disable audio reporting entirely. */ audio?: QualityReportingAudioSettings; /** Called when a stream has been silent for at least minSilenceMs. */ onSilenceDetected?: (event: { streamKey: StreamKey; rmsDb: number; }) => void; /** Called when signal returns after silence (minClearMs of audio). */ onSilenceEnded?: (event: { streamKey: StreamKey; durationMs: number; }) => void; /** Called when clipping begins (clip_ratio above threshold, sustained). */ onClippingDetected?: (event: { streamKey: StreamKey; clipRatio: number; }) => void; /** Called when clipping ends. */ onClippingEnded?: (event: { streamKey: StreamKey; durationMs: number; }) => void; /** Called when a DC-offset run begins (|dc_offset| above threshold, sustained). */ onDcOffsetDetected?: (event: { streamKey: StreamKey; dcOffset: number; }) => void; /** Called when a DC-offset run ends. */ onDcOffsetEnded?: (event: { streamKey: StreamKey; durationMs: number; }) => void; /** Called when a phase issue begins (correlation below threshold, sustained). */ onPhaseIssueDetected?: (event: { streamKey: StreamKey; correlation: number; }) => void; /** Called when a phase issue ends. */ onPhaseIssueEnded?: (event: { streamKey: StreamKey; durationMs: number; }) => void; /** Called when a channel-dropout run begins. */ onDeadChannelDetected?: (event: { streamKey: StreamKey; }) => void; /** Called when a channel-dropout run ends. */ onDeadChannelEnded?: (event: { streamKey: StreamKey; durationMs: number; }) => void; /** Called when a tone run begins; `freq` is the dominant frequency (Hz). */ onToneDetected?: (event: { streamKey: StreamKey; freq: number; }) => void; /** Called when a tone run ends. */ onToneEnded?: (event: { streamKey: StreamKey; durationMs: number; }) => void; /** Called when a static-noise run begins (`flatness` ≈ 1 = flat spectrum). */ onNoiseDetected?: (event: { streamKey: StreamKey; flatness: number; }) => void; /** Called when a static-noise run ends. */ onNoiseEnded?: (event: { streamKey: StreamKey; durationMs: number; }) => void; /** Called when a mains-hum run begins (`humEnergy` = relative 50/60Hz energy). */ onHumDetected?: (event: { streamKey: StreamKey; humEnergy: number; }) => void; /** Called when a mains-hum run ends. */ onHumEnded?: (event: { streamKey: StreamKey; durationMs: number; }) => void; /** Called when short-term loudness goes outside target ± tolerance; `lufs` is the current short-term value. */ onLoudnessOutOfRange?: (event: { streamKey: StreamKey; lufs: number; }) => void; /** Called when loudness returns within range. */ onLoudnessInRange?: (event: { streamKey: StreamKey; durationMs: number; }) => void; /** Called when true peak exceeds the ceiling; `dbtp` is the peak (dBTP). */ onTruePeakOver?: (event: { streamKey: StreamKey; dbtp: number; }) => void; /** Called when true peak returns below the ceiling. */ onTruePeakOk?: (event: { streamKey: StreamKey; durationMs: number; }) => void; /** Called when a dual-mono run begins (correlation held above the threshold). */ onDualMonoDetected?: (event: { streamKey: StreamKey; correlation: number; }) => void; /** Called when the dual-mono condition clears. */ onDualMonoEnded?: (event: { streamKey: StreamKey; durationMs: number; }) => void; /** Called when a stuck/frozen-feed run begins. */ onStuckDetected?: (event: { streamKey: StreamKey; }) => void; /** Called when the feed unsticks. */ onStuckEnded?: (event: { streamKey: StreamKey; durationMs: number; }) => void; /** Called when a black-frame run begins (after minBlackFrames consecutive black frames). */ onBlackFrameDetected?: (event: { streamKey: StreamKey; blackPixelRatio: number; }) => void; /** Called when a black-frame run ends (after minClearFrames consecutive non-black frames). */ onBlackFrameEnded?: (event: { streamKey: StreamKey; durationFrames: number; }) => void; /** Called when a freeze-frame run begins (after minFrozenFrames consecutive frozen frames). */ onFreezeDetected?: (event: { streamKey: StreamKey; freezeScore: number; }) => void; /** Called when a freeze-frame run ends (after minMovingFrames consecutive moving frames). */ onFreezeEnded?: (event: { streamKey: StreamKey; durationFrames: number; }) => void; /** Called when an NR-IQA poor-quality run begins (after minPoorFrames consecutive sub-threshold scores). */ onNrIqaQualityDegraded?: (event: { streamKey: StreamKey; score: number; }) => void; /** Called when an NR-IQA poor-quality run ends. */ onNrIqaQualityRestored?: (event: { streamKey: StreamKey; durationFrames: number; }) => void; /** * Called with the aggregated SVTA MQA-VIDEO composite score (emitted only when * reportMqaVideo is enabled) — whenever it changes, and otherwise periodically * so the `components` breakdown stays live. Each component is present only when * measured this report (psnr/ssim need the encoder; nrIqa is sampled). */ onMqaVideoScore?: (event: { streamKey: StreamKey; score: number; components?: { psnr?: number; ssim?: number; nrIqa?: number; blackRatio?: number; freezeScore?: number; }; analysisLagMs?: number; }) => void; /** * Called each time the aggregated SVTA MQA-AUDIO composite score changes * (emitted only when reportMqaAudio is enabled). */ onMqaAudioScore?: (event: { streamKey: StreamKey; score: number; }) => void; /** * Called when no frames have arrived on a still-advertised stream for at * least the configured signalLostDetect timeout (transport up, media * stalled — the stream disappearing entirely is a subscription change, * not this event). */ onSignalLost?: (event: { streamKey: StreamKey; }) => void; /** Called when frames resume after a signal-lost period. */ onSignalRestored?: (event: { streamKey: StreamKey; outageMs: number; }) => void; /** * Called with the TR 101 290 transport-stream error counters (ETR 101 290 * priorities 1-3). Only fires on TS-based ingest. `counters` are CUMULATIVE * running totals since the stream started (Prometheus-counter style) — a * consumer differences successive reports for windowed counts / rates. * Emitted at most ~1/s, and only when a counter has advanced. */ onTsErrors?: (event: { streamKey: StreamKey; counters: { syncLoss: number; syncByteErrors: number; ccErrorsDuplicate: number; ccErrorsOutOfOrder: number; patErrors: number; pmtErrors: number; pidErrors: number; transportErrors: number; crcErrors: number; pcrRepetitionErrors: number; pcrDiscontinuityErrors: number; pcrAccuracyErrors: number; ptsErrors: number; catErrors: number; unreferencedPids: number; siRepetitionErrors: number; totalPackets: number; }; }) => void; } /** * @public * see: {@link NorskInspect.qualityReporting} */ export declare class QualityReportingNode extends AutoSinkMediaNode { /** * Dynamically update detection thresholds and MQA config while the node is * running. Only provided fields are updated; omitted fields keep their * current values on the server. * @param config - Partial dynamic config update. */ updateConfig(config: QualityReportingDynamicConfig): void; } /** * @public * Methods that allow you to inspect media streams, for monitoring, decisioning or debug purposes. */ export interface NorskInspect { /** Intercept all the timestamps of any subscribed stream * @param settings - Configuration for the report node */ streamTimestampReport(settings: StreamTimestampReportSettings): Promise; /** * Observe the subtitle content in a subtitle stream. * * The chunks of subtitling/captioning data observed may consist of fully formatted cues (e.g. where they are coming from a stream * already in WebVTT format) or text which has not yet been split/formatted (possibly with word-level timestamps). These can be modified and sent to a streamWebVtt input * @param settings - Configuration for the report node */ subtitles(settings: InspectSubtitlesSettings): Promise; /** * Generate metrics for one or more input streams * * These will end up in the telemetry store and are exportable via the prometheus endpoint * or an otel collector */ streamMetrics(settings: MetricsSettings): Promise; /** * Continuously monitor stream quality (black frame detection, with more * detections to follow). Emits transition events when configured thresholds * are crossed. */ qualityMonitoring(settings: QualityMonitoringSettings): Promise; /** * Report quality events from a stream that already has quality decisions * written to its per-frame qualityMetrics (e.g. by an upstream * QualityMonitor). Does no detection work itself. */ qualityReporting(settings: QualityReportingSettings): Promise; } //# sourceMappingURL=inspect.d.ts.map