import { AudioGraphParam, AudioGraphState, StreamStatisticsSampling, Subscription, SipEvent_Status, KantarSnapLicenseInformation as KantarSnapLicenseInformationPB, SourceTimeConfiguration } from "@norskvideo/norsk-api/lib/media_pb"; import { ReasoningPlanSession, ReasoningPlanSettings } from "./reasoningPlan"; import { ReasoningEvaluateNode, ReasoningEvaluateSettings } from "./reasoningEvaluate"; import { LivePlanSession, LivePlanSettings } from "./livePlan"; import { LiveEvaluateNode, LiveEvaluateSettings } from "./liveEvaluate"; import { MqaConfig } from "./mqa"; import { FrameRate, VancPayloadFormat, VancType2AncillaryId } from "../types"; import { SpectrumExpression } from "./spectrum"; import type { ColorPrimaries, TransferFunction, VideoRange } from "./spectrum"; import { AutoSinkMediaNode, MediaClient, MediaNodeState, SourceMediaNode, SourceMediaNodeEvents, StreamStatisticsMixin, AutoProcessorMediaNode, ProcessorNodeSettings } from "./common"; import { AacBitrateMode, AacProfile, DolbyDigitalEncoderBackend, AudioMeasureLevels, AwsCredentials, ChannelLayout, ComposeMissingStreamBehaviour, ComposeHardwareAcceleration, StreamSwitchSmoothHardwareAcceleration, Db, IceServerSettings, LoganH264, LoganHevc, MultiStreamStatistics, NvidiaH264, NvidiaHevc, PixelFormat, QuadraH264, QuadraHevc, AmdU30H264, AmdU30Hevc, AmdMA35DH264, AmdMA35DHevc, Resolution, SampleAspectRatio, SampleRate, SentenceBuildMode, SimpleEasing, StabilizationMode, StreamKey, StreamMetadata, X264Codec, X265Codec, SubscriptionError, DeinterlaceSettings, Scte35SpliceInfoSection, Interval, fromInterval, SampleFormat, VideoStreamMetadata, QuadraAv1, AmdMA35DAv1, QuadraPipelineHints, JitterBufferConfig, SubtitleFragment, MainConceptHevcCodec, SvtJpegXsCodec, FrameRateSettings, PlainMessage } from "./types"; import { Writable, Readable } from 'stream'; import { Norsk } from "../sdk"; import { EmbeddedAINode, EmbeddedAINodeSettings } from "./embeddedAI"; import type { BrowserAppSettings } from "./input"; /** @public */ export interface ProcessorMediaNode extends SourceMediaNode, AutoSinkMediaNode { } /** @public */ export declare class ProcessorMediaNode { constructor(client: MediaClient, unregisterNode: (node: MediaNodeState) => void, getGrpcStream: () => (Readable | Writable), subscribeFn: (subscription: Subscription) => Promise, subscribeErrorFn?: (error: SubscriptionError) => void, subscribedStreamsChangedFn?: (streams: StreamMetadata[]) => void); onError(): void; } /** * @public * Settings for the Hard Stream Switch * see: {@link NorskControl.streamSwitchHard} * */ export interface StreamSwitchHardSettings extends ProcessorNodeSettings> { /** The currently active source to display on the output */ activeSource: Pins; /** the source name to give the output of this switch operation */ outputSource: string; /** * Maximum duration to hold any stream in the case that one or more are running behind. In the case the late * stream is delayed rather than having a large gap, this will result in discarded input frames. */ maxQueueMs?: number; /** * Optionally delay all streams by a fixed (wallclock) duration. This option is provided to allow decisions on switching * to be made with the benefit of a buffer's worth of foresight, specifically if a stream should disappear, actioning the switch * to a backup stream can be made early enough that the switch can occur on a keyframe */ bufferDelayMs?: number; /** Callback which will be called if a switch request cannot be fulfilled */ onSwitchError?: (message: string, inputPin?: Pins) => void; /** * Callback which will be called if a switch request has been effectuated - that is, after a source switch is requested and * has been accepted (is not an error), the desired source is now active on the output. For video sources, this means that * a keyframe (IDR/IRAP/etc) has arrived on (at least one video stream), for audio-only sources this will be any frame. */ onSwitchComplete?: (source?: string) => void; /** * Callback to be called when inbound context changes on some input; presence of an * input means that media has arrived and is ready to switch * immediately * * Note that in combination with {@link StreamSwitchHardSettings.bufferDelayMs} this event represents the * delayed media context (i.e. still ready to switch immediately according to this context, but any observation * of early changes must happen upstream). * * @param allStreams - The collection of input contexts received over all input pins */ onInboundContextChange?: (allStreams: Map) => Promise; /** Starting stream ID for the output video stream (default 1) */ startVideoStreamId?: number; /** Starting stream ID for the output audio stream (default 2) */ startAudioStreamId?: number; /** Starting stream ID for the output subtitle stream (default 257) */ startSubtitleStreamId?: number; /** Starting stream ID for the output ancillary stream (default 513) */ startAncillaryStreamId?: number; /** * When true, strip volatile metadata fields (currently `bitrate` on compressed * audio/video) from the output context. Useful when downstream consumers are * sensitive to context churn caused by the active source's instantaneous * bitrate fluctuating. Defaults to false. */ stripVolatileMetadata?: boolean; /** * When true, suppress transient/partial output contexts during source * transitions. The output context only changes when the new context is * either fully empty (carries teardown semantics) or contains at least * the streams of the previously-emitted one; identical-to-previous * contexts are deduped. Pairs naturally with `stripVolatileMetadata` when * downstream is sensitive to context churn. Defaults to false. */ stableOutputContext?: boolean; } /** * @public * see: {@link NorskControl.streamSwitchHard} */ export declare class StreamSwitchHardNode extends ProcessorMediaNode { /** * @public * The currently active source (that is, the source which has been requested to be active - may not yet be present on the output * until the corresponding event is raised). */ get activeSource(): Pins | undefined; private _activeSource?; /** * @public * Switch to a new active source at its first valid keyframe; the old * source's still-arriving frames stop emitting at the same instant. * For the gapless-playlist pattern (where the previous source's tail * must keep playing while the next source warms up), use * {@link NorskControl.streamSourceSequence} instead. */ switchSource(newSource: Pins): Promise; } /** * @public * Settings for the StreamSourceSequence node. * see {@link NorskControl.streamSourceSequence} * * Plays an ordered sequence of sources gaplessly. Companion to (and the * recommended replacement for) the {@link NorskControl.streamSwitchHard} * playlist pattern. Downstream sees a single logical stream with stream * keys stable across source turnover. * * Unlike `streamSwitchHard`, SSQ has no per-pin hold/release/switch API * surface — the client describes the sequence and the node runs it. The * only client-driven action is `advanceNow()` to trigger an early cut at * the next source's next IDR. */ export interface StreamSourceSequenceSettings extends ProcessorNodeSettings> { /** The source name to give the unified output stream. */ outputSource: string; /** * The ordered sequence of source pins to play. The first entry plays * first; later entries activate as earlier ones reach EOF (or via the * {@link StreamSourceSequenceNode.advanceNow} trigger). May be empty * at construction and appended to later via * {@link StreamSourceSequenceNode.appendSource}. */ sources: { pin: Pins; /** * How to transition from the previous source. Default `hardCutAtEof` * waits for the previous source to fully drain. `hardCutAtIdr` is * for the manual early-switch case (paired with `advanceNow()`). * Ignored on the first entry (no previous source). */ transitionFromPrevious?: 'hardCutAtEof' | 'hardCutAtIdr'; }[]; /** Starting stream ID for the unified output video stream. */ startVideoStreamId?: number; /** Starting stream ID for the unified output audio stream. */ startAudioStreamId?: number; /** Starting stream ID for the unified output subtitle stream. */ startSubtitleStreamId?: number; /** Starting stream ID for the unified output ancillary stream. */ startAncillaryStreamId?: number; /** * Reorder window for the internal cross-source DTS sort. Default 200 * ms — sized to cover B-frame ptsOffset plus cross-source jitter at * the boundary, while staying small enough for sub-second steady-state * latency. */ reorderWindowMs?: number; /** * Audio silence-pad threshold. Audio gaps below this are sub-frame * and not worth filling; the default 10 ms is appropriate for typical * AAC frame durations. */ audioSilencePadGapThresholdMs?: number; /** * Audio silence-pad cap. Gaps larger than this are almost certainly * a bug (e.g. a wild PTS jump) and the node prefers to surface them * as a gap rather than fill with arbitrary silence. Default 500 ms. */ audioSilencePadMaximumFillMs?: number; /** * When true, strip volatile metadata fields (currently `bitrate` on * compressed audio/video) from the output context so downstream * consumers don't see spurious context changes when the active * source's instantaneous bitrate fluctuates. Defaults to false. */ stripVolatileMetadata?: boolean; /** * Fires when the node has handed off to a new active source. The * pin in the callback is whichever source is now feeding the output. * * `lastSeenPts`, when present, is the last PTS (microseconds) the * engine emitted from the PREVIOUS active pin — the source that * just ended. Absent (`undefined`) on the very first Advance (no * previous source). Clients use this for cross-switch PTS * continuity: feed it back as `anchorPts` on a sibling switch's * `releasePreloaded` so the next pin's video PTS picks up where * the previous pin's last PTS left off. */ onAdvance?: (nowActive: Pins, lastSeenPts: number | undefined) => void; /** * Fires when the engine's currently-active source has fully drained * (natural EOF or synthetic via `endCurrentSource`). `endedPin` is * the pin that just ended; `lastSeenPts` is the last PTS * (microseconds) the engine emitted from it. Feed it back as * `anchorPts` on the destination switch's `releasePreloaded` for * PTS-continuous handoff (same-mode SSQ→SSQ or cross-mode SSQ→SSS). * * SSQ no longer auto-advances from the declared sequence — every * transition is the client's responsibility. After `onSourceEnded` * fires, no frames are being emitted until `releasePreloaded` is * called. */ onSourceEnded?: (endedPin: Pins, lastSeenPts: number) => void; /** * Fires when the engine holds a source pin (pre-warmed, queued, * ready). Re-fires whenever the held pin's stream complement * changes so the client can wait for an expected shape (e.g. * audio + video both present) before pausing the upstream and * choosing release timing. * * Held pins remain held until the client calls * `releasePreloaded(pin, { anchorPts })`. SSQ mirrors SSS in this * respect — every pin (including the first one in the sequence) is * held until explicitly released. */ onPreloaded?: (pin: Pins, streamKeys: StreamKey[]) => void; /** * Active-pin sibling of `onPreloaded`: fires when the currently- * active pin's seen-stream-key set changes — typically the first * time each stream emits a frame on the active pin after a * paused-then-resumed upstream. Distinct from `onAdvance` (source * change only) and `onPreloaded` (held pins only). * * The most common scenario this signals is a passthrough preload * that goes directly active (no holding window) because it was the * only source in the sequence — when the client later resumes the * paused upstream, this callback fires as each stream's first * frame arrives. Without it, downstream switches that gate on the * active pin's stream complement have no event to react to. */ onStreamsChanged?: (pin: Pins, streamKeys: StreamKey[]) => void; } /** * @public * StreamSourceSequence — plays an ordered sequence of sources gaplessly. */ export declare class StreamSourceSequenceNode extends ProcessorMediaNode { /** * @public * Append a source to the end of the sequence. The pin must be * subscribed upstream (via `subscribeToPins`) for its frames to flow. */ appendSource(pin: Pins, transitionFromPrevious?: 'hardCutAtEof' | 'hardCutAtIdr'): void; /** * @public * Manually trigger an early cut to the next source in the sequence, * at that source's next IDR. The previous source's frames after that * IDR (in display order) are dropped. */ advanceNow(): void; /** * @public * End the currently active source immediately. The engine fires a * synthetic `PreloadEnded` for the active pin, which surfaces as the * existing `onAdvance` callback with `lastSeenPts` set to the * source's last rebased output PTS (engine's `state.latestOutputPts` * captured atomically at the synthetic-end moment). * * After this call, no further frames from the just-ended pin flow * downstream — the engine inserts the tag into its `trimmedSources` * map so any in-flight upstream frames are silently dropped at * `processInput`. * * Useful for cross-node manual cuts where the caller wants to anchor * the next node's `releasePreloaded` at the just-ended source's PTS * (mirrors SSS's `endCurrentSource` — symmetric API). * * If a `releasePreloaded(pin, ...)` was previously queued via * `pendingRelease`, the `Advance` callback fires for that pin; * otherwise it fires for the sequence-next pin. * * Idempotent — calling a second time while the tag is already ended * is a silent no-op (logged engine-side, no callback re-fires). * No-op when there is no active source. */ endCurrentSource(): Promise; /** * @public * Signal that no further sources will be released onto the output. * The engine ends the current active source (synthetic `PreloadEnded`, * mirroring `endCurrentSource`) and then emits a terminal empty * context downstream. Consumers (HLS / CMAF / SRT muxers) take that * empty context as their cue to flush the last segment and tag * end-of-stream cleanly. * * Distinct from `close()`: `endSequence()` lets the SSQ keep running * (e.g. for callers that want to observe downstream finalisation * before tearing the node down). Idempotent and a no-op if a * sequence-end is already in flight. */ endSequence(): Promise; /** * @public * Tell the engine which pin to release on the NEXT source boundary, * overriding the autopilot's default "next-pin-from-sequence" pick * for that single transition. Mirrors SSH's `releasePreloaded` * semantics: the client is responsible for any upstream pause/play * around the release, and chooses when each held pin should advance * onto the output. Pair with `onPreloaded` and an upstream * `pause()` to backpressure long-lived held sources. * * `options.anchorPts` — optional video-display PTS anchor (in * microseconds) for the released pin's rebase. Used by clients * that need cross-switch PTS continuity (e.g. when an HSS * downstream is alternating between SSS-output and SSQ-output and * the boundary needs the OTHER switch's last PTS as the anchor). * **Phase 3a note**: SSQ accepts this on the wire but does not yet * apply it — the SSQ release path runs through the autopilot's * setHoldDecision, which isn't anchor-aware yet. Phase 3b lands * the full plumbing. */ releasePreloaded(pin: Pins, options?: { anchorPts?: number; }): void; } /** * @public * Settings for the Smooth Source Switch * see {@link NorskControl.streamSwitchSmooth} * */ export interface StreamSwitchSmoothSettings extends ProcessorNodeSettings> { /** The presently active source being used to generate output for this node */ activeSource?: Pins; /** The source name given to the output of this node */ outputSource: string; /** How many milliseconds to use for the fade operation between two sources */ transitionDurationMs?: number; /** The constant resolution that all output video will be scaled to */ outputResolution: Resolution; /** The constant framerate that all output video will be sampled to */ frameRate: FrameRate; /** The constant samplerate that all output audio will be resampled to */ sampleRate: SampleRate; /** The sample format of the built outgoing stream (Defaults to FLTP)*/ sampleFormat?: SampleFormat; /** The constant channel layout that all output audio will be resampled to */ channelLayout: ChannelLayout; /** Alignment behaviour of the component * whether to rebase all incoming streams to a common timeline * Note: This will modify the timestamps, meaning that merging streams not involved in this may result in * operation may result in sync issues. To avoid this, you can use {@link NorskTransform.streamAlign} instead of relying * on this component for this behaviour * Note: This behaviour may be removed in a future release and replaced with something similar * */ alignment?: "aligned" | "not_aligned"; /** Callback which will be called if a switch request cannot be fulfilled */ onSwitchError?: (message: string, inputPin?: Pins) => void; /** Callback which will be called a transition has succesfully completed for a requested switch, i.e. the new source * is now showing. * * Note that if additional transitions are triggered when a transition is already in progress, a notification may only be * given for the last transition to finish. **/ onTransitionComplete?: (inputPin: Pins) => void; /** * Callback to be called when inbound context changes on some input; presence of an * input means that media has arrived and is ready to switch * immediately * @param allStreams - The collection of input contexts received over all input pins */ onInboundContextChange?: (allStreams: Map) => Promise; /** * Optionally attempt to perform the compose operation on hardware */ hardwareAcceleration?: StreamSwitchSmoothHardwareAcceleration; /** * Extra options for influencing how the pipeline gets constructed and what algorithms get used for certain operations. * Silently ignored when the operation does not run on Quadra hardware. */ pipelineHints?: QuadraPipelineHints; /** * Maximum duration to hold any stream in the case that one or more are running behind. In the case the late * stream is delayed rather than having a large gap, this will result in discarded input frames. */ maxQueueMs?: number; /** Latency in milliseconds for the audio gap filler. Higher values allow * better concealment of gaps/overlaps at the cost of added audio delay. * Defaults to 0 (no latency). */ audioLatencyMs?: number; /** Starting stream ID for the output video stream (default 1) */ startVideoStreamId?: number; /** Starting stream ID for the output audio stream (default 2) */ startAudioStreamId?: number; /** * Called on the first frame of any source pin. Return "hold" to queue frames * for that pin (for preloading), or "passthrough" to let them flow normally. * Return an object form (e.g. `{ release: "other" }` or `{ hold: true, release: "other" }`) * to additionally release another held pin atomically as part of the same decision. */ onFirstFrame?: (pin: Pins, streams: StreamMetadata[]) => Promise<"hold" | "passthrough" | { hold?: boolean; release?: Pins; }>; /** * Called whenever the visible stream count for a source pin changes (grows or shrinks but * not to zero). Return "hold" to start queueing frames for that pin, "passthrough" to * release a held pin and let frames flow, or `undefined` to acknowledge the change without * altering the pin's current hold/passthrough state. Return an object form (e.g. * `{ hold: true, release: "other" }` or `{ release: "other" }`) to additionally release * another held pin atomically as part of the same decision. Return `{ trim: true }` to * declare the source is winding down — any remaining frames on this pin are dropped at * the preload stage until its onSourceEnded fires. This callback blocks context * propagation until it returns. */ onSourceChanged?: (pin: Pins, streams: StreamMetadata[]) => Promise<"hold" | "passthrough" | void | { hold?: boolean; keep?: boolean; release?: Pins; trim?: boolean; }>; /** * Called when a source's streams disappear on a pin (e.g. file ended). This callback * blocks context propagation - use it to set up the next source before returning. * * `lastSeenPts` (microseconds) is the last PTS this switch's engine emitted from the * ending pin across ALL streams (max END-OF-FRAME of audio + video + any fill). * * `lastSeenVideoPts` (microseconds, optional) is the video-stream-only end-PTS. * Prefer this when feeding back as `anchorPts` to a sibling switch whose downstream * is a hard switch (`streamSwitchHard`) gating on video-only `lastOutput` — if the * ending source's audio tail extends past its last video frame, `lastSeenPts` would * overshoot the hard switch's video-only `lastOutput` and the sibling's IDR would be * dropped at the gate. Falls back to `undefined` when the ending pin had no emitted * video (in which case use `lastSeenPts`). */ onSourceEnded?: (pin: Pins, lastSeenPts: number | undefined, lastSeenVideoPts: number | undefined) => Promise<{ release?: Pins; } | void>; } export interface StreamSwitchSmoothSwitchOptions { /** Duration to switch for this transition only (if omitted, the configured default shall be used, to suppress a transition specify this but as 0). */ transitionDurationMs?: number; } /** * @public * see: {@link NorskControl.streamSwitchSmooth} */ export declare class StreamSwitchSmoothNode extends ProcessorMediaNode { /** * @public * The currently active source */ get activeSource(): Pins | undefined; private _activeSource?; /** * @public * Switches the source used for the current output of this node */ switchSource(newSource: Pins, options?: StreamSwitchSmoothSwitchOptions): Promise; /** * @public * Release held frames for a preloaded pin, allowing them to flow through with rebased timestamps. * * `options.anchorPts` — optional video-display PTS anchor (in * microseconds) overriding the engine's internal per-pin * `videoPrevEndByTag` tracking for this release. Used by clients * needing cross-switch PTS continuity (e.g. when an HSS downstream * alternates between SSS-output and SSQ-output and the boundary * needs the OTHER switch's last PTS as the anchor). Audio + DTS * anchors still use internal tracking. */ releasePreloaded(pin: Pins, options?: { anchorPts?: number; }): void; /** * @public * End the currently active source immediately. The engine fires a * synthetic `PreloadEnded` for the active pin, which surfaces as the * existing `onSourceEnded(pin, lastSeenPts)` callback with * `lastSeenPts` set to the source's last rebased output PTS * (engine's `state.latestOutputPts` captured atomically at the * synthetic-end moment). * * After this call, no further frames from the just-ended pin flow * downstream — the engine inserts the tag into its `trimmedSources` * map so any in-flight upstream frames are silently dropped at * `processInput`. * * Useful for cross-node manual cuts where the caller wants to anchor * the next node's `releasePreloaded` at the just-ended source's PTS * (e.g. an HSS downstream alternating between SSS- and SSQ-output — * the SSS's `lastSeenPts` becomes the SSQ's `anchorPts`). * * Idempotent — calling a second time while the tag is already ended * is a silent no-op (logged engine-side, no callback re-fires). * No-op when there is no active source. */ endCurrentSource(): Promise; /** * Park the switch in a silent state and forget all internal clock * and audio-transition bookkeeping. The next `switchSource` will be * processed as a cold-start switch — the new pin's first emitted * frame becomes the new PTS baseline rather than being interpreted * as a continuation of the previously-active source's timeline. * * Use this when the switch is being parked between consumer windows * — e.g. when an HSS downstream is routing to a sibling switch and * this switch's output is not on the wire. Without `silence`, the * switch's compose chain retains `latestPts` etc. from its previous * activeSource; when it later resumes for an anchored cross-mode * handoff, that stale anchor collides with the new pin's intended * one and produces a multi-second forward jump that downstream * encoders / muxers report as a timestamp discontinuity. * * After this call: no output frames flow until a subsequent * `switchSource` or `releasePreloaded`. The switch remains * subscribed to its inputs — no upstream teardown. */ silence(): Promise; } /** * @public * Settings for a Stream Statistics Node * see: {@link NorskControl.streamStatistics} */ export interface StreamStatisticsSettings extends ProcessorNodeSettings, StreamStatisticsMixin { /** * Called periodically with the stream stats * @param stats - The statistics for the stream * @eventProperty */ onStreamStatistics?: (stats: MultiStreamStatistics) => void; /** * Sampling rates for stream stats, in seconds */ statsSampling?: PlainMessage; } /** * @public * see {@link NorskControl.streamStatistics}. */ export declare class StreamStatisticsNode extends AutoProcessorMediaNode<"audio" | "video"> { } /** * @public * Settings for an AudioMeasureLevelsNode * see: {@link NorskControl.audioMeasureLevels} */ export interface AudioMeasureLevelsSettings extends ProcessorNodeSettings { /** * Called with the audio level data * @param levels - The level data for the audio stream * @eventProperty */ onData: (levels: AudioMeasureLevels) => void; /** Optionally control the sample frequency */ intervalFrames?: number; } /** * @public * see: {@link NorskControl.audioMeasureLevels}. */ export declare class AudioMeasureLevelsNode extends AutoProcessorMediaNode<"audio"> { } export type GeminiApiAuth = { authType: "geminiApi"; googleApiKey: string; }; export type VertexAuth = { authType: "vertex"; project: string; location: string; serviceAccountFile?: string; }; export type GeminiAuth = GeminiApiAuth | VertexAuth; /** * @public * Settings for Gemini Video */ export interface GeminiVideoSettings { resolution: Resolution; frameRate: FrameRate; } /** * @public * Gemini status enumeration */ export type GeminiStatus = "connected" | "setupCompleted" | "turnComplete"; /** * @public * Authentication for OpenAI Realtime */ export type OpenAIAuth = { authType: "apiKey"; apiKey: string; }; /** * @public * Settings for a Stream Timestamp Nudge * see: {@link NorskTransform.streamTimestampNudge} * */ export interface StreamTimestampNudgeSettings extends ProcessorNodeSettings { /** the initial nudge to apply, in milliseconds */ nudge?: number; } /** * @public * see: {@link NorskTransform.streamTimestampNudge} */ export declare class StreamTimestampNudgeNode extends AutoProcessorMediaNode<"audio" | "video"> { /** * @public * Applies a gradual nudge to the stream timestamps by the specified number of milliseconds * */ nudge(nudge: number): void; } /** * @public * Settings for a Stream Key Override * see: {@link NorskTransform.streamKeyOverride} * */ export interface StreamKeyOverrideSettings extends ProcessorNodeSettings { /** The stream key that all frames passing through this node will be assigned */ streamKey: StreamKey; metrics?: "enabled" | "minimal" | "none"; } /** * @public * see: {@link NorskTransform.streamKeyOverride} */ export declare class StreamKeyOverrideNode extends AutoProcessorMediaNode<"audio" | "video" | "subtitle"> { } /** * @public * Settings for a Stream Metadata Override Node * see: {@link NorskTransform.streamMetadataOverride} * */ export interface StreamMetadataOverrideSettings extends ProcessorNodeSettings, StreamMetadataOverrideSettingsUpdate { } /** * @public * A single rectangular region of interest. Coordinates are normalised to * [0, 1] relative to the frame's own width / height; `qOffset` follows the * FFmpeg AVRegionOfInterest convention: -1.0 = best possible quality, * +1.0 = worst, 0.0 = no change. */ export interface RoiRegion { left: number; top: number; right: number; bottom: number; qOffset: number; } /** * @public * Region-of-interest metadata to attach to raw video frames. An empty * `regions` list is the "no ROI" state. */ export interface RoiMetadata { regions: RoiRegion[]; } /** * @public * Colour information for a raw video stream, as H.273 / ISO-IEC 23091-2 code * points. Set on {@link StreamMetadataOverrideSettingsUpdate} to force a * source's colour metadata (e.g. BT.709) so it matches its siblings and avoids * a downstream switch seeing a colour-context change. */ export interface ColourInfo { /** Colour primaries code point (e.g. 1 = BT.709, 9 = BT.2020). */ primaries: number; /** Transfer characteristics code point (e.g. 1 = BT.709, 16 = PQ, 18 = HLG). */ transferCharacteristics: number; /** Matrix coefficients code point (e.g. 1 = BT.709, 9 = BT.2020 NCL). */ matrixCoefficients: number; /** Full-range flag (false = limited / "TV" range). */ fullRange: boolean; /** Chroma sample location code point (e.g. 0 = left, 2 = top-left). */ chromaLocation: number; } /** @public */ export interface StreamMetadataOverrideSettingsUpdate { video?: { /** Override the bitrate metadata of a compressed video stream, or `0` to clear */ bitrate?: number; /** Override the ROI metadata attached to a raw video stream, or an empty * regions list to clear */ roi?: RoiMetadata; /** Override the colour information of a raw video stream (e.g. force BT.709 * so it matches its siblings and avoids a downstream switch-time colour * context change). Leaving it unset preserves the upstream value. */ colourInfo?: ColourInfo; }; audio?: { /** Override the bitrate metadata of a compressed audio stream, or `0` to clear */ bitrate?: number; /** Override the language metadata of an audio stream, or `""` to clear. RFC 5646 language tag. */ language?: string; }; subtitles?: { /** Override the language metadata of a subtitles stream, or `""` to clear. RFC 5646 language tag. */ language?: string; /** Override the property of whether a subtitles string is the default/primary rendition or not */ default?: boolean; }; playlist?: { /** Override the name of a playlist stream, or `""` to clear. Free form text. */ name?: string; }; } /** * @public * see: {@link NorskTransform.streamMetadataOverride} */ export declare class StreamMetadataOverrideNode extends AutoProcessorMediaNode<"audio" | "video" | "subtitle"> { /** * @public * Updates the config used by this metadata override node for all subsequent frames * @param settings - The new settings */ updateConfig(settings: StreamMetadataOverrideSettingsUpdate): void; } /** * @public * Settings for a Jitter Buffer * see: {@link NorskTransform.jitterBuffer} * */ export interface JitterBufferSettings extends ProcessorNodeSettings { /** Buffer delay in milliseconds */ delayMs: number; } /** * @public * see: {@link NorskTransform.jitterBuffer} */ export declare class JitterBufferNode extends AutoProcessorMediaNode<"audio" | "video" | "subtitle"> { } /** * @public * Settings for a StreamSync node * see {@link NorskTransform.streamSync} * */ export interface StreamSyncSettings extends ProcessorNodeSettings { /** * Maximum duration to hold any stream in the case that one or more are running behind. In the case the late * stream is delayed rather than having a large gap, this will result in discarded input frames. */ maxQueueMs?: number; /** * When enabled, converts gaps to discontinuities and ensures that every stream has a discontinuity if a single stream has one * This means we can then use EXT-X-DISCONTINUITY tag generation in HLS outputs instead of EXT-X-GAP tags */ injectDiscontinuities?: boolean; /** When enabled, wait for subtitles. This is almost never what you want as it will delay most outputs substantially. The only reason (normally) to include subtitles in a stream sync is to include them within the injectDicontinuity logic */ syncSubtitles?: boolean; } /** * @public * see: {@link NorskTransform.streamSync} */ export declare class StreamSyncNode extends AutoProcessorMediaNode<"audio" | "video"> { } /** * @public * Settings for a StreamAlign node * This will reset all streams to the same framerates/sample rates * and align their timestamps so that they completely line up for downstream operations * see {@link NorskTransform.streamAlign} * */ export interface StreamAlignSettings extends ProcessorNodeSettings { /** The normalisd sample rate of the audio output */ sampleRate: SampleRate; /** The normalised frame rate of the video output */ frameRate: FrameRate; /** Synchronise audio/video sources aggressively to start at the same timestamp by dropping frames until a video keyframe occurs */ syncAv?: boolean; } /** * @public * see: {@link NorskTransform.streamAlign} */ export declare class StreamAlignNode extends AutoProcessorMediaNode<"audio" | "video"> { } /** @public */ export interface StreamConditionSettings extends ProcessorNodeSettings { } /** @public */ export interface StreamConditionRequest { kind: 'in' | 'out' | 'idr_only' | 'intra_refresh'; pts?: Interval; /** * Wave length in frames for `kind: 'intra_refresh'`. Required for that kind, * ignored otherwise. Only honoured by encoders with a runtime intra-refresh * trigger (currently NVENC); other encoders ignore the request. */ frameCount?: number; } /** * @public * see: {@link NorskTransform.streamCondition} */ export declare class StreamConditionNode extends AutoProcessorMediaNode<"audio" | "video" | "ancillary"> { /** @public */ condition(request: StreamConditionRequest): void; } /** @public */ export interface Scte35MessageEvent extends Scte35SpliceInfoSection { pts: Interval; } /** @public */ export interface Scte35Message extends Scte35SpliceInfoSection { pts?: Interval; } /** @public */ export interface Smpte2038MessageEvent extends Smpte2038Message { pts: Interval; } /** @public */ export interface Smpte2038SendMessage extends Smpte2038Message { pts?: Interval; } /** @public */ export interface Smpte2038Message { cNotYChannelFlag: boolean; lineNumber: number; horizontalOffset: number; payloadFormat: VancPayloadFormat; ancillaryId: VancType2AncillaryId; userData: Uint8Array; } /** @public */ export type MetadataFormat = 'klv' | 'id3'; /** * @public * A metadata message as carried in a Transport Stream * */ export interface MetadataMessage { /** Raw metadata message data */ data: Uint8Array; /** Metadata service id (if present) */ serviceId: number; /** Format of the metadata (if known) */ format?: MetadataFormat; } /** @public */ export interface MetadataMessageEvent extends MetadataMessage { /** Timestamp of the message */ pts: Interval; } /** @public */ export interface MetadataSendMessage extends MetadataMessage { /** Timestamp of the message */ pts?: Interval; } /** * @public * Settings for an Ancillary node * see {@link NorskTransform.ancillary} */ export interface AncillarySettings extends ProcessorNodeSettings { onScte35?: (stream: StreamKey, message: Scte35MessageEvent) => void; onSmpte2038?: (stream: StreamKey, message: Smpte2038Message) => void; onMetadata?: (stream: StreamKey, message: MetadataMessageEvent) => void; /** * Called when a reference clock is available, i.e. a message with a time of "now" can be generated. * * This means data arriving on a video/audio stream the ancillary node is subscribed to - such a subscription is required * for "now" timestamps but not for explicitly specified timestamp values derived from input ancillary messages or other nodes. */ onReferenceClockAvailable?: () => void; } /** * @public * see: {@link NorskTransform.ancillary} */ export declare class AncillaryNode extends AutoProcessorMediaNode<"ancillary"> { /** Send a SCTE-35 message. * * The pts may be specified, in which case it should correspond to the same program * (e.g. obtained from a receieved SCTE-35 message or other timestamped message from that program), or it may be * omitted to send "now". If omitting the pts, the node must subscribe to an audio or video stream from the target * program in order to fix the latest timestamp to consider "now". */ sendScte35(key: StreamKey, info: Scte35Message): void; /** Send a metadata message (eg ID3 timed metadata, or KLV) * * The pts may be specified, in which case it should correspond to the same program * (e.g. obtained from a receieved message from that program), or it may be * omitted to send "now". If omitting the pts, the node must subscribe to an audio or video stream from the target * program in order to fix the latest timestamp to consider "now". */ sendMetadata(key: StreamKey, info: MetadataSendMessage): void; } /** * @public * Settings for a MetadataCombineNode, see {@link NorskTransform.metadataCombine} * */ export interface MetadataCombineSettings extends ProcessorNodeSettings { outputStreamKey: StreamKey; maxSyncDelta?: number; } /** * @public * see: {@link NorskTransform.metadataCombine} */ export declare class MetadataCombineMode extends AutoProcessorMediaNode<"ancillary"> { } /** * @public * Settings for an Opus encode * see: {@link NorskTransform.audioEncode} * */ export interface OpusSettings { kind: "opus"; } /** * @public * Settings for an AAC encode * see: {@link NorskTransform.audioEncode} */ export interface AacSettings { kind: "aac"; /** The output sample rate of this AAC encode */ sampleRate: SampleRate; /** The AAC profile of this AAC encode */ profile: AacProfile; /** * Bitrate mode: constant ("cbr") or one of FDK's variable-bitrate quality * levels ("vbr_1" lowest, "vbr_5" highest). Defaults to "cbr". */ bitrateMode?: AacBitrateMode; /** * Enable FDK's higher-quality second-pass encode. On by default; the CPU * cost is small. Set to false to disable. */ afterburner?: boolean; } /** * @public * Settings for an AC-3 (Dolby Digital) encode. Supports mono/stereo/surround/5.1 * at 32/44.1/48 kHz (channel layout and bitrate are on {@link AudioEncodeSettings}). * see: {@link NorskTransform.audioEncode} */ export interface Ac3Settings { kind: "ac3"; /** The output sample rate of this AC-3 encode (32000, 44100 or 48000) */ sampleRate: SampleRate; /** Encoder backend. Defaults to "ffmpeg". */ backend?: DolbyDigitalEncoderBackend; } /** * @public * Settings for an E-AC-3 (Dolby Digital Plus) encode. As AC-3, plus the * bitstream mode (bsmod). * see: {@link NorskTransform.audioEncode} */ export interface Eac3Settings { kind: "eac3"; /** The output sample rate of this E-AC-3 encode (32000, 44100 or 48000) */ sampleRate: SampleRate; /** Encoder backend. Defaults to "ffmpeg". */ backend?: DolbyDigitalEncoderBackend; /** * Bitstream mode (bsmod), per ETSI TS 102 366. * * Reserved: the ffmpeg backend does not expose bitstream mode and always * emits 0 (main/complete audio service), so this field is currently ignored. * It is retained for the future Dolby backend, which can set it. */ bsmod?: number; } /** * @public * Settings for an audio encode * see: {@link NorskTransform.audioEncode} * */ export interface AudioEncodeSettings extends ProcessorNodeSettings { /** * The channel layout of this encode * Note: If the channel layout doesn't match then it will be automatically converted * to gain greater control over this process, see {@link NorskTransform.audioMix} and {@link NorskTransform.audioMixMatrix} * */ channelLayout: ChannelLayout; /** The target bitrate of this encode */ bitrate: number; /** The name given to the rendition portion of the stream key assigned to this node's output */ outputRenditionName: string; /** What codec to (re) encode the audio to */ codec: OpusSettings | AacSettings | Ac3Settings | Eac3Settings; /** Latency in milliseconds for the audio gap filler. Higher values allow * better concealment of gaps/overlaps at the cost of added audio delay. * Defaults to 0 (no latency). */ audioLatencyMs?: number; } /** * @public * see: {@link NorskTransform.audioEncode} */ export declare class AudioEncodeNode extends AutoProcessorMediaNode<"audio"> { } /** * @public * The Dolby E program configuration (DP `prog_conf`): how the channels carried * by the frame are partitioned into independent programs (Dolby's "+"/"x" * shorthand). The audio fed to the encoder must carry the channels in the * order/count the chosen config expects. * see: {@link NorskTransform.dolbyEEncode} */ export type DolbyEProgramConfigName = "5.1+2" | "5.1+1+1" | "4+4" | "4+2+2" | "4+2+1+1" | "4+1+1+1+1" | "2+2+2+2" | "2+2+2+1+1" | "2+2+1+1+1+1" | "2+1+1+1+1+1+1" | "mono x8" | "5.1" | "4+2" | "4+1+1" | "2+2+2" | "2+2+1+1" | "2+1+1+1+1" | "mono x6" | "4" | "2+2" | "2+1+1" | "mono x4"; /** * @public * Settings for a Dolby E encode. * * Dolby E is video-frame-locked: subscribe BOTH an audio source (the PCM to * encode, on the "audio" pin) and a video source (timing only, on the "video" * pin) — the Dolby E frame rate is derived from the video stream. Use * {@link subscribeToPins} with {@link audioToPin}("audio") and * {@link videoToPin}("video"). * see: {@link NorskTransform.dolbyEEncode} */ export interface DolbyEEncodeSettings extends ProcessorNodeSettings { /** The name given to the rendition portion of the stream key assigned to this node's output */ outputRenditionName: string; /** How the channels are partitioned into Dolby E programs */ programConfig: DolbyEProgramConfigName; /** Dolby E word size. 20-bit is higher precision; 16-bit is the common interop choice. Defaults to 20. */ bitDepth?: 16 | 20; } /** * @public * see: {@link NorskTransform.dolbyEEncode} */ export declare class DolbyEEncodeNode extends AutoProcessorMediaNode<"audio" | "video"> { } /** * @public * Settings for an AudioDecode operation * see: {@link NorskTransform.audioDecode} * */ export interface AudioDecodeSettings extends ProcessorNodeSettings { } /** * @public * see: {@link NorskTransform.audioDecode} */ export declare class AudioDecodeNode extends AutoProcessorMediaNode<"audio"> { } /** * @public * A rectangle used for describing a subset of an image * */ export interface OffsetRect { /** The leftmost coordinate of the rect, where 0,0 is top left */ x: number; /** The topmost coordinate of the rect, where 0,0 is top left */ y: number; /** the width of this rectangle */ width: number; /** the height of this rectangle */ height: number; } export interface ComposePart { /** Input pin for this source */ pin: Pins; /** * Z-index to determine ordering by which the sources are overlaid * (higher layers appear on top) */ zIndex: number; /** * Opacity multiplier of this overlay (where 0.0 is fully transparent and 1.0 * is fully opaque) */ opacity: number; /** Optionally identify the part to enable transitions */ id?: string; /** * Optionally specify a transition for this part. A transition is applied only * if the part is specified in both the existing and the current/new * configuration, identified by having the same id specified, and a transition * is specified for the new configuration. */ transition?: PartTransition; /** * A callback that produces a compose operation, specifying in exact pixels * a) The source rect from the source video to select * b) The dest rect within the output video to render to */ compose: (partStream: VideoStreamMetadata, settings: VideoComposeSettings) => ComposeOperation; } /** * @public * The base OnlineLicense interface for the {@link NorskKantarEmbedder.kantarEmbedder} */ export interface KantarSnapOnlineLicenseBase { /** * The license type - must be "online" */ type: "online"; /** * Your login to the Kantar licensing server */ login: string; /** * The password corresponding to your login */ password: string; /** * The Kantar licensing server address. Defaults to "licenseofe.kantarmedia.com". For * testing, you likely want to use "licenseofe-integration.kantarmedia.fr". */ server?: string; /** * The port that the licensing server listens on. Defaults to 443. */ port?: number; } /** * @public * The base OfflineLicense interface for the {@link NorskKantarEmbedder.kantarEmbedder} */ export interface KantarSnapOfflineLicenseBase { /** * The license type - must be "offline" */ type: "offline"; /** * The path to your license file; this is from the context of the Norsk media container. */ kantarLicensePath: string; /** * The path to your audience license file; this is from the context of the Norsk media container. */ audienceLicensePath: string; } /** * @public * OnlineLicense definition for the {@link NorskKantarEmbedder.kantarEmbedder} */ export interface KantarSnapOnlineLicense extends KantarSnapOnlineLicenseBase { /** * The name of the license your wish to use */ licenseName: string; /** * A json string containing the name of the channel you wish to use, plus any other information * as required by Kantar. e.g.: * "\{\"channel_name\":\"channel1\"\}" */ jsonMetadata: string; } /** * @public * OfflineLicense definition for the {@link NorskKantarEmbedder.kantarEmbedder} */ export interface KantarSnapOfflineLicense extends KantarSnapOfflineLicenseBase { /** * The channel name you wish to use */ channelName: string; } /** * @public * Event raised by the Kantar Snap Embedder; see {@link NorskKantarEmbedder.kantarEmbedder} */ export interface KantarSnapSnapEvent { /** * The event severity */ eventType: "info" | "warning" | "error"; /** * The Kantar event code. Refer to Kantar documentation or support to intepret this number. */ code: number; /** * A human-readable description of the event */ message: string; } /** * @public * Information about a channel within a license */ export interface KantarSnapChannelInfo { channelName: string; channelId: bigint; } /** * @public * License information, as reported by the Kantar Snap Embedder; see {@link NorskKantarEmbedder.kantarEmbedder} */ export interface KantarSnapLicenseInformation { /** * The days remaining until this license must be refreshed. -1 indicates a perpetual license. */ remainingDays: number; /** * List of channels available with this license */ channelInfos: KantarSnapChannelInfo[]; } /** * @public * Online License information, as reported by the Kantar Snap Embedder; see {@link NorskKantarEmbedder.kantarEmbedder} */ export interface KantarSnapOnlineLicenseInformation { /** * The name of the license */ name: string; /** * Information about the license */ information: KantarSnapLicenseInformation; } /** * @public * Settings for an Kantar Audio Watermark Embedder node * see: {@link NorskKantarEmbedder.kantarEmbedder} * */ export interface KantarSnapSettings extends ProcessorNodeSettings { /** * The license settings */ license: KantarSnapOnlineLicense | KantarSnapOfflineLicense; /** * Event fired at startup, providing information about the current license */ onLicenseInformation?: (info: KantarSnapLicenseInformation) => void; /** * Event fired whenever the Kantar Snap Embedder raises an event */ onSnapEvent?: (event: KantarSnapSnapEvent) => void; /** * Event first whenever a timecode resync occurs */ onTimecodeResync?: () => void; } /** * @public * Kantar version information * */ export interface KantarVersion { /** * The version of the norsk-to-kantar integration library */ norskIntegrationVersion: string; /** * The version of the Kantar SDK */ kantarSdkVersion: string; } /** * @public * see: {@link NorskKantarEmbedder.kantarEmbedder} * */ export declare class KantarSnapNode extends AutoProcessorMediaNode<"audio"> { static queryOnlineLicense(settings: KantarSnapOnlineLicenseBase, client: MediaClient): Promise; static queryOfflineLicense(settings: KantarSnapOfflineLicenseBase, client: MediaClient): Promise; static queryVersion(client: MediaClient): Promise; static licenseInfoFromPB(licenseInfo: KantarSnapLicenseInformationPB): KantarSnapLicenseInformation; static assertJsonMetadata(input: string): void; /** @public * If the Kantar license needs updating, for example because it is due to expire, then call this method with the new license details. Norsk will perform the license update with no interruption to the audio stream. */ updateLicense(license: KantarSnapOnlineLicense | KantarSnapOfflineLicense): void; } export interface AbsoluteSourceTime { type: "absolute"; startTimeMs: bigint; } export interface UtcOffset { type: "offset"; offsetMs: bigint; } export type SpecifiedSourceTime = AbsoluteSourceTime | UtcOffset; /** * @public * Settings for a SourceTime node * see {@link NorskTransform.streamSync} * */ export interface SourceTimeSettings extends ProcessorNodeSettings { sourceTime?: SpecifiedSourceTime; explicitFrameRate?: FrameRate; } /** * @public * see: {@link NorskTransform.streamSync} */ export declare class SourceTimeNode extends AutoProcessorMediaNode<"audio" | "video"> { updateConfiguration(settings: SourceTimeSettings): void; static toSourceTime(sourceTime?: SpecifiedSourceTime): SourceTimeConfiguration["sourceTime"]; } /** * The return result of a compose callback, directing which pixels to place where */ export type ComposeOperation = { /** * The area within the source picture to include. This may be the full picture * or cropped, and will be rescaled if necessary. */ sourceRect: OffsetRect; /** * The area within the destination picture to place this part of the composition. */ destRect: OffsetRect; }; /** * Helpers for generating standard compose results */ export declare const VideoComposeDefaults: { /** * Takes the whole input part and renders it over the whole output video, scaling it as required to fit * and entirely ignoring aspect ratio in doing so */ fullscreen: () => (ComposePart["compose"]); fixed: ({ sourceRect, destRect, referenceResolution }: { sourceRect: OffsetRect; destRect: OffsetRect; referenceResolution: Resolution; }) => (ComposePart["compose"]); /** * Given a set of percentage based rects * a) Take the source part and crop using the source percentages specified * b) Render it onto the output video using the output percentages specified */ percentage: ({ sourceRect, destRect }: { sourceRect: OffsetRect; destRect: OffsetRect; }) => (ComposePart["compose"]); /** * Takes the whole input part and renders it scaled to fit the whole output video, letterboxed or pillarboxed if required * to maintain aspect ratio */ letterbox: () => (ComposePart["compose"]); }; /** @public * A transition for a video composition part. * * A transition interpolates the source_rect, dest_rect, and opacity properties * over the specified duration according to the specified easing function. * * As a special case, if a transition is specified and the input pin of the part * changes, an opacity fade from one to the other will occur. */ export interface PartTransition { /** Duration for the transition */ durationMs: number; /** * Easing function to apply to the transition. If not specified will be * linear. */ easing?: SimpleEasing; } /** * Settings for a VideoCompose node */ export interface VideoComposeSettings extends ProcessorNodeSettings> { /** * Required. Pin name of the reference stream. This is the video stream * which defines the output frame timing, which will typically be part of the * composition, e.g. the main picture in the case of a simple * overlay/picture-in-picture, or the top left quadrant of a 4-way split * screen. */ referenceStream: Pins; /** The parts (images/overlays) to include in the composition The functions provided here will be invoked when source contexts arrive so that pixel-based configuration can be generated see {@link VideoComposeDefaults} for helpers */ parts: readonly (ComposePart)[]; /** The resolution of the output video */ outputResolution: Resolution; /** * Output pixel format to use. If not specified, this will be chosen * automatically based on the sources present in the initial composition */ outputPixelFormat?: PixelFormat; /** * Behaviour in the case of a missing stream used in an active composition * part. Note that this does not apply to the reference stream, but to every * part which does not use the reference stream, whether at startup or on * context change. * * Missing means not present in the context or never having sent a frame. */ missingStreamBehaviour?: ComposeMissingStreamBehaviour; /** * Optionally attempt to perform the compose operation on hardware */ hardwareAcceleration?: ComposeHardwareAcceleration; /** * Called when the transitions specified in the last config update have * completed (in the case of multiple parts with specified transitions of * different duration, this means that the last remaining transitions have * completed */ onTransitionComplete?: () => void; /** * Maximum duration to hold any stream in the case that one or more are running behind. In the case the late * stream is delayed rather than having a large gap, this will result in discarded input frames. */ maxQueueMs?: number; /** * Extra options for influencing how the pipeline gets constructed and what algorithms get used for certain operations. * Silently ignored when the operation does not run on Quadra hardware. */ pipelineHints?: QuadraPipelineHints; /** * Build-time knobs for the Spectrum compose arms (`hardwareAcceleration: * "spectrum-sw"` or `"spectrum-nvidia"`). Silently ignored by the other * backends. Unset matches Spectrum's historic default behaviour. See * {@link SpectrumBuildOptions}. */ spectrumBuildOptions?: SpectrumBuildOptions; /** * How a STRUCTURAL composition update — a layer added or removed, or a * part's sourceRect appearing/disappearing — is applied on the Spectrum * arms, which rebuild their compiled pipeline for such changes. * Non-structural updates (geometry, opacity, transitions) always apply in * place regardless of this setting. Silently ignored by the other * backends. * * - `"glitch-free"` (the default): make-before-break — the previous * composition keeps rendering while the new pipeline is prepared, then * output cuts over. Output never pauses and no frames are dropped, but * the change lands a few frames late (or seconds late the first time a * never-before-seen structure is compiled on a box; compiled pipelines * are cached in memory and on disk, so that's a first-time-only cost). * - `"frame-accurate"`: break-before-make — output pauses at the update * point, input frames queue, and every queued frame is rendered with * the new composition once the pipeline is ready. Choose when the exact * frame the update applies at matters more than continuous output. */ structuralUpdateMode?: "glitch-free" | "frame-accurate"; } /** * @public * An update operation for a VideoCompose operation * see: {@link VideoComposeNode.updateConfig} * */ export interface VideoComposeSettingsUpdate { /** Update the parts (images/overlays) to include in the composition */ parts: readonly ComposePart[]; } /** * @public * see: {@link NorskTransform.videoCompose} */ export declare class VideoComposeNode extends ProcessorMediaNode { /** * @public * Updates the config used for a video compose operation * If transitions are specified, animations will be provided, otherwise * the change will be immediate * * Note: This is not a 'cheap' operation and care should be taken not to * do this too often (more than once a second for example!) */ updateConfig(settings: VideoComposeSettingsUpdate): void; doConfigUpdate(): void; } /** * @public * The settings for a single source within an AudioMix operation * see: {@link NorskTransform.audioMix} * */ export interface AudioMixSource { /** The name of the InputPin for this source */ pin: Pins; /** A vector of gains for this source, one for each channel */ channelGains?: readonly Gain[]; /** Optional transition to apply when changing gains */ transition?: PartTransition; } /** * @public * The settings for an AudioMix operation * see: {@link NorskTransform.audioMix} * */ export interface AudioMixSettings extends ProcessorNodeSettings> { /** The audio sources to mix */ sources: readonly AudioMixSource[]; /** The source name to use for the output stream */ outputSource: string; /** The channel layout that the mixer runs at * all audio streams will be normalised to this value and therefore * this will be the output channel layout of this node */ channelLayout: ChannelLayout; /** The sample rate that the mixer runs at * all audio streams will be normalised to this value and therefore * this will be the output sample rate of this node */ sampleRate?: SampleRate; } /** * @public * An update operation for an AudioMix node * see: {@link AudioMixNode.updateConfig} * */ export interface AudioMixSettingsUpdate { /** The audio sources to mix along with their potentially new gain values */ sources: readonly AudioMixSource[]; } /** * @public * see: {@link NorskTransform.audioMix} */ export declare class AudioMixNode extends ProcessorMediaNode { /** * @public * Updates the config of this AudioMix for all subsequent frames * this allows the user to change the levels and sources in the outgoing mix * dynamically as the stream progresses * @param settings - The updated settings */ updateConfig(settings: AudioMixSettingsUpdate): void; } /** * @public * A relative change in decibels, expressing a power ratio. * * A value of 0dB means no change, positive values mean an increase in power, and negative values mean a decrease in power. */ export type Gain = Db; /** * @public * Settings for the Audio Mix Matrix Node * see: {@link NorskTransform.audioMixMatrix} * */ export interface AudioMixMatrixSettings extends ProcessorNodeSettings { /** The NxM matrix of gains from N input channels to M output channels */ channelGains: readonly Gain[][]; /** The desired output channel layout, such as "5.1" */ outputChannelLayout: ChannelLayout; } /** * @public * Config update for the {@link AudioMixMatrixNode}. * Call {@link AudioMixMatrixNode.updateConfig} for updating the config. */ export interface AudioMixMatrixSettingsUpdate { /** The NxM updated matrix of gains from N input channels to M output channels */ channelGains: readonly Gain[][]; } /** * @public * see: {@link NorskTransform.audioMixMatrix} */ export declare class AudioMixMatrixNode extends AutoProcessorMediaNode<"audio"> { /** * @public * Updates the config of this AudioMixMatrix node for all subsequent frames * this allows the user to change the gains in the outgoing mix * dynamically as the stream progresses * @param settings - The updated settings */ updateConfig(settings: AudioMixMatrixSettingsUpdate): void; } /** * @public * An opaque handle to a node in an {@link AudioGraphBuilder}. The *only* way to * obtain one is to create a node, and every operation requires handles for its * inputs — so the graph you build is acyclic by construction: you cannot * reference a node that doesn't exist yet (no cycles), nor name one that was * never created (no dangling refs). Reuse a handle to fan it out. */ export type AudioNode = { readonly __audioGraphNode: unique symbol; }; /** * @public * Builds a spectrum-audio processing graph. Start from {@link AudioGraphBuilder.input} * (the single source); each operation takes input handle(s) + params and returns * a new handle. Operations are added one at a time as the library grows. */ export interface AudioGraphBuilder { /** The input audio stream — the graph's (first) source; `inputs[0]`. */ readonly input: AudioNode; /** * One handle per configured source, in {@link AudioGraphSettings.sources} * order (a single-input graph has exactly `[input]`). Feed them into any op — * `mix(inputs)` is the classic multi-source shape. */ readonly inputs: AudioNode[]; /** Apply a gain, in dB (0 = unity). */ gain(input: AudioNode, opts: { db: number; }): AudioNode; /** * An RBJ biquad filter (the full cookbook), built against the stream's rate. * `gainDb` applies to the shelf/peaking shapes. Runtime-retunable via * {@link AudioGraphNode.setParams} (`cutoffHz` / `q` / `db`) — the live EQ * tweak. */ biquad(input: AudioNode, opts: { kind: "lowPass" | "highPass" | "bandPass" | "notch" | "lowShelf" | "highShelf" | "peaking"; cutoffHz: number; q: number; gainDb?: number; }): AudioNode; /** * A multi-band parametric EQ: `bands` biquads applied in series as one node. * Each band's filter kind is fixed at build; its frequency/Q/gain are * runtime-tunable via {@link AudioGraphNode.setParams} `eqBands` (entry i * tunes band i). The number of bands is fixed at build. */ eq(input: AudioNode, opts: { bands: { kind: "lowPass" | "highPass" | "bandPass" | "notch" | "lowShelf" | "highShelf" | "peaking"; cutoffHz: number; q: number; gainDb?: number; }[]; name?: string; }): AudioNode; /** * TEST/AUDITION tool — deterministically punches timeline gaps into the * stream (drops `gapMs` of samples every `periodMs`, phased from the first * frame, so gap positions are identical on every run of the same content). * Feed a downstream {@link plc} node to audition concealment on real * material. `periodMs`/`gapMs` are runtime-updatable via setParams. When * named, emits `gap_injected_ms` on the measurement firehose as each gap * closes. Not for production graphs. */ gapInject(input: AudioNode, opts: { periodMs: number; gapMs: number; name?: string; }): AudioNode; /** * Packet-loss concealment: fills timeline gaps in the input with * synthesized audio so a dropout (a dropped SDI frame, a lost packet run) * is broadly inaudible up to ~40 ms and inoffensive beyond. * * `strategy` (default `"plc"`): signal-adaptive — tonal content continues * at its own pitch, noise-like content extends as shaped noise, both * attenuated to silence by ~100 ms. `"replicate"` is the legacy GapFiller * echo; `"silence"` fades out and back in (debug). * * Gaps longer than `maxGapMs` (default 500) are an outage: nothing is * manufactured — the (smaller) hole passes through and the audio fades * back in on return. `latencyMs` (default 0) holds audio back so the * silence strategy can fade out the pre-gap tail retrospectively, at the * cost of that much latency. * * When a `name` is given, concealment events (`concealed_ms`, `voiced`) * are emitted on the measurement firehose under that tap name. */ plc(input: AudioNode, opts?: { strategy?: "plc" | "replicate" | "silence"; maxGapMs?: number; latencyMs?: number; name?: string; }): AudioNode; /** A one-pole DC blocker (corner at `cutoffHz`, default 20 Hz). */ dcBlock(input: AudioNode, opts?: { cutoffHz?: number; }): AudioNode; /** Polarity inversion (× −1, all channels). */ polarity(input: AudioNode): AudioNode; /** * Manual L/R phase corrector — bring an out-of-phase left/right pair back * into phase. Two operator-driven controls (drive them live via `setParams` * while watching the correlation meter): * - `invertLeft` / `invertRight`: flip that channel's polarity (fixes the * ~180° fault where the pair cancels when summed to mono). * - `skewMs`: delay one channel to line the pair up in time — `> 0` delays * the right channel, `< 0` the left (whole-sample delay; latency = |skew|). * With `corrWindowMs > 0` the node emits a `correlation` reading of the * *corrected* output every window (0 = off) so the UI can show it trending to * +1. Only channels 0/1 (L/R) are affected; further channels pass through. */ lrPhaseCorrect(input: AudioNode, opts?: { invertLeft?: boolean; invertRight?: boolean; skewMs?: number; corrWindowMs?: number; name?: string; }): AudioNode; /** Select one channel of the input as a mono stream (0-based channel index). */ channelSelect(input: AudioNode, opts: { channel: number; }): AudioNode; /** Merge N mono inputs into one stream (its layout = the number of inputs). */ /** Concatenate the inputs' channels into one stream (input k's channels * become the next block of output channels). N mono inputs -> an N-channel * stream; two stereos -> 4 channels. */ channelConcat(inputs: AudioNode[]): AudioNode; /** Force a stream to exactly `target` channels: pad short inputs with * silence, truncate wide ones. The crash-safe front of a fixed-channel-count * graph (e.g. a fan-out configured for 16 channels). */ channelPad(input: AudioNode, opts: { target: number; }): AudioNode; /** * Convenience: split a `channels`-wide input into that many mono streams (one * `channelSelect` per channel). Returns the handles in channel order. The wire * graph is identical to writing the selects by hand — the source runs once and * each select extracts only its own channel. */ split(input: AudioNode, channels: number): AudioNode[]; /** * A windowed RMS level tap: the audio passes through unchanged (the returned * handle carries it) and per window it emits a per-channel `rms_db` * measurement. `name` identifies the tap in the {@link AudioGraphSettings.onMeasurement} * callback; `windowMs` is the measurement window. */ rms(input: AudioNode, opts: { name: string; windowMs: number; }): AudioNode; /** * An EBU R128 loudness tap (audio passes through): emits whole-stream * momentary/shortterm/integrated LUFS + LRA + true-peak per window. Reference * it from an output's `measurements` to pin its readings into that output's * qualityMetrics (for downstream switchers), and/or read it via * {@link AudioGraphSettings.onMeasurement}. */ loudness(input: AudioNode, opts: { name: string; windowMs: number; }): AudioNode; /** * A per-channel gain, in dB (one entry per channel, in channel order; a * channel beyond the list stays at unity). Unlike a diagonal `matrixMix`, * each channel can be faded independently at runtime (`setParams` with * `gainsDb`). */ channelGain(input: AudioNode, opts: { gainsDb: number[]; }): AudioNode; /** * Mix N inputs into one stream. The output's layout and rate are the FIRST * input's (other inputs are resampled to its rate; a layout mismatch is a * build error — align layouts first with `matrixMix` / channel ops). * `weights` are linear, one per input; omitted = unity for every input. * Weights are runtime-tunable (`setParams` with `weights`, ramped). */ mix(inputs: AudioNode[], opts?: { weights?: number[]; }): AudioNode; /** * Up/down-mix by a linear-gain matrix: `matrix[out][in]` — rows are output * channels (the output layout is the row count), columns input channels. */ matrixMix(input: AudioNode, opts: { matrix: number[][]; }): AudioNode; /** Sample-rate convert to `rate` Hz (layout preserved). */ resample(input: AudioNode, opts: { rate: number; }): AudioNode; /** * A feed-forward dynamic range compressor (linked channels — one gain across * all channels, so the image doesn't shift; log-domain soft knee; branching * attack/release smoothing; makeup gain). All parameters are runtime-tunable * via {@link AudioGraphNode.setParams}; `makeupDb` honours a transition. * Defaults: −20 dBFS threshold, 3:1, 6 dB knee, 5 ms attack, 50 ms release. */ compressor(input: AudioNode, opts?: { thresholdDb?: number; ratio?: number; kneeDb?: number; attackMs?: number; releaseMs?: number; makeupDb?: number; /** Opt-in gain-reduction metering cadence (ms): emits `gain_reduction_db` * measurements as tap `name` for GR meters. Omitted = no events. */ meterMs?: number; name?: string; /** false = independent per-channel detection/gain (discrete * multichannel feeds). Default true: one gain across all channels, so * the stereo/surround image never shifts. */ linked?: boolean; /** "peak" (default, snappy) or "rms" (a mean-square average over * `rmsMs` — smoother, more "musical"). Runtime-tunable via setParams. */ detector?: "peak" | "rms"; /** RMS averaging window (ms) when `detector: "rms"`. Default 10. */ rmsMs?: number; /** Program-dependent (auto) release: fast on isolated transients, slow * on sustained reduction. `releaseMs` sets the fast end. Runtime-tunable. */ autoRelease?: boolean; /** Sidechain high-pass on the DETECTOR (Hz; 0/omit = off). Low (~80 Hz) * stops bass pumping the compressor; high (~5-6 kHz) makes it a de-esser. * The gain still lands on the full signal. Runtime-tunable. */ sidechainHpHz?: number; /** Auto makeup-gain: derive the makeup from threshold/ratio (tracks live * changes) instead of `makeupDb`. Runtime-tunable (`autoMakeup`). */ autoMakeup?: boolean; /** External-key (sidechain) ducking: route the detector to this KEY node * instead of `input` — the classic "music ducks under voice" (main = * music, key = voice). The gain still lands on `input`; an external key * forces linked detection (the key and main channel counts may differ). * Omit for the normal self-keyed compressor. */ key?: AudioNode; }): AudioNode; /** * A brick-wall look-ahead limiter (linked channels): the gain attacks ahead * of a transient (content is delayed by `lookaheadMs`, keeping its PTS; the * delay is reported as node latency) and a final clamp makes the ceiling * absolute. `lookaheadMs` is fixed at build; the rest are runtime params. * With `truePeak` the detector is 4× oversampled inter-sample peaks * (BS.1770), so `ceilingDb` can be a true-peak (dBTP) limit directly; * without it the detector is sample-peak — leave ~1 dB inter-sample margin * on the ceiling. Defaults: −1 dBFS ceiling, 2 ms look-ahead, 1 ms attack, * 50 ms release, sample-peak. */ limiter(input: AudioNode, opts?: { ceilingDb?: number; lookaheadMs?: number; attackMs?: number; releaseMs?: number; truePeak?: boolean; /** Opt-in gain-reduction metering cadence (ms): emits `gain_reduction_db` * + `clamped` (brick-wall hits) as tap `name`. Omitted = no events. */ meterMs?: number; name?: string; /** false = independent per-channel limiting. Default true (linked). */ linked?: boolean; /** Input drive (dB): a pre-gain into the limiter — pushes harder against * the ceiling (louder, more limiting; the ceiling stays absolute). * Runtime-tunable (`driveDb`). */ driveDb?: number; }): AudioNode; /** * A loudness-driven automatic volume control: steers BS.1770 short-term * loudness toward `targetLufs` with slew-limited gain (`upDbPerS` / * `downDbPerS`) inside `[minGainDb, maxGainDb]`; adaptation freezes while * momentary loudness is below `gateLufs`, so silence is never pumped. Also a * measurement tap: emits `agc` readings (`gain_db`, `shortterm_lufs`) every * 100 ms — give it a `name` to receive them via * {@link AudioGraphSettings.onMeasurement}. All numeric fields are runtime * params. Defaults: −23 LUFS (EBU R128), ±18 dB, 3 dB/s up, 12 dB/s down, * gate −45 LUFS. */ agc(input: AudioNode, opts?: { name?: string; targetLufs?: number; minGainDb?: number; maxGainDb?: number; upDbPerS?: number; downDbPerS?: number; gateLufs?: number; }): AudioNode; /** * A windowed silence-detection tap (audio passes through): per window emits * `silent` (0/1) + `rms_db`, flagged when the loudest channel is below * `thresholdDb` (default −60 dBFS). */ silenceDetect(input: AudioNode, opts: { name: string; windowMs: number; thresholdDb?: number; }): AudioNode; /** * A windowed clipping tap: per window emits `clip_ratio`, the fraction of * samples at/above `threshold` of full scale (default 0.99). */ clip(input: AudioNode, opts: { name: string; windowMs: number; threshold?: number; }): AudioNode; /** A windowed DC-offset tap: per window emits the largest per-channel mean. */ dcOffset(input: AudioNode, opts: { name: string; windowMs: number; }): AudioNode; /** A windowed inter-channel correlation tap (stereo phase, −1..1). */ correlation(input: AudioNode, opts: { name: string; windowMs: number; }): AudioNode; /** * A windowed dead-channel tap: flags a channel below `floorDb` (default −70) * while another channel is above it — the lost-leg case whole-stream silence * detection misses. */ deadChannel(input: AudioNode, opts: { name: string; windowMs: number; floorDb?: number; }): AudioNode; /** * A windowed FFT tap: per window emits `spectral_flatness` / `peak_ratio` / * `peak_freq` / `hum_energy` (the tone / static-noise / mains-hum substrate). * `windowMs` is converted to the FFT size in frames. */ spectral(input: AudioNode, opts: { name: string; windowMs: number; }): AudioNode; /** * The channel-strip meter tap (audio passes through): per channel per window * it emits `rms_db` (the bar), `peak_db` (the floating peak line) and * `peak_hold_db` (max window peak over the last `holdMs`, default 1500 ms); * with `truePeak`, also per-channel `true_peak_db` (BS.1770 4× inter-sample * peaks). 10–50 ms windows drive a responsive console meter. */ meter(input: AudioNode, opts: { name: string; windowMs: number; holdMs?: number; truePeak?: boolean; }): AudioNode; /** * The RTA (spectrum analyser) tap: per window, `bands` log-spaced band * magnitudes (dB, 20 Hz→Nyquist; default 31, max 64) as `band_0..band_{N−1}` * readings plus a `bands` count. A tone reads ≈ its programme level in its * band. `windowMs` is the FFT length. */ spectrum(input: AudioNode, opts: { name: string; windowMs: number; bands?: number; }): AudioNode; /** * The waveform-timeline tap (audio passes through): per channel per window * it emits signed linear `min`/`max` sample values — the scrolling-waveform * feed. 1–10 ms windows give DAW-zoom resolution at trivial bandwidth * (measurements are batched per processed frame on the wire). */ envelope(input: AudioNode, opts: { name: string; windowMs: number; }): AudioNode; /** * The stereo-image (goniometer / Lissajous) feed: per window the measurement * carries `data` — decimated L/R sample pairs packed as interleaved i16 LE. * Copy before viewing (the bytes view may be unaligned): * `const b = data.slice(); new Int16Array(b.buffer, 0, b.length / 2)`. * Also carries a `pairs` count. Defaults (33 ms window, ÷8 decimation) * ≈ 190 kbit/s. */ goniometer(input: AudioNode, opts: { name: string; windowMs?: number; decimate?: number; }): AudioNode; /** * A local audio-out MONITOR sink: play this point of the graph on a local * output device (operator monitoring, "listen in at any point"). A tap — it * passes audio through, nothing downstream. `device` is an output device * name from hardware info's `audioDevices` (omit/"" = default). Both the * device and `enabled` are runtime-tunable via * {@link AudioGraphNode.setParams} (`device` / `enabled`), so you can start/ * stop and re-point monitoring live without rebuilding the graph. Returns the * node so you can target it with setParams. */ monitor(input: AudioNode, opts?: { device?: string; enabled?: boolean; volume?: number; }): AudioNode; /** * A click-free hard MUTE. Ramps between unity and silence over `rampMs` * (default 15 ms) so toggling never clicks. `muted` is runtime-tunable via * {@link AudioGraphNode.setParams} (`muted`), so it toggles live. */ mute(input: AudioNode, opts?: { muted?: boolean; rampMs?: number; }): AudioNode; /** * An EBU R128 compliance chain (−23 LUFS programme, ≤ −1 dBTP): an `agc` * steering short-term loudness to −23, an optional compressor for range * control, and a brick-wall true-peak `limiter` with its ceiling at the * standard's −1 dBTP. A `loudness` tap on the chain's output (named `name`, * default "ebuR128") is returned alongside the output node: pin it into your * output's qualityMetrics (`measurements: [chain.loudness]`) and/or read it * via {@link AudioGraphSettings.onMeasurement} for compliance metering; the * agc's own gain readings arrive as tap `".agc"`. */ ebuR128Chain(input: AudioNode, opts?: { name?: string; compressor?: { thresholdDb?: number; ratio?: number; kneeDb?: number; attackMs?: number; releaseMs?: number; }; }): { node: AudioNode; loudness: AudioNode; }; /** * An ATSC A/85 (CALM Act) compliance chain (−24 LKFS programme, ≤ −2 dBTP): * as {@link AudioGraphBuilder.ebuR128Chain} with the US broadcast targets — * agc to −24 LUFS and the true-peak limiter ceiling at −2 dBTP. Default tap * name "calm". */ calmChain(input: AudioNode, opts?: { name?: string; compressor?: { thresholdDb?: number; ratio?: number; kneeDb?: number; attackMs?: number; releaseMs?: number; }; }): { node: AudioNode; loudness: AudioNode; }; } /** * @public * Settings for the {@link NorskTransform.audioGraph} node. */ /** * @public * A measurement emitted by an analysis tap in an {@link NorskTransform.audioGraph} * graph, delivered to {@link AudioGraphSettings.onMeasurement}. */ export interface AudioGraphMeasurement { /** The tap's name (as given to the op that produced it). */ tap: string; /** The metric family, e.g. "rms". */ source: string; /** The channel this reading is for, or undefined for a whole-stream reading. */ channel?: number; /** The named readings, e.g. `{ rms_db: -23.1 }`. */ values: Record; /** The media PTS the reading was taken at, as a rational (seconds). Lets a * consumer correlate a reading with a point in the stream / compute rates. */ pts: Interval; /** Packed binary payload for sample-feed taps (the goniometer's interleaved * i16 LE L/R pairs); undefined for scalar measurements. */ data?: Uint8Array; } /** * @public * One entry in a multi-output {@link AudioGraphSettings.build}: either a bare node * handle, or a handle plus the tap handles whose latest readings pin into that * output's per-frame qualityMetrics. */ export type AudioGraphOutputSpec = AudioNode | { node: AudioNode; measurements?: AudioNode[]; }; export interface AudioGraphSettings extends ProcessorNodeSettings> { /** * Multi-source mode: named input pins, one per graph source, in wire-source * order — `inputs[k]` in the builder is the stream subscribed to pin * `sources[k]` (via {@link AudioGraphNode.subscribeToPins} with * {@link audioToPin}). Omit for a single-input graph (plain `subscribe`). * Sources are co-timed by sample count from each one's first frame — start * them together (no PTS-based sync yet). */ sources?: Pins[]; /** * Build the processing graph and declare its output(s). Return a single node * for one output (which inherits the source's stream key), or a record of * `renditionName → output` for multiple independently-subscribable outputs — * each emits a stream whose key carries that renditionName, so downstream * subscribes to a specific one by rendition. Outputs may have different channel * layouts, and each may pin analysis-tap readings into its qualityMetrics (the * `{ node, measurements }` form). */ build: (graph: AudioGraphBuilder) => AudioNode | Record; /** Called for every measurement an analysis tap (e.g. `rms`) emits. */ onMeasurement?: (measurement: AudioGraphMeasurement) => void; /** * Called with every runtime parameter update as the server applies it (the * param echo) — relay these to your own UI clients to keep a multi-operator * surface in sync without tracking state yourself. `nodeIndex` matches the * wire indices `getGraph()` reports. */ onParamsApplied?: (update: { nodeIndex: number; params: Record; transitionMs?: number; }) => void; } /** * @public * A runtime parameter update for {@link AudioGraphNode.setParams}. Fields are * op-friendly (mapped to the engine's parameter names internally); only those * the target node supports take effect. Grows as ops gain runtime parameters. */ export interface AudioGraphParamsUpdate { /** New gain in dB — for a `gain` node. */ db?: number; /** New per-channel gains in dB — for a `channelGain` node (entry i tunes channel i). */ gainsDb?: number[]; /** New corner/centre frequency in Hz — for a `biquad` node (live retune). */ cutoffHz?: number; /** New filter Q — for a `biquad` node. */ q?: number; /** Per-band tuning — for an `eq` node (entry i tunes band i). */ eqBands?: { cutoffHz?: number; q?: number; gainDb?: number; }[]; /** New gap length in ms — for a `gapInject` audition node. */ gapMs?: number; /** New gap period in ms — for a `gapInject` audition node. */ periodMs?: number; /** New linear input weights — for a `mix` node (entry i tunes input i). */ weights?: number[]; /** Output device name — for a `monitor` node (empty = default device). */ device?: string; /** Enable/disable playback — for a `monitor` node. */ enabled?: boolean; /** Mute / unmute — for a `mute` node (ramped, click-free). */ muted?: boolean; /** Output level (linear, 1 = unity) — for a `monitor` node. */ volume?: number; /** Detector mode — for a `compressor` node ("peak" | "rms"). */ detector?: "peak" | "rms"; /** RMS averaging window in ms — for a `compressor` node. */ rmsMs?: number; /** Program-dependent (auto) release on/off — for a `compressor` node. */ autoRelease?: boolean; /** Sidechain high-pass on the detector (Hz; 0 = off) — for a `compressor` node. */ sidechainHpHz?: number; /** Auto makeup-gain on/off — for a `compressor` node. */ autoMakeup?: boolean; /** Input drive in dB — for a `limiter` node. */ driveDb?: number; /** New threshold in dBFS — for a `compressor` node. */ thresholdDb?: number; /** New ratio — for a `compressor` node. */ ratio?: number; /** New knee width in dB — for a `compressor` node. */ kneeDb?: number; /** New attack time in ms — for a `compressor` / `limiter` node. */ attackMs?: number; /** New release time in ms — for a `compressor` / `limiter` node. */ releaseMs?: number; /** New makeup gain in dB — for a `compressor` node (honours `transition`). */ makeupDb?: number; /** New ceiling in dBFS — for a `limiter` node. */ ceilingDb?: number; /** New target loudness in LUFS — for an `agc` node. */ targetLufs?: number; /** New minimum gain in dB — for an `agc` node. */ minGainDb?: number; /** New maximum gain in dB — for an `agc` node. */ maxGainDb?: number; /** New upward slew rate in dB/s — for an `agc` node. */ upDbPerS?: number; /** New downward slew rate in dB/s — for an `agc` node. */ downDbPerS?: number; /** New adaptation gate in LUFS — for an `agc` node. */ gateLufs?: number; /** Restart the integrated-loudness measurement — for a `loudness` tap (the * "start metering at the top of the programme" control). */ resetIntegrated?: boolean; /** Flip the left channel's polarity — for an `lrPhaseCorrect` node. */ invertLeft?: boolean; /** Flip the right channel's polarity — for an `lrPhaseCorrect` node. */ invertRight?: boolean; /** New inter-channel skew in ms (> 0 delays right, < 0 left) — for an * `lrPhaseCorrect` node. */ skewMs?: number; /** Bypass this node — it passes its input straight through with no * processing (a live, click-free effect bypass for any 1-in/1-out op: * compressor, EQ, limiter, AGC, gain, gap-conceal). No graph rebuild. */ bypass?: boolean; /** Optional ramp so the change is click-free. */ transition?: PartTransition; } export declare function decodeMeasurement(m: { node: number; source: string; channel: number; pts?: Parameters[0]; values: AudioGraphParam[]; data: Uint8Array; }, tapNames: Map): AudioGraphMeasurement; /** * @public * see: {@link NorskTransform.audioGraph} */ export declare class AudioGraphNode extends AutoProcessorMediaNode { /** * @public * Apply a runtime parameter update to a node in the graph, addressed by the * handle returned when it was built (hoist it out of the `build` closure to * keep a reference). An optional {@link PartTransition} ramps the change so it * is click-free. Only parameters the target op supports take effect (a `gain` * node reads `db`). * * @example * ```ts * let vol: AudioNode; * const graph = await norsk.processor.transform.audioGraph({ * build: (g) => (vol = g.gain(g.input, { db: -6 })), * }); * graph.setParams(vol, { db: -3, transition: { durationMs: 200 } }); * ``` */ setParams(node: AudioNode, update: AudioGraphParamsUpdate): void; /** * @public * The graph's shape + last-applied runtime params, as the server holds them — * the discovery surface for a UI that didn't build the graph itself (a * reconnecting or second client). `config.nodes` are the wire ops in index * order (sources occupy indices 0..N−1), `appliedParams` the most recent * setParams per node. */ getGraph(): Promise; } /** * @public * Settings for an Audio Gain node * see: {@link NorskTransform.audioGain} * */ export interface AudioGainSettings extends ProcessorNodeSettings { /** A vector of gains for this source, one for each channel */ channelGains: readonly Gain[]; /** Input changed callback, allowing the opportunity to update config (eg on channel count changing) */ onInputChanged?: (metadata?: StreamMetadata) => (Gain[] | undefined | void); } /** * @public * An update operation for an Audio Gain node * see: {@link AudioGainNode.updateConfig} * */ export interface AudioGainSettingsUpdate { /** A vector of gains for this source, one for each channel */ channelGains?: readonly Gain[]; /** Optional transition to apply when changing gains */ transition?: PartTransition; } /** * @public * see: {@link NorskTransform.audioGain} */ export declare class AudioGainNode extends AutoProcessorMediaNode<"audio"> { /** * @public * Updates the config of this AudioGain node for all subsequent frames * this allows the user to change the gains in the outgoing stream * dynamically as the stream progresses * @param settings - The updated settings */ updateConfig(settings: AudioGainSettingsUpdate): void; } /** * @public * Settings for an SeiInjectionNode. * see: {@link NorskTransform.seiInjection} */ export interface SeiInjectionSettings extends ProcessorNodeSettings { /** Inject timecode SEI messages, using the source-time if available, otherwise using the system time. Defaults to false. */ outputTimecode?: boolean; /** Inject SVTA MQA quality metrics SEI from frame metadata. Defaults to false. */ outputQualityMetrics?: boolean; /** Forward original SEI messages from the input stream. Defaults to false. */ passthroughSei?: boolean; /** Optional MQA quality-metric aggregation weights. When omitted, server defaults are used. */ mqaConfig?: MqaConfig; /** * Never resample or re-encode: accept H.264/H.265 at native frame rate and * bitrate (bit-exact apart from the injected SEI). When false (the legacy * default) non-matching input is converted to H.264/25fps/1Mbps. */ passthrough?: boolean; } /** * @public * Runtime-updatable SeiInjection fields. * see {@link SeiInjectionNode.updateConfig} */ export interface SeiInjectionDynamicConfig { /** * Toggle the MQA quality-metrics SEI write on a live workflow (e.g. a * downstream device chokes on the SEI mid-event — turn it off without a * restart). */ outputQualityMetrics: boolean; } /** * @public * see: {@link NorskTransform.seiInjection} */ export declare class SeiInjectionNode extends AutoProcessorMediaNode<"video"> { /** * Dynamically update the node while it is running (the MQA-write toggle). */ updateConfig(config: SeiInjectionDynamicConfig): void; } /** * @public * Settings for an HlgToSdrNode * see: {@link NorskTransform.hlgToSdr} * */ export interface HlgToSdrSettings extends ProcessorNodeSettings { } /** * @public * see: {@link NorskTransform.hlgToSdr}. */ export declare class HlgToSdrNode extends AutoProcessorMediaNode<"video"> { } /** * @public * Settings for a BrowserRenderNode * see: {@link NorskTransform.browserRender} */ export interface BrowserRenderSettings extends ProcessorNodeSettings { /** The CEF settings to use for this browser render instance */ appConfig?: BrowserAppSettings; /** The URL to load in the browser session */ url: string; /** The resolution of the browser window (and therefore the output browser frames) */ resolution: { width: number; height: number; }; /** The frame rate for the browser output */ frameRate: { frames: number; seconds: number; }; /** Maximum number of input frames to queue while waiting for browser renders. * When exceeded, the oldest queued frame is dropped. Default: 2. */ maxQueueDepth?: number; /** How to handle input frames arriving before the CEF browser is ready * (i.e. before the first successful paint). CEF takes a moment to load * the page and produce its first frame. * - "bufferUntilReady" (default): Queue input frames without bound until * the browser is ready. Once ready, maxQueueDepth is enforced. Good * for file inputs where every frame must be preserved. * - "passthroughUntilReady": Emit input frames on the original pin * immediately with no corresponding browser frame. Good for live * inputs where startup latency matters more than having a browser * overlay for the first fraction of a second. */ startupBehaviour?: "bufferUntilReady" | "passthroughUntilReady"; /** The source name for the browser output stream key */ browserSourceName: string; } /** * @public * A processor that takes video frames as input and produces two outputs: * the original input frames passed through, and browser-rendered frames * synchronized to each input frame's metadata. * * The HTML page receives frame metadata via a 'norsk-frame' CustomEvent * and must call window.cefQuery(\{request: 'ready'\}) when the DOM update * is complete. A 'norsk-context' event is dispatched on context changes. * * see: {@link NorskTransform.browserRender} */ export declare class BrowserRenderNode extends AutoProcessorMediaNode<"video"> { } /** * @public * Settings for an LutProcessorNode * see: {@link NorskTransform.lutProcessor} * */ export interface LutProcessorSettings extends ProcessorNodeSettings { lutCubeFilename: string; } /** * @public * see: {@link NorskTransform.lutProcessor}. */ export declare class LutProcessorNode extends AutoProcessorMediaNode<"video"> { } /** * @public * One Spectrum output: a named expression tree plus an optional output * pixel format. The name is mandatory and unique within a Spectrum node; * it is used as both the OutputExpression name passed to the engine and * the per-output rendition name observed downstream. */ export interface SpectrumOutputSpec { /** Unique name for this output (also used as its rendition name). */ name: string; /** The Spectrum expression tree describing this output's pipeline. */ expression: SpectrumExpression; /** * Output pixel format. If not specified, defaults to the source pixel * format. Useful for ensuring the output is in a format suitable for * downstream encoding (e.g. "yuv420p" for H.264/H.265). */ outputPixelFormat?: PixelFormat; /** * Desired output colourimetry. The pipeline auto-injects whatever * conversions are needed (TransferFunction, GamutMap, range conversion) * to reach these from the kernel-natural upstream — for example, a * `toneMap` chain followed by `outputTransfer: "bt709"` will deliver an * SDR BT.709-encoded stream rather than linear-light. Omit any field to * mirror the kernel's natural output for that aspect. */ outputPrimaries?: ColorPrimaries; outputTransfer?: TransferFunction; outputRange?: VideoRange; } /** * @public * Settings for a Spectrum video processor node * see: {@link NorskTransform.spectrum} * */ /** * @public * Accuracy-vs-speed preference for Spectrum's integer fast paths. * * - `"accurate"` (default): int32/Q14 fixed-point fast paths, sub-LSB error * vs the reference — numerically/visually indistinguishable, and faster. * - `"fast"`: looser int16 fast paths with a few LSB drift on the 8-bit * output (up to ~5 LSB on chroma). Faster per-CPU-cycle on BT.709 YUV↔RGB * UINT8 chains. * - `"reference"`: skip the integer fast paths entirely — float reference * math, stable across releases. For golden / pixel-fingerprint workflows. */ export type SpectrumPrecisionPreference = "accurate" | "fast" | "reference"; /** * @public * Colour domain in which Spectrum's compose / resize / spatial ops operate. * Orthogonal to {@link SpectrumPrecisionPreference}: working space chooses * *which* (both-valid) result is computed (visible on translucent pixels), * precision chooses how exactly. * * - `"auto"` (default): resolve per content — SDR display-encoded content * operates in its encoded domain (the structural fast path that avoids the * colour round-trip); HDR / scene-linear content uses linear light. * - `"linearLight"`: always linearise, operate on light, re-encode. * Photometric; required for HDR; safest for heavy translucency. * - `"displayEncoded"`: always operate in the encoded reference transfer. * SDR graphics convention; cheapest. Wrong for HDR translucency. */ export type SpectrumWorkingSpace = "auto" | "linearLight" | "displayEncoded"; /** * @public * Per-Spectrum-pipeline build-time knobs. All fields are optional; an * unset `SpectrumBuildOptions` matches Spectrum's historic default * behaviour exactly. */ export interface SpectrumBuildOptions { /** * Accuracy-vs-speed preference. Defaults to `"accurate"`. * See {@link SpectrumPrecisionPreference}. */ precision?: SpectrumPrecisionPreference; /** * Colour domain for compose / resize / spatial ops. Defaults to `"auto"`. * See {@link SpectrumWorkingSpace}. */ workingSpace?: SpectrumWorkingSpace; /** * Max threads the pipeline may use at runtime. * * - `0` (default): emit `parallel(yo)` directives; runtime uses all * available cores. Lowest per-frame latency; binds more CPU per * pipeline. * - `1`: single-thread schedule — skip parallel directives entirely. * The kernel runs end-to-end on the calling thread with zero * Halide worker-pool / queue / sync overhead. Use for workflows * that comfortably sustain their target frame rate on one core, * and where CPU cost per pipeline matters more than per-call * latency (e.g. many concurrent low-load streams on one host). * - `>= 2`: cap. Currently treated as auto for emission; a runtime * thread-pool cap is a follow-up. * * IMPORTANT: `maxThreads: 1` is fundamentally different from binding * the process to one CPU via `taskset` / `cpuset`. Pinning still * causes parallel directives to execute — workers spawn, queue and * sync overhead happens, all forced to time-share one core. That can * be 10-25× slower than the actual kernel. `maxThreads: 1` makes the * SCHEDULE itself serial so the runtime doesn't engage at all. */ maxThreads?: number; } export interface SpectrumSettings extends ProcessorNodeSettings { /** * Non-empty list of outputs. One frame stream is produced per entry, * sharing a single internal expression DAG so common subtrees (sources, * resizes, tone maps, …) are evaluated once. */ outputs: SpectrumOutputSpec[]; /** * Optional build-time knobs. See {@link SpectrumBuildOptions}. */ buildOptions?: SpectrumBuildOptions; /** * When set, the spectrum processor runs its GPU-mode pipeline regardless * of whether the input frame is host (InMemory) or an NVIDIA surface, and * emits nvidia-output frames. Useful when the downstream consumer (e.g. * an `nv-h264` encoder) expects a GPU surface and you want to avoid the * host→GPU bounce that would otherwise happen via a separate * payload-to-surface step. * * Default: `false` (host-in/host-out or gpu-in/gpu-out, inferred from * the input). */ nvidiaOutput?: boolean; } /** * @public * Spectrum video processor - applies an expression-based processing pipeline to video. * Supports resize, crop, compose, color grading, tone mapping, LUT, transfer function, * and gamut mapping operations. * see: {@link NorskTransform.spectrum} */ export declare class SpectrumNode extends ProcessorMediaNode { /** * Update dynamic parameters on the running Spectrum pipeline without recompilation. * Keys use dot-notation paths (e.g. "colorGrade.saturation", "toneMap.exposure"). * @param params - Key-value pairs of parameter paths to new values */ updateDynamicParams(params: Record): Promise; } /** Result from Spectrum input inference analysis */ export interface SpectrumInputInferenceResult { colorPrimaries: ColorPrimaries; transferFunction: TransferFunction; videoRange: VideoRange; overallConfidence: number; primariesConfidence: number; transferConfidence: number; rangeConfidence: number; peakBrightness: number; effectiveBitDepth: number; gamutUtilization: number; dynamicRange: number; detectedFormat: string; } /** * @public * Settings for a SpectrumInputInference node. * Analyzes video input to detect colour primaries, transfer function, * video range, and other metadata with confidence scoring. */ export interface SpectrumInputInferenceSettings extends ProcessorNodeSettings { /** Called each time inference completes on a sampled frame */ onData: (result: SpectrumInputInferenceResult) => void; /** Run inference every N frames (default 30) */ sampleEveryNFrames?: number; /** Expected bit depth of input (default 10) */ nominalBitDepth?: number; } /** * @public * Spectrum input inference node — subscribes to a video stream, samples frames, * and streams auto-detection results (colour primaries, transfer function, etc.). * see: {@link NorskControl.spectrumInputInference} */ export declare class SpectrumInputInferenceNode extends AutoProcessorMediaNode<"video"> { } /** * @public * Settings for an Audio Split Multichannel node * see: {@link NorskTransform.audioSplitMultichannel} * */ export interface AudioSplitMultichannelSettings extends ProcessorNodeSettings { /** * The output stream key of the first channel * subsequent channels will have streamId incremented by N */ outputStreamKey: StreamKey; metrics?: "enabled" | "minimal" | "none"; } /** * @public * see: {@link NorskTransform.audioSplitMultichannel} */ export declare class AudioSplitMultichannelNode extends AutoProcessorMediaNode<"audio"> { } /** * @public * Settings for an Audio Build Multichannel Node * see: {@link NorskTransform.audioBuildMultichannel} * */ export interface AudioBuildMultichannelSettings extends ProcessorNodeSettings { /** The channel layout of the built outgoing stream */ channelLayout: ChannelLayout; /** The sample rate of the built outgoing stream */ sampleRate: SampleRate; /** The sample format of the built outgoing stream (Defaults to FLTP)*/ sampleFormat?: SampleFormat; /** * Stream keys specifying the source for each channel, where the order is * significant. The streams must all have the same sample format and sample * rate. */ channelList: readonly StreamKey[]; /** * Callback invoked when the inbound context changes * a new channel list can be returned here that overrides the initial configuration * and allows the channel order to be changed at runtime */ onInputChanged?: (keys: StreamKey[]) => StreamKey[] | undefined; /** The stream key to use for the outging stream*/ outputStreamKey: StreamKey; metrics?: "enabled" | "minimal" | "none"; } /** * @public * see: {@link NorskTransform.audioBuildMultichannel} */ export declare class AudioBuildMultichannelNode extends AutoProcessorMediaNode<"audio"> { } /** * @public * Settings for an Audio Transcribe operation using AWS * see: {@link NorskTransform.audioTranscribeAws} * */ export interface AudioTranscribeAwsSettings extends ProcessorNodeSettings { /** Region for the transcribe endpoint */ awsRegion: string; /** the stream id to allocate to the outgoing stream*/ outputStreamId: number; /** the language that we want to transcribe (also put in the outgoing metadata) */ language: string; /** The mode to be used for building sentences */ sentenceBuildMode: SentenceBuildMode; /** The mode to be used for stabilising sentences */ sentenceStabilizationMode: StabilizationMode; /** The AWS credentials to use for this operation * If not supplied, the standard environment variables will be used if present, or EC2 role credentials (IMDSv1) * */ awsCredentials?: AwsCredentials; } /** * @public * see: {@link NorskTransform.audioTranscribeAws} */ export declare class AudioTranscribeAwsNode extends AutoProcessorMediaNode<"audio"> { } /** * @public * Settings for an Audio Transcribe operation using AWS * see: {@link NorskTransform.subtitleTranslateAws} * */ export interface SubtitleTranslateAwsSettings extends ProcessorNodeSettings { /** Source language code/tag, e.g. de or fr-CA (omit to use the source subtitle language / AWS automatic detection) */ sourceLanguage?: string; /** Target language code/tag, e.g. en or es-MX */ targetLanguage: string; /** Enable brevity option */ brevity?: boolean; /** Enable profanity masking */ maskProfanity?: boolean; } /** * @public * see: {@link NorskTransform.subtitleTranslateAws} */ export declare class SubtitleTranslateAwsNode extends AutoProcessorMediaNode<"audio"> { } /** * @public * CTA-608 format (note this may be embedded in 708 according to output container) * * Aka CEA-608/EIA-608. * Note restrictions on 608 captions - 31 characters per line, a low data rate of about * 60 characters per second, in particular impacting any attempt to pop-on captions with revisions (eg adding word by word) */ export type Cta608Format = { kind: '608'; /** Caption style (default: selected according to source) */ style?: 'pop-on' | 'roll-up'; /** The total/maximum number of lines to use for captioning */ lines?: number; }; /** * @public * CTA-708 format (this means native 708, not the embedding of 608 in 708). * * Note some providers claim 608/708 support but are unclear if this means true 708 or merely 608 embedded in 708. */ export type Cta708Format = { kind: '708'; }; /** * @public * WebVTT format * * Also used as a generic "full text cue" transport for conversion to other output formats. */ export type WebVttFormat = { kind: 'webvtt'; /** Maximum length of any line in the cue in characters */ maximumLineLength?: number; /** Minimum length of the overall cue in characters */ minimumCueLength?: number; /** Maximum number of lines in a cue. * * Consider using a value of 1 and a longer max line length and allowing the player to break lines: per the WebVTT standard * "In general, therefore, authors are encouraged to write cues all on one line except when a line break is definitely necessary." * However if the player does not do this adequately, using the actual max line length desired and more lines, hard line breaks * will be inserted. Note a maximum subtitle length of two lines is recommended (eg BBC guidance) */ maximumNumLines?: number; /** Maximum gap between fragments before breaking into a separate cue. By default some unspecified gap value will be used */ maximumGapMs?: number; /** Maximum duration of the cue, if the cue duration would be greater than this it will be split into a separate cue. By default some unspecified duration value will be used */ maximumDurationMs?: number; /** Words to suppress breaking lines/cues after, e.g. to keep together a title as in "Mr. Spock" the title "Mr." could be added here */ noBreak?: string[]; /** Override text alignment (default: per the source or automatic) */ textAlignment?: SubtitleTextAlignment; }; /** * @public * * Text alignment for subtitles */ export type SubtitleTextAlignment = "left" | "right" | "center" | "start" | "end"; /** * @public * Teletext subtitles format. */ export type TeletextFormat = { kind: 'teletext'; }; /** * @public * TTML (Timed Text Markup Language) subtitles format. */ export type TtmlFormat = { kind: 'ttml'; }; /** * @public * The format to convert subtitles to * */ export type SubtitleConvertFormat = Cta608Format | Cta708Format | WebVttFormat | TeletextFormat | TtmlFormat; /** * @public * Settings for an Subtitle Convert operation * see: {@link NorskTransform.subtitleTranslateAws} * */ export interface SubtitleConvertSettings extends ProcessorNodeSettings { format: SubtitleConvertFormat; /** For conversion from transcribed sources containing partial and complete transcriptions, filter to only include the transcription * from a fully transcribed section/utterance. Note this may be multiple sentences and span up to 30s duration or beyond, making this * generally an option for non-live flows */ onlyComplete?: boolean; } /** * @public * see: {@link NorskTransform.subtitleConvert} */ export declare class SubtitleConvertNode extends AutoProcessorMediaNode<"subtitle"> { } /** * @public * Settings for an DVB Subtitle to image operation * see: {@link NorskTransform.subtitleToImage} * */ export interface SubtitleToImageSettings extends ProcessorNodeSettings { } /** * @public * see: {@link NorskTransform.subtitleToImage} */ export declare class SubtitleToImageNode extends AutoProcessorMediaNode<"subtitle"> { } /** * @public * Settings for an Caption Transform operation * see: {@link NorskTransform.captionTransform} * */ export interface CaptionTransformSettings extends ProcessorNodeSettings { /** Transformations to apply to a teletext stream */ teletext?: TeletextTransformSettings; } export interface TeletextTransformSettings { /** Override the data identifier (optional). */ dataIdentifier?: number; /** Override the magazine (1-8, optional) */ magazine?: number; /** Override the page (optional). Note that the teletext page is usually expressed as 2 hex digits, e.g. 0x88 */ page?: number; /** Shift all content vertically */ verticalAdjust?: { type: "shift"; value: number; }; } /** * @public * Settings for updating a Caption Transform operation at runtime * see: {@link CaptionTransformNode.updateConfig} * */ export interface CaptionTransformSettingsUpdate { /** Transformations to apply to a teletext stream */ teletext?: TeletextTransformSettings; } /** * @public * see: {@link NorskTransform.captionTransform} */ export declare class CaptionTransformNode extends AutoProcessorMediaNode<"subtitle"> { /** * Updates the teletext transform configuration at runtime * @param settings - The updated teletext settings */ updateConfig(settings: CaptionTransformSettingsUpdate): void; } /** * @public * Settings for an audio transcribe/translate operation using Azure Speech Service * see: {@link NorskTransform.audioTranscribeAzure} * */ export interface AudioTranscribeAzureSettings extends ProcessorNodeSettings { outputStreamId: number; /** The source language to recognise - an IETF BCP 47 language tag, eg en-US, en-GB, de-DE. Supported languages are * found at https://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-support?tabs=stt */ sourceLanguage: string; /** The target output languages for translation - technically a BCP 47 language tag but but in most cases omitting region, e.g. en, de, zh-Hant. * Leave this field absent/empty to use the transcription service without * translation, while if any target languages are present the translation service will be used even if this is the same as the * source language. */ targetLanguages?: string[]; /** Key for the Azure Speech Service endpoint */ azureKey: string; /** Region for the Azure Speech Service endpoint */ azureRegion: string; /** Enable dictation mode (recognise dictated punctuation etc rather than transcribing the audio verbatim) */ dictation?: boolean; /** Profanity behaviour (whether to mask or remove profanity) */ profanity?: 'masked' | 'removed' | 'raw'; } /** * @public * see: {@link NorskTransform.audioTranscribeAws} */ export declare class AudioTranscribeAzureNode extends AutoProcessorMediaNode<"audio"> { } /** * @public * Settings for an Audio Transcribe operation using Whisper sdk (whisper-cpp) * see: {@link NorskTransform.audioTranscribeWhisper} * */ export interface AudioTranscribeWhisperSettings extends ProcessorNodeSettings { /** Stream ID of the output subtitles */ outputStreamId: number; /** The duration of audio that is accumulated before performing one transcription step. Decreasing this * value will decrease latency but also decrease performance. Visualiser metrics are available to monitor the * duration of each "step" operation, if this is not clearly faster than the audio duration real-time output will not be * attained and the workflow will back up. * * Default 3000ms. */ stepMs?: number; /** Duration of audio to keep when clearing the buffer to allow for partial-word recognition. Default 400ms */ keepMs?: number; /** Max tokens per segment */ maxTokens?: number; noFallback?: boolean; /** Number of threads to use. Note using a large number of threads rarely improves performance */ numThreads?: number; /** * Use GPU if available. In the cases where GPU is available, it may not necessarily increase performance, but instead opt * to move load from CPU to GPU. */ useGpu?: boolean; /** * Language setting for the Whisper model. Leave unset to auto-detect (with a multi-language model) */ language?: string; /** * The file name of the GGML-format whisper model. * * Information: https://github.com/ggerganov/whisper.cpp/blob/master/models/README.md * * Model downloads: https://huggingface.co/ggerganov/whisper.cpp/tree/main */ model: string; /** * Whether to translate a non-English input to English, or leave the foreign-language transcription in the source language. */ translate?: boolean; /** * Enable tiny-diarize if supported in the given model */ tinyDiarize?: boolean; /** * Initial prompt to prime the model - this is in addition to prompting based on past transcription history. */ initialPrompt?: string; /** * Whether to supply a prompt consisting of the tokens recognised in the previous chunk. By default it is not supplied, relying only * on the overlap of transcription chunks to resolve partial words occurring at the start/end of a chunk. */ contextPrompt?: boolean; /** * Whether to suppress non-speech tokens */ suppressNonSpeechTokens?: boolean; /** Greedy (default) or beam sampling strategy */ samplingStrategy?: WhisperSamplingStrategy; initialTemperature?: number; /** Temperature increment on fallback (unset: use library default, currently 0.2). To disable fallback set this explicitly to 0.0 */ temperatureIncrement?: number; entropyThreshold?: number; logProbThreshold?: number; noSpeechThreshold?: number; /** * VAD configuration (omit: disable vad) - using a VAD model (eg silero) integrated * in whisper-cpp to both reduce the number of processed samples and suppress non-speech content */ vad?: AudioTranscribeWhisperVadSettings; /** * Callback to receive raw whisper transcription chunks - timed sequences of fragments (words or partial words) which have been * recognised during a single inference pass, without de-overlapping to remove duplicate or partial words in the overlap region between * consecutive chunks, word merging, timestamp correction, etc. */ onChunk?: (chunk: WhisperRawChunk) => void; } /** * @public * Settings for whisper-cpp VAD model * see: {@link AudioTranscribeWhisperSettings} * */ export interface AudioTranscribeWhisperVadSettings { /** * The file name of the GGML-format whisper VAD model, ie a GGML silero-vad model. * * Model downloads: https://huggingface.co/ggml-org/whisper-vad */ model: string; /** Probability threshold to consider as speech. */ threshold?: number; /** Min duration for a valid speech segment. */ minSpeechDurationMs?: number; /** Min silence duration to consider speech as ended. */ minSilenceDurationMs?: number; /** Max duration of a speech segment before forcing a new segment. */ maxSpeechDurationS?: number; /** Padding added before and after speech segments. */ speechPadMs?: number; /** Overlap in seconds when copying audio samples from speech segment. */ samplesOverlap?: number; } type WhisperSamplingStrategy = { strategy: 'greedy'; bestOf?: number; } | { strategy: "beam_search"; beam_size?: number; }; /** * @public */ export interface WhisperRawChunk { startTimestamp: Interval; endTimestamp: Interval; fragments: SubtitleFragment[]; } /** * @public * see: {@link NorskTransform.audioTranscribeWhisper} */ export declare class AudioTranscribeWhisperNode extends AutoProcessorMediaNode<"audio"> { } /** * @public * A single rung in a video encode ladder * see: {@link NorskTransform.videoEncode} * */ export interface VideoEncodeRung { /** The name of this rung, this should be unique across the ladder * and will end up in the renditionName of the outgoing StreamKey */ name: string; /** The width of the outgoing video resolution */ width: number; /** The height of the outgoing video resolution */ height: number; /** * Optionally change the frameRate for this rendition * This can be useful if the input is 50FPS for example and some * lower rungs need to be 25fps * * Note: If you wish to apply the same frame rate across all rungs, it is * more efficient to use a single {@link VideoTransformNode} before the ladder * created with {@link NorskTransform.videoTransform} and leave this value undefined * */ frameRate?: FrameRate; /** * Specifies the input video's Sample Aspect Ratio (SAR) to be used by the * encoder in width:height */ sar?: SampleAspectRatio; /** * The codec (and detailed configuration) to use for the encoding operation. * * Note: Nvidia, Logan/Quadra, AmdU30, AmdMA35D require the appropriate hardware to be set up and * made available to Norsk * * A ladder can use several different codecs across its various rungs and the * VideoEncode node will attempt to build a pipeline that uses the hardware efficently */ codec: X264Codec | X265Codec | MainConceptHevcCodec | SvtJpegXsCodec | NvidiaH264 | NvidiaHevc | LoganH264 | LoganHevc | QuadraH264 | QuadraHevc | QuadraAv1 | AmdU30H264 | AmdU30Hevc | AmdMA35DH264 | AmdMA35DHevc | AmdMA35DAv1; /** * Extra options for influencing how the ladder gets constructed and what algorithms get used for certain operations */ pipelineHints?: QuadraPipelineHints; /** * Arrange for gops to be created in a consistent manner across multiple encoders; used for primary/backup systems * so that HLS/DASH outputs have consistent segmentation to enable seamless player switching. * If you want this, then you should set this to 'true' for every run that is being used in your ABR ladder; rungs * not used in the ladder can be left as false (or unset, which defaults to false). * For rungs where consistentGops is true there are some restrictions: * - gop sizes must be set and fixed, and must all be equal or be integral multiples of each other * - frame rates must either be *all* left undefined (in which case source frame rate is used), or must *all* be set and, as * with the gop size, they can be different but if they are they must be integral multiples. */ consistentGops?: boolean; } /** * @public * Settings for a VideoEncode operation * see: {@link NorskTransform.videoEncode} * */ export interface VideoEncodeSettings extends ProcessorNodeSettings { rungs: readonly VideoEncodeRung[]; fillGaps?: boolean; } /** * @public * see: {@link NorskTransform.videoEncode} */ export declare class VideoEncodeNode extends AutoProcessorMediaNode<"video"> { } /** * @public * Settings for a VideoDecode operation * see: {@link NorskTransform.videoDecode} * */ export type VideoDecodeSettings = MostVideoDecodeSettings | SoftwareDecodeSettings; export interface MostVideoDecodeSettings extends ProcessorNodeSettings { decoder: 'nvidia' | 'quadra' | 'logan' | 'amdU30' | 'amdMA35D'; } export interface SoftwareDecodeSettings extends ProcessorNodeSettings { decoder: "software"; threadCount?: number; lowDelay?: boolean; } /** * @public * see: {@link NorskTransform.videoDecode} */ export declare class VideoDecodeNode extends AutoProcessorMediaNode<"video"> { } /** * @public * Settings for a Video Transform node * see: {@link NorskTransform.videoTransform} * */ export interface VideoTransformSettings extends ProcessorNodeSettings { /** An optional resolution to rescale this single stream to */ resolution?: Resolution; /** An optional framerate to resample this single stream to * NB: only supported in software */ frameRate?: FrameRateSettings; /** An optional de-interlace algorithm to apply on this stream * NB: only supported in software */ deinterlace?: DeinterlaceSettings; /** An optional pixel format for output - NB: This only has any effect with in-memory software frames It is mostly useful if you have a high bpp pixelFormat (for example yuv422p or yuv444p) and want to encode yuv420p with x264 **/ pixelFormat?: PixelFormat; /** An optional SAR to set on the outgoing stream * Note: You can set this and only this if the SAR on your incoming stream is incorrect * for example (An often-seen problem with sources) * */ sar?: SampleAspectRatio; /** * Optionally force this operation to take place on hardware / in software * Not all operations are supported by each mode * This is also useful for forcing an upload/download in a known location in your workflow before other operations */ hardwareAcceleration?: "nvidia" | "quadra" | "software"; /** * Extra options for influencing how the pipeline gets constructed and what algorithms get used for certain operations. * Silently ignored when the operation does not run on Quadra hardware. */ pipelineHints?: QuadraPipelineHints; } /** * @public * see: {@link NorskTransform.videoTransform} */ export declare class VideoTransformNode extends AutoProcessorMediaNode<"video"> { } /** * @public * Randomly drop frames on a stream * - 0.0 means don't drop any frames * - 1.0 means drop every single frame * */ export interface DropRandom { kind: "random"; percentage: number; start?: number; end?: number; } /** * @public * Drop every N frames from an incoming video stream * */ export interface DropEvery { kind: "every"; every: number; } /** * @public * Drop the first N frames from an incoming video stream * */ export interface DropStart { kind: "start"; start: number; } /** @public * Drop a number of frames after a certain N frames have already been accepted */ export interface DropAfter { kind: "drop_after"; start: number; count: number; } /** * @public * Video chaos effect mode */ /** * @public * Colour of noise pixels in white noise mode */ export type NoiseColour = "white" | "black" | "random"; /** * @public * Video chaos effect mode */ export type VideoChaosMode = { kind: "disabled"; } | { kind: "black_frames"; } | { kind: "green_frames"; } | { kind: "frozen_frames"; } | { kind: "white_noise"; percentage: number; pixelSize: number; colour?: NoiseColour; } | { kind: "blocky"; blockSize: number; }; /** * @public * The settings for a Chaos Monkey * see: {@link NorskTransform.streamChaosMonkey} * */ export interface StreamChaosMonkeySettings extends ProcessorNodeSettings { /** Optional configuration to drop frames from a stream * leaving this undefined means don't drop any frames * */ frameDrop?: DropRandom | DropEvery | DropStart | DropAfter; /** * Introduce random jitter */ jitterMs?: number; /** Periodically output a null context and start dropping frames for a specified interval NB: This will automatically reset should a new context arrive while dropping frames */ nullContexts?: { frequency: number; duration: number; }; /** * Optional video chaos effect to apply to raw video frames. * Non-video frames are passed through unchanged. */ videoChaos?: VideoChaosMode; } /** * @public * see: {@link NorskTransform.streamChaosMonkey} */ export declare class StreamChaosMonkeyNode extends AutoProcessorMediaNode<"audio" | "video" | "subtitle"> { pause(): void; play(): void; /** * Update the video chaos effect at runtime */ updateVideoChaos(mode: VideoChaosMode): void; } /** * @public * Settings for a WebRTC browser session * see: {@link NorskDuplex.webRtcBrowser} * */ export interface WebRTCBrowserSettings extends ProcessorNodeSettings, StreamStatisticsMixin { /** List of ice servers to use as part of session negotiation */ iceServers?: IceServerSettings[]; /** Internal addresses for the ice servers (defaults to iceServers) */ reportedIceServers?: IceServerSettings[]; /** * List of IPs to advertise as your host address - useful e.g. when on a cloud server * so that the public rather than private IP is used. */ hostIps?: string[]; /** * Similar to hostIps, but a list of server reflexive candidates so that ICE negotiations can be * sped up */ serverReflexiveIps?: string[]; /** Jitter buffer configuration */ jitterBuffer?: JitterBufferConfig; name: string; } /** * @public * see: {@link NorskDuplex.webRtcBrowser} */ export declare class WebRTCBrowserNode extends AutoProcessorMediaNode<"audio" | "video"> { /** @public The URL of the local player */ playerUrl: string; /*** * @public The URL of the duplex endpoint * * This negotiation protocol is non-standard but can be used with the `DuplexClient` in `@norskvideo/webrtc-client` */ endpointUrl: string; } /** * @public * Settings for a SIP session */ export interface SipSettings extends ProcessorNodeSettings, StreamStatisticsMixin { sourceName: string; jitterBuffer?: JitterBufferConfig; account: SipAccountSettings; publicAddr?: string; call: SipCallSettings; onStatus?: (status: SipEvent_Status) => void; onConnectionStats?: (stats: SipConnectionStatistics) => void; } export interface SipAccountSettings { id: string; credentials: SipAccountCredentials; regUri?: string; } export interface SipAccountCredentials { realm: string; username: string; credential: SipAccountCredential; } export type SipAccountCredential = { type: "plain"; password: string; } | { type: "digest"; digest: string; }; export interface SipCallSettings { address: string; } export interface SipConnectionStatistics { send: SipStreamStatistics; receive: SipStreamStatistics; } export interface SipStreamStatistics { numBytes: number; numPackets: number; } /** * @public * see: {@link NorskDuplex.sip} */ export declare class SipNode extends AutoProcessorMediaNode<"audio"> { /** @public * * Send a sequence of DTMF digits, via RFC2833 (if supported by the peer) */ sendDtmf(digits: string): void; } /** * @public * Methods that allow you to both ingest and egest media from your application * at the same time */ export interface NorskDuplex { /** * Playback audio/video via webrtc to a browser, and accept audio/video input from a browser. * The browser client must conform to a custom protocol as implemented in the hosted test page. * (Available from {@link WebRTCBrowserNode.playerUrl} * For general WebRTC ingest prefer the WHIP input node, and for egest to a downstream media server * use the WHIP output node. For browser egest (e.g. stream preview) use the WHEP output node. * @param settings - Options for the webrtc node */ webRtcBrowser(settings: WebRTCBrowserSettings): Promise; sip(settings: SipSettings): Promise; } /** * @public * Methods that allow you to embed audio watermarks into your media streams */ export interface NorskKantarEmbedder { /** * Embeds audio watermarks into the audio stream, using the Kantar Snap Live Embedder. * * @remarks * Norsk supports both online and offline licensing models. In order to get a watermarking * embedding license, please contact Kantar support at https://www.kantarmedia.com/watermarkinghelpdesk * with following information: * * * Product name and version * * * Customer name * * * Country * * * If different, country of broadcast * * * Channel(s) to be watermarked * * * Customer internal name for the hardware platform * * * AuthorisationCode for each hardware or login contact for online solution. * * Once you have obtained the appropriate Kantar license, you can configure this through * the license field in the settings, providing either an {@link KantarSnapOnlineLicense} or * an {@link KantarSnapOfflineLicense}. On startup, the {@link KantarSnapSettings.onLicenseInformation} callback * is called, providing information about your license. * * Events from the Kantar embedder are raised through the {@link KantarSnapSettings.onLicenseInformation} callback, * which you can use to log in your own application's event logs. Norsk also logs this information to the default Norsk * log files. * * Norsk automatically handles synchronisation between the Kantar embedding process and the * local system time. It performs a resync every 12 hours, and any time that a jump in the * system clock occurs of more than 10 seconds. This is reported via the {@link KantarSnapSettings.onTimecodeResync} event. * * Note that when active, the watermarking processing will introduce a constant audio delay of 2560 audio * samples, which is 53ms at 48kHz; Norsk will ensure that all related media streams (e.g. * video) are kept in sync. * * Obviously the audio watermark is only applied to streams that it is subscribed to. If for some reason your application * needs to close the watermarking node, or drop the subscriptions to the source streams to some reason, you should * ensure that this is done when off-air. * * Obviously the audio watermark is only applied to streams that it is subscribed to. If for some reason your application * needs to close the watermarking node, or drop the subscriptions to the source streams to some reason, you should * ensure that this is done when off-air. * */ kantarEmbedder(settings: KantarSnapSettings): Promise; /** * This method allows you to query the channels available in an offline license */ queryKantarOfflineLicense(settings: KantarSnapOfflineLicenseBase): Promise; /** * This method allows you to query licenses and the channels available in each license with your login to the Kantar licensing server. */ queryKantarOnlineLicense(settings: KantarSnapOnlineLicenseBase): Promise; /** * This method allows you to query the version information related to the Kantar Embedder */ queryKantarVersion(): Promise; } /** * @public * Methods that allow you to manipulate color space, transfer functions etc in your video streams */ export interface NorskColor { /** * Apply tone mapping to convert HDR/HLG content to SDR * @param settings - Tone mapping settings */ hlgToSdr(settings: HlgToSdrSettings): Promise; /** * Apply a LUT cube to the video stream * @param settings - LUT Cube settings */ lutProcessor(settings: LutProcessorSettings): Promise; } /** * @public * Methods that allow you to manipulate your media streams */ export interface NorskTransform { /** * Inject SEI messages (timecodes, quality metrics) into an H.264 or HEVC stream * @param settings - SEI injection settings */ seiInjection(settings: SeiInjectionSettings): Promise; /** * Encode a video stream to one or more renditions * using either software or appropriate hardware if available * @param settings - Encode ladder settings */ videoEncode(settings: VideoEncodeSettings): Promise; /** * Decode a video stream to a specific type of 'raw' format * this isn't usually needed because decode will happen automatically for nodes that need raw data * however if we definitely want a hardware decode and we're creating nodes that accept inMemory raw, we can use this node * to ensure that the hardware decode takes place * @param settings - Decode settings */ videoDecode(settings: VideoDecodeSettings): Promise; /** * Decode an audio stream to raw PCM * this isn't usually needed because decode will happen automatically for nodes that need raw data * however it can be useful for explicitly controlling the decode pipeline * @param settings - Decode settings */ audioDecode(settings: AudioDecodeSettings): Promise; /** * Transform a single video stream (rescale, frame rate, etc) * @param settings - Transform settings */ videoTransform(settings: VideoTransformSettings): Promise; /** * Interferes with a stream by dropping frames * Why would you want this? Stick one of these after a decoder and before * anything else in order to simulate what the world is going to look like if you * have network problems (packet drops for example) in your ingest * * *Just don't forget to remove it again when you've finished testing!* * @param settings - Chaos monkey settings */ streamChaosMonkey(settings: StreamChaosMonkeySettings): Promise; /** * Compose multiple video streams together into a single output * @param settings - Composition settings */ videoCompose(settings: VideoComposeSettings): Promise>; /** * Create a Media Node performing transcription into subtitles using the * Amazon Transcribe AWS service. * @param settings - Settings and credentials for AWS transcribe */ audioTranscribeAws(settings: AudioTranscribeAwsSettings): Promise; /** * Create a Media Node performing transcription into subtitles using the * Azure Speech service. * @param settings - Settings and credentials for Azure transcribe */ audioTranscribeAzure(settings: AudioTranscribeAzureSettings): Promise; /** * Create a Media Node performing transcription into subtitles using the * Whisper speech recognition model via the whisper-cpp SDK. * * For reference on general concepts https://github.com/ggerganov/whisper.cpp - many settings are directly settings on the * underlying library and can be evaluted via the CLI tool there also. * @param settings - Settings and credentials for Whisper transcribe */ audioTranscribeWhisper(settings: AudioTranscribeWhisperSettings): Promise; /** * Mix multiple audio streams together into a single output, * with optional gain control on each input. * @param settings - Settings for the mixer, including the gain vectors */ audioMix(settings: AudioMixSettings): Promise>; /** * Given an audio stream of N channels, mix it down to M channels through a matrix of NxM gains. * @param settings - Settings for the mixer, including the gain matrix */ audioMixMatrix(settings: AudioMixMatrixSettings): Promise; /** * Run a spectrum-audio processing graph (gain, filter, …) over an audio stream. * The graph is built with a type-safe builder, so it is acyclic by construction. * @param settings - Settings, including the `build` callback that wires the graph */ audioGraph(settings: AudioGraphSettings): Promise>; /** * Apply gain to an audio stream * @param settings - Settings for the gain node */ audioGain(settings: AudioGainSettings): Promise; /** * Aggregate many single-channel audio streams into a stream with the * specified channel layout. The streams must all have the same sample format * and sample rate. The order of the streams provided for the channels is * important. * @param settings - Settings for the builder, including the channel layout * and stream keys specifying the sources for each channel. */ audioBuildMultichannel(settings: AudioBuildMultichannelSettings): Promise; /** * Split a multichannel audio stream into its individual channels. The first * channel receives the specified stream key, and each subsequent channel * increments the stream id on the stream key. * @param settings - Settings for the splitter */ audioSplitMultichannel(settings: AudioSplitMultichannelSettings): Promise; /** * Encode an audio stream. * @param settings - Settings for the encoder, including channel layout and * bitrate. */ audioEncode(settings: AudioEncodeSettings): Promise; /** * Encode an audio + video stream pair to Dolby E. Dolby E is video-frame-locked, * so subscribe both an audio source (to the "audio" pin) and a video source * (timing only, to the "video" pin); the frame rate is derived from the video. * @param settings - Settings for the encoder (program config, bit depth, rendition name). */ dolbyEEncode(settings: DolbyEEncodeSettings): Promise; /** * Methods to allow you to embed watermarks into audio streams */ audioWatermark: NorskKantarEmbedder; /** * Inject a source time into a stream or streams - this is intended for simple test scenarios, * and not for production use. In production, source times should come from standards such as SEI pic_timing * messages or VITC timecodes */ sourceTime(settings: SourceTimeSettings): Promise; /** * Translate subtitles using the AWS Translate service. * * Credentials are provided either via the standard AWS environment variables (for the Norsk server instance), * EC2 role credentials (IMDSv2), etc via the AWS SDK standard credential provider chain. */ subtitleTranslateAws(settings: SubtitleTranslateAwsSettings): Promise; /** * Convert subtitles/captions/transcriptions from one format to another * * Similar to audio and video encodes, this may happen implicitly as required, but this explicit node allows * choice of format and conversion parameters to be specified * @param settings - Conversion settings */ subtitleConvert(settings: SubtitleConvertSettings): Promise; /** * Convert a DVB subtitling stream to images * * Suggested use: overlay (i.e. burn in) with {@link NorskTransform.videoCompose}, or consume client side with an image preivew. */ subtitleToImage(settings: SubtitleToImageSettings): Promise; /** * Transform a subtitle/caption stream (eg Teletext, CEA608) without conversion or fully re-encoding * * @param settings - Conversion settings */ captionTransform(settings: CaptionTransformSettings): Promise; /** * A node to nudge the timestamps on a stream, which affects how it syncs * with other streams. Useful for correcting for drift between different * sources. * * Subsequent nudges, via the `nudge` method, are applied gradually. * * This functionality is also provided by a `nudge` method on many sources. * @param settings - Initial nudge plus general node settings. */ streamTimestampNudge(settings: StreamTimestampNudgeSettings): Promise; /** * Provide a new stream key for a single stream. Cannot be subscribed to * multiple streams at once. * * The stream key is used for identifying streams within multiplexed sources * and also is translated into URIs for HLS playlists and other resources. * * This can be useful if changing sources and wanting to maintain a consistent * streamkey going into an output * @param settings - New stream key plus general node settings. */ streamKeyOverride(settings: StreamKeyOverrideSettings): Promise; /** * Override bitrate and language metadata on streams. * * Audio and video bitrate metadata is required for playlists for the * {@link NorskOutput.cmafMultiVariant} node. * It is automatically configured for some sources (like RTMP) and in * cases where re-encoding is done, but is unset for other sources (like SRT). * @param settings - Bitrate and language metadata plus general node settings. */ streamMetadataOverride(settings: StreamMetadataOverrideSettings): Promise; /** * Buffer a stream for the specified number of milliseconds. This can be used * to reduce or eliminate jitter. * @param settings - Buffer delay time. */ jitterBuffer(settings: JitterBufferSettings): Promise; /** * Sync multiple streams together by timestamps, queuing frames from streams * that are behind the others. This is already included in most nodes, * especially outputs. */ streamSync(settings: StreamSyncSettings): Promise; /** * This processor does multiple things * - joins together multiple streams from multiple sources * - rebases their timestamps so that they all start at the same point * - sets the program id to a common value * * It is useful for syncing multiple incoming streams that on paper are already synchronised but because * of the time taken to set up connections and subscriptions across various protocols, are off by a few * hundred milliseconds */ streamAlign(settings: StreamAlignSettings): Promise; /** * Condition a stream for switching (i.e. for ad insertion) * * Provides a mechanism for requesting that a straem be conditioned for switching, with in and out points. * This means insertion of IDR frames, relevant to both continuous outputs (e.g. TS based), and hinting * of segmentation breaks for segmented outputs (ie HLS). * * This may be used in combination with an {@link NorskTransform.ancillary} node for reacting to SCTE-35 message * @param settings - Options for the conditioner */ streamCondition(settings: StreamConditionSettings): Promise; /** * Observe, modify or inject ancillary data such as SCTE-35 or timed metadata. * * If intending to send ancillary messages without a specified timestamp this node should be subscribed * to an audio or video stream from the given program to act as a timing source. */ ancillary(settings: AncillarySettings): Promise; /** * Combine compatible streams of metadata (this refers to ancillary streams of metadata messages, such as that * carried in an MPEG-TS PES metadata stream (e.g. KLV), unrelated to operations on the metadata of audio/video/etc streams. */ metadataCombine(settings: MetadataCombineSettings): Promise; /** * Apply a Spectrum video processing expression to the video stream. * Supports resize, crop, compose, color grading, tone mapping, LUT application, * transfer function conversion, and gamut mapping. * @param settings - Spectrum processing settings */ spectrum(settings: SpectrumSettings): Promise; /** * Implements the {@link NorskColor} interface */ color: NorskColor; /** * Provides for frame-accurate HTML transitions */ browserRender(settings: BrowserRenderSettings): Promise; } /** * @public * Methods that allow you to control and monitor media streams */ export interface NorskControl { /** * Switch between multiple input sources via a hard cut. May be used to switch between * sources of possibly different configurations or without decoding. * * May be used for audio-only, video-only, or A/V sources; when video is present, switches will occur * on a keyframe when possible. * @param settings - Options for the switcher */ streamSwitchHard(settings: StreamSwitchHardSettings): Promise>; /** * Switch between multiple input sources without interruption, via a transition. * @param settings - Options for the switcher */ streamSwitchSmooth(settings: StreamSwitchSmoothSettings): Promise>; /** * Play a sequence of sources gaplessly, with auto-advance on EOF and * an optional early-cut trigger ({@link StreamSourceSequenceNode.advanceNow}). * Companion to (and recommended replacement for) the * {@link NorskControl.streamSwitchHard} playlist pattern. * @param settings - Sequence configuration and event callbacks */ streamSourceSequence(settings: StreamSourceSequenceSettings): Promise>; /** * Record statistical information about media streams, including bitrate, * frame rate, and number of keyframes, measured over some configurable * sampling windows. * * Corresponding settings are found on many input and output nodes. * @param settings - Callback and sampling intervals */ streamStatistics(settings: StreamStatisticsSettings): Promise; /** * Monitor the volume of an audio stream * @param settings - Callback and options for the level data */ audioMeasureLevels(settings: AudioMeasureLevelsSettings): Promise; /** * Analyze video input to detect colour primaries, transfer function, * video range, and other metadata with confidence scoring. * Samples 1-in-N frames and streams detection results. * @param settings - Callback and options for inference */ spectrumInputInference(settings: SpectrumInputInferenceSettings): Promise; embeddedAI(settings: EmbeddedAINodeSettings): Promise; } /** @public */ export declare class NorskProcessor { /** * Implements the {@link NorskControl} interface */ control: NorskControl; /** * Implements the {@link NorskTransform} interface */ transform: NorskTransform; /** * Create a reasoning plan session for interactive ReasoningSpec generation * @param settings - Query, provider, and callbacks for the plan session */ reasoningPlan: (settings: ReasoningPlanSettings) => Promise; /** * Create a reasoning evaluate node that evaluates video against a ReasoningSpec * @param settings - ReasoningSpec, provider, video settings */ reasoningEvaluate: (settings: ReasoningEvaluateSettings) => Promise; /** * Create a live plan session for interactive LiveSpec generation * @param settings - Query, provider, and callbacks for the live plan session */ livePlan: (settings: LivePlanSettings) => Promise; /** * Create a live evaluate node that uses the Gemini Live API to continuously * analyse video/audio, dispatching tool calls and text in real time. * @param settings - LiveSpec, provider, video settings */ liveEvaluate: (settings: LiveEvaluateSettings) => Promise; constructor(parent: Norsk, client: MediaClient); } export {}; //# sourceMappingURL=processor.d.ts.map