@norskvideo/norsk-sdk 1.0.331 → 1.0.334

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,17 +8,15 @@ import { CurrentLoad } from '@norskvideo/norsk-api/lib/shared/common_pb';
8
8
  import { ExplicitChannel } from '@norskvideo/norsk-api/lib/media_pb';
9
9
  import { FileTsInputMessage } from '@norskvideo/norsk-api/lib/media_pb';
10
10
  import * as grpc from '@grpc/grpc-js';
11
- import { HlsMasterPushMessage } from '@norskvideo/norsk-api/lib/media_pb';
12
11
  import { HlsOutputEvent } from '@norskvideo/norsk-api/lib/media_pb';
13
12
  import { HlsTsAudioMessage } from '@norskvideo/norsk-api/lib/media_pb';
14
- import { HlsTsAudioPushMessage } from '@norskvideo/norsk-api/lib/media_pb';
15
13
  import { HlsTsCombinedPushMessage } from '@norskvideo/norsk-api/lib/media_pb';
16
14
  import { HlsTsVideoMessage } from '@norskvideo/norsk-api/lib/media_pb';
17
- import { HlsTsVideoPushMessage } from '@norskvideo/norsk-api/lib/media_pb';
18
- import { HlsWebVttPushMessage } from '@norskvideo/norsk-api/lib/media_pb';
19
15
  import { MediaClient } from '@norskvideo/norsk-api/lib/media_grpc_pb';
20
16
  import { Nullable } from 'typescript-nullable';
21
17
  import { PlainMessage } from '@bufbuild/protobuf';
18
+ import { RtmpError_UnsupportedAudio } from '@norskvideo/norsk-api/lib/media_pb';
19
+ import { RtmpError_UnsupportedVideo } from '@norskvideo/norsk-api/lib/media_pb';
22
20
  import { StreamKey as StreamKey_2 } from '@norskvideo/norsk-api/lib/media_pb';
23
21
  import { StreamStatisticsSampling } from '@norskvideo/norsk-api/lib/media_pb';
24
22
  import { Subscription } from '@norskvideo/norsk-api/lib/media_pb';
@@ -398,7 +396,6 @@ export declare interface AwsCredentials {
398
396
  accessKey: string;
399
397
  secretKey: string;
400
398
  sessionToken: string;
401
- region: string;
402
399
  }
403
400
 
404
401
  /**
@@ -651,6 +648,18 @@ export declare type ChannelName =
651
648
  /** Unknown */
652
649
  | "unknown";
653
650
 
651
+ /** @public */
652
+ export declare function clientHostExternal(): string;
653
+
654
+ /** @public */
655
+ export declare function clientHostInternal(): string;
656
+
657
+ /** @public */
658
+ export declare function clientPortExternal(): string;
659
+
660
+ /** @public */
661
+ export declare function clientPortInternal(): string;
662
+
654
663
  /**
655
664
  * @public
656
665
  * see: {@link NorskOutput.cmafAudio}
@@ -807,6 +816,13 @@ export declare interface CmafVideoOutputSettings extends SinkNodeSettings<CmafVi
807
816
  * see: {@link NorskOutput.cmafWebVtt}
808
817
  */
809
818
  export declare class CmafWebVttOutputNode extends HlsNodeWithPlaylist<CmafWebVttMessage, "subtitle", CmafWebVttOutputNode> {
819
+ /**
820
+ * @public
821
+ * Updates the credentials for a specific destination within this output by id
822
+ * see: {@link UpdateCredentials}
823
+ * see: {@link CMAFDestinationSettings}
824
+ */
825
+ updateCredentials(settings: UpdateCredentials): void;
810
826
  }
811
827
 
812
828
  /**
@@ -820,13 +836,6 @@ export declare interface CmafWebVttOutputSettings extends SinkNodeSettings<CmafW
820
836
  * in a compliant manner if necessary
821
837
  */
822
838
  segmentDurationSeconds: number;
823
- /**
824
- * Optionally supply a string that will be inserted into the path structure for segments published in this stream
825
- *
826
- * This is useful for stream restarts or republishing when duplicate segment IDs would be generated causing problems with
827
- * cacheing directives
828
- */
829
- sessionId?: string;
830
839
  /**
831
840
  * By default, the program date time or event start time will be based on the
832
841
  * timestamp of the first video packet received by Norsk in a stream.
@@ -839,6 +848,18 @@ export declare interface CmafWebVttOutputSettings extends SinkNodeSettings<CmafW
839
848
  * This number should match the delayOutputMs of other streams which will be served within the same master playlist
840
849
  */
841
850
  delayOutputMs?: number;
851
+ /**
852
+ * A list of destinations {@link CMAFDestinationSettings} for this stream to be published to
853
+ */
854
+ destinations: CMAFDestinationSettings[];
855
+ /**
856
+ * A local directory in which to store the segments while they're available
857
+ */
858
+ hlsCacheDirectory: string;
859
+ /**
860
+ * The maximum number of segments to display in a single generated playlist
861
+ */
862
+ maximumPlaylistSegments: number;
842
863
  }
843
864
 
844
865
  declare class CommonHlsNode<ClientMessage, Pins extends string, T extends MediaNodeState> extends AutoSinkMediaNode<Pins> {
@@ -1176,29 +1197,6 @@ export declare interface HardwareInfo {
1176
1197
  deckLinkCards: DeckLinkCard[];
1177
1198
  }
1178
1199
 
1179
- /**
1180
- * @public
1181
- * see: {@link NorskOutput.hlsMasterPush}
1182
- */
1183
- export declare class HlsMasterPushOutputNode extends CommonHlsNode<HlsMasterPushMessage, "video" | "audio" | "subtitle", HlsMasterPushOutputNode> {
1184
- }
1185
-
1186
- /**
1187
- * @public
1188
- * The settings for pushing a master playlist to a destination
1189
- * see: {@link NorskOutput.hlsMasterPush}
1190
- */
1191
- export declare interface HlsMasterPushOutputSettings extends SinkNodeSettings<HlsMasterPushOutputNode> {
1192
- /**
1193
- * The name of this master playlist (.m3u8 will be added onto this field to generate a filename)
1194
- */
1195
- playlistName: string;
1196
- /**
1197
- * The destinations {@link CMAFDestinationSettings} for this playlist to be published to
1198
- */
1199
- destination: CMAFDestinationSettings;
1200
- }
1201
-
1202
1200
  declare class HlsNodeWithPlaylist<ClientMessage, Pins extends string, T extends MediaNodeState> extends CommonHlsNode<ClientMessage, Pins, T> {
1203
1201
  constructor(client: MediaClient, settings: SinkNodeSettings<T> & StreamStatisticsMixin, grpcInit: () => grpc.ClientDuplexStream<ClientMessage, HlsOutputEvent>, subscribeFn: (subscription: Subscription) => void);
1204
1202
  /**
@@ -1250,6 +1248,13 @@ export declare interface HlsPushDestinationSettings {
1250
1248
  * see: {@link NorskOutput.hlsTsAudio}
1251
1249
  */
1252
1250
  export declare class HlsTsAudioOutputNode extends CommonHlsNode<HlsTsAudioMessage, "audio", HlsTsAudioOutputNode> {
1251
+ /**
1252
+ * @public
1253
+ * Updates the credentials for a specific destination within this output by id
1254
+ * see: {@link UpdateCredentials}
1255
+ * see: {@link CMAFDestinationSettings}
1256
+ */
1257
+ updateCredentials(settings: UpdateCredentials): void;
1253
1258
  }
1254
1259
 
1255
1260
  /**
@@ -1275,42 +1280,10 @@ export declare interface HlsTsAudioOutputSettings extends SinkNodeSettings<HlsTs
1275
1280
  * This number should match the delayOutputMs of other streams which will be served within the same master playlist
1276
1281
  */
1277
1282
  delayOutputMs?: number;
1278
- }
1279
-
1280
- /**
1281
- * @public
1282
- * see: {@link NorskOutput.hlsTsAudioPush}
1283
- */
1284
- export declare class HlsTsAudioPushOutputNode extends CommonHlsNode<HlsTsAudioPushMessage, "audio", HlsTsAudioOutputNode> {
1285
- }
1286
-
1287
- /**
1288
- * @public
1289
- * Settings for a HLS Transport Stream Audio Push Output
1290
- * see {@link NorskOutput.hlsTsVideoPush}
1291
- */
1292
- export declare interface HlsTsAudioPushOutputSettings extends SinkNodeSettings<HlsTsAudioPushOutputNode> {
1293
1283
  /**
1294
- * The target segment duration in seconds. Norsk will make the largest segments it can
1295
- * without going over this target using the durations of the individual audio frames
1296
- */
1297
- segmentDurationSeconds: number;
1298
- /**
1299
- * By default, the program date time or event start time will be based on the
1300
- * timestamp of the first video packet received by Norsk in a stream.
1301
- *
1302
- * Assuming minimal latency in Norsk itself, this behaviour is fine - but encodes and composition
1303
- * or synchronisation with external streams can then result in players requesting segments that don't exist yet
1304
- *
1305
- * delayOutputMs can be used to push the timestamp forwards so that players can calculate the edge of the stream accurately.
1306
- *
1307
- * This number should match the delayOutputMs of other streams which will be served within the same master playlist
1308
- */
1309
- delayOutputMs?: number;
1310
- /**
1311
- * The destination {@link CMAFDestinationSettings} for this stream to be published to
1284
+ * A list of destinations {@link CMAFDestinationSettings} for this stream to be published to
1312
1285
  */
1313
- destination: CMAFDestinationSettings;
1286
+ destinations: CMAFDestinationSettings[];
1314
1287
  }
1315
1288
 
1316
1289
  /**
@@ -1359,6 +1332,13 @@ export declare interface HlsTsCombinedPushOutputSettings extends SinkNodeSetting
1359
1332
  * see: {@link NorskOutput.hlsTsVideo}
1360
1333
  */
1361
1334
  export declare class HlsTsVideoOutputNode extends CommonHlsNode<HlsTsVideoMessage, "video", HlsTsVideoOutputNode> {
1335
+ /**
1336
+ * @public
1337
+ * Updates the credentials for a specific destination within this output by id
1338
+ * see: {@link UpdateCredentials}
1339
+ * see: {@link CMAFDestinationSettings}
1340
+ */
1341
+ updateCredentials(settings: UpdateCredentials): void;
1362
1342
  }
1363
1343
 
1364
1344
  /**
@@ -1384,87 +1364,10 @@ export declare interface HlsTsVideoOutputSettings extends SinkNodeSettings<HlsTs
1384
1364
  * This number should match the delayOutputMs of other streams which will be served within the same master playlist
1385
1365
  */
1386
1366
  delayOutputMs?: number;
1387
- }
1388
-
1389
- /**
1390
- * @public
1391
- * see: {@link NorskOutput.hlsTsVideoPush}
1392
- */
1393
- export declare class HlsTsVideoPushOutputNode extends CommonHlsNode<HlsTsVideoPushMessage, "video", HlsTsVideoOutputNode> {
1394
- }
1395
-
1396
- /**
1397
- * @public
1398
- * Settings for a HLS Transport Stream Video Push Output
1399
- * see {@link NorskOutput.hlsTsVideoPush}
1400
- */
1401
- export declare interface HlsTsVideoPushOutputSettings extends SinkNodeSettings<HlsTsVideoPushOutputNode> {
1402
- /**
1403
- * The target segment duration in seconds. Norsk will use the framerate of the stream in order
1404
- * to produce compliant segments that are less than or equal to this in duration
1405
- */
1406
- segmentDurationSeconds: number;
1407
- /**
1408
- * By default, the program date time or event start time will be based on the
1409
- * timestamp of the first video packet received by Norsk in a stream.
1410
- *
1411
- * Assuming minimal latency in Norsk itself, this behaviour is fine - but encodes and composition
1412
- * or synchronisation with external streams can then result in players requesting segments that don't exist yet
1413
- *
1414
- * delayOutputMs can be used to push the timestamp forwards so that players can calculate the edge of the stream accurately.
1415
- *
1416
- * This number should match the delayOutputMs of other streams which will be served within the same master playlist
1417
- */
1418
- delayOutputMs?: number;
1419
1367
  /**
1420
- * The destination {@link CMAFDestinationSettings} for this stream to be published to
1421
- */
1422
- destination: CMAFDestinationSettings;
1423
- }
1424
-
1425
- /**
1426
- * @public
1427
- * see: {@link NorskOutput.hlsWebVttPush}
1428
- */
1429
- export declare class HlsWebVttPushOutputNode extends CommonHlsNode<HlsWebVttPushMessage, "subtitle", HlsWebVttPushOutputNode> {
1430
- }
1431
-
1432
- /** @public */
1433
- export declare interface HlsWebVttPushOutputSettings extends SinkNodeSettings<HlsWebVttPushOutputNode> {
1434
- /**
1435
- * The target segment duration in seconds, Norsk will split subtitles over multiple segments
1436
- * in a compliant manner if necessary
1437
- */
1438
- segmentDurationSeconds: number;
1439
- /**
1440
- * By default, the program date time or event start time will be based on the
1441
- * timestamp of the first video packet received by Norsk in a stream.
1442
- *
1443
- * Assuming minimal latency in Norsk itself, this behaviour is fine - but encodes and composition
1444
- * or synchronisation with external streams can then result in players requesting segments that don't exist yet
1445
- *
1446
- * delayOutputMs can be used to push the timestamp forwards so that players can calculate the edge of the stream accurately.
1447
- *
1448
- * This number should match the delayOutputMs of other streams which will be served within the same master playlist
1449
- */
1450
- delayOutputMs?: number;
1451
- /**
1452
- * The destination {@link CMAFDestinationSettings} for this stream to be published to
1453
- */
1454
- destination: CMAFDestinationSettings;
1455
- /**
1456
- * How long to retain data for this playlist (this information can end up in the playlist to let the client know
1457
- * what the availability window is, for example)
1458
- */
1459
- retentionPeriodSeconds: number;
1460
- /**
1461
- * A local directory in which to store the segments while they're available
1462
- */
1463
- hlsCacheDirectory: string;
1464
- /**
1465
- * The maximum number of segments to display in a single generated playlist
1368
+ * A list of destinations {@link CMAFDestinationSettings} for this stream to be published to
1466
1369
  */
1467
- maximumPlaylistSegments: number;
1370
+ destinations: CMAFDestinationSettings[];
1468
1371
  }
1469
1372
 
1470
1373
  /** @public */
@@ -1555,6 +1458,11 @@ export declare function mkSine(freq: number): Wave;
1555
1458
  export declare interface MultiStreamStatistics {
1556
1459
  allStreams: SingleStreamStatistics[];
1557
1460
  sampleSizeSeconds: number;
1461
+ /**
1462
+ * Either `"default"`, if there is only one direction, or `"input"`/`"output"`
1463
+ * (for duplex nodes, where there are two directions)
1464
+ */
1465
+ label: string;
1558
1466
  total: StreamStatistics;
1559
1467
  audio: StreamStatistics;
1560
1468
  video: StreamStatistics;
@@ -1772,6 +1680,9 @@ export declare interface NorskDuplex {
1772
1680
  webRtcBrowser(settings: WebRTCBrowserSettings): Promise<WebRTCBrowserNode>;
1773
1681
  }
1774
1682
 
1683
+ /** @public */
1684
+ export declare function norskHost(): string;
1685
+
1775
1686
  /**
1776
1687
  * @public
1777
1688
  * Methods that allow you to ingest media into your application
@@ -1884,16 +1795,10 @@ export declare interface NorskOutput {
1884
1795
  * @param settings - Configuration for the CMAF Master Manifest
1885
1796
  */
1886
1797
  cmafMaster(settings: CmafMasterOutputSettings): Promise<CmafMasterOutputNode>;
1887
- /**
1888
- * Produces WebVTT segments with the supplied settings for use in
1889
- * HLS or DASH manifests and pushes them to the configured location
1890
- *
1891
- * @param settings - Configuration for the CMAF WebVTT Stream
1892
- */
1893
- hlsWebVttPush(settings: HlsWebVttPushOutputSettings): Promise<HlsWebVttPushOutputNode>;
1894
1798
  /**
1895
1799
  * Produces Transport Stream video segments with the supplied settings for use in
1896
1800
  * HLS manifests and builds a playlist served locally from the Norsk Web Server
1801
+ * or from other locations - see {@link CMAFDestinationSettings}
1897
1802
  *
1898
1803
  * @param settings - Configuration for the HLS TS Stream
1899
1804
  */
@@ -1901,24 +1806,11 @@ export declare interface NorskOutput {
1901
1806
  /**
1902
1807
  * Produces Transport Stream audio segments with the supplied settings for use in
1903
1808
  * HLS manifests and builds a playlist served locally from the Norsk Web Server
1809
+ * or from other locations - see {@link CMAFDestinationSettings}
1904
1810
  *
1905
1811
  * @param settings - Configuration for the HLS TS Stream
1906
1812
  */
1907
1813
  hlsTsAudio(settings: HlsTsAudioOutputSettings): Promise<HlsTsAudioOutputNode>;
1908
- /**
1909
- * Produces Transport Stream video segments with the supplied settings for use in
1910
- * HLS manifests and pushes them to the configured location (see {@link CMAFDestinationSettings})
1911
- *
1912
- * @param settings - Configuration for the HLS TS Stream
1913
- */
1914
- hlsTsVideoPush(settings: HlsTsVideoPushOutputSettings): Promise<HlsTsVideoPushOutputNode>;
1915
- /**
1916
- * Produces Transport Stream audio segments with the supplied settings for use in
1917
- * HLS manifests and pushes them to the configured location (see {@link CMAFDestinationSettings})
1918
- *
1919
- * @param settings - Configuration for the HLS TS Stream
1920
- */
1921
- hlsTsAudioPush(settings: HlsTsAudioPushOutputSettings): Promise<HlsTsAudioPushOutputNode>;
1922
1814
  /**
1923
1815
  * Produces Transport Stream segments containing both video and audio with the supplied settings for use in
1924
1816
  * HLS manifests and pushes them to the configured location (see {@link CMAFDestinationSettings})
@@ -1926,13 +1818,6 @@ export declare interface NorskOutput {
1926
1818
  * @param settings - Configuration for the HLS TS Stream
1927
1819
  */
1928
1820
  hlsTsCombinedPush(settings: HlsTsCombinedPushOutputSettings): Promise<HlsTsCombinedPushOutputNode>;
1929
- /**
1930
- * Produces a HLS master manifest for a collection of media streams
1931
- * and pushes it to the specified location, see {@link CMAFDestinationSettings}
1932
- *
1933
- * @param settings - Configuration for the HLS Master Manifest
1934
- */
1935
- hlsMasterPush(settings: HlsMasterPushOutputSettings): Promise<HlsMasterPushOutputNode>;
1936
1821
  /**
1937
1822
  * Produces a Transport Stream optionally containing both video and audio
1938
1823
  * and sends it out over UDP
@@ -1985,6 +1870,9 @@ export declare interface NorskOutput {
1985
1870
  fileMp4(settings: FileMp4OutputSettings): Promise<FileMp4OutputNode>;
1986
1871
  }
1987
1872
 
1873
+ /** @public */
1874
+ export declare function norskPort(): string;
1875
+
1988
1876
  /** @public */
1989
1877
  export declare class NorskProcessor {
1990
1878
  /**
@@ -2136,9 +2024,9 @@ export declare interface NorskTransform {
2136
2024
  /**
2137
2025
  * Override bitrate and language metadata on streams.
2138
2026
  *
2139
- * Audio and video bitrate metadata is required for playlists for both
2140
- * {@link NorskOutput.cmafMaster} and {@link NorskOutput.hlsMasterPush}
2141
- * nodes. It is automatically configured for some sources (like RTMP) and in
2027
+ * Audio and video bitrate metadata is required for playlists for the
2028
+ * {@link NorskOutput.cmafMaster} node.
2029
+ * It is automatically configured for some sources (like RTMP) and in
2142
2030
  * cases where re-encoding is done, but is unset for other sources (like SRT).
2143
2031
  * @param settings - Bitrate and language metadata plus general node settings.
2144
2032
  */
@@ -2393,6 +2281,9 @@ declare class ProcessorMediaNode<Pins extends string> {
2393
2281
  export declare interface ProcessorNodeSettings<T extends MediaNodeState> extends SourceNodeSettings<T> {
2394
2282
  }
2395
2283
 
2284
+ /** @public */
2285
+ export declare function publicUrlPrefix(): string;
2286
+
2396
2287
  /** @public */
2397
2288
  export declare type ReceiveFromAddress<Pins extends string> = {
2398
2289
  source: SourceMediaNode;
@@ -2471,6 +2362,8 @@ export declare interface RtmpServerInputSettings extends SourceNodeSettings<Rtmp
2471
2362
  * @eventProperty
2472
2363
  */
2473
2364
  onConnection?: (
2365
+ /** The connection ID, unique to this RtmpServer node */
2366
+ connectionId: string,
2474
2367
  /** The RTMP "app" field from the connection string */
2475
2368
  app: string,
2476
2369
  /** The full URL of the RTMP connection string */
@@ -2485,6 +2378,8 @@ export declare interface RtmpServerInputSettings extends SourceNodeSettings<Rtmp
2485
2378
  * @eventProperty
2486
2379
  */
2487
2380
  onStream?: (
2381
+ /** The connection ID, unique to this RtmpServer node */
2382
+ connectionId: string,
2488
2383
  /** The RTMP "app" field from the connection string */
2489
2384
  app: string,
2490
2385
  /** The full URL of the RTMP connection string */
@@ -2498,6 +2393,8 @@ export declare interface RtmpServerInputSettings extends SourceNodeSettings<Rtmp
2498
2393
  * @eventProperty
2499
2394
  */
2500
2395
  onConnectionStatusChange?: (
2396
+ /** The connection ID, unique to this RtmpServer node */
2397
+ connectionId: string,
2501
2398
  /** The new connection state */
2502
2399
  status: RtmpServerInputStatus,
2503
2400
  /** The audio and video stream keys that were present in the stream at the time of the status change */
@@ -2505,6 +2402,16 @@ export declare interface RtmpServerInputSettings extends SourceNodeSettings<Rtmp
2505
2402
  audioStreamKey: StreamKey_2;
2506
2403
  videoStreamKey: StreamKey_2;
2507
2404
  }[]) => void;
2405
+ onConnectionError?: (
2406
+ /** The connection ID, unique to this RtmpServer node */
2407
+ connectionId: string,
2408
+ /** The error */
2409
+ error: RtmpError_UnsupportedVideo | RtmpError_UnsupportedAudio) => void;
2410
+ onConnectionBytesRead?: (
2411
+ /** The connection ID, unique to this RtmpServer node */
2412
+ connectionId: string,
2413
+ /** The number of bytes read, as reported by the peer */
2414
+ bytesRead: bigint) => void;
2508
2415
  }
2509
2416
 
2510
2417
  /** @public */
@@ -1,6 +1,6 @@
1
1
  import * as grpc from "@grpc/grpc-js";
2
2
  import { MediaClient } from "@norskvideo/norsk-api/lib/media_grpc_pb";
3
- import { TsInputEvent, StreamKey as StreamKeyPB, Wave, FileTsInputMessage, UdpTsInputMessage, TimestampProgramNudge } from "@norskvideo/norsk-api/lib/media_pb";
3
+ import { TsInputEvent, StreamKey as StreamKeyPB, Wave, FileTsInputMessage, UdpTsInputMessage, TimestampProgramNudge, RtmpError_UnsupportedVideo, RtmpError_UnsupportedAudio } from "@norskvideo/norsk-api/lib/media_pb";
4
4
  import { BrowserEvent, ChannelLayout, RtmpServerInputStatus, RtpLinearPcmBitDepth, SampleFormat, SampleRate, SrtMode, SrtInputStatus, ImageFormat } from "./types";
5
5
  import { FrameRate } from "../types";
6
6
  import { DeckLinkPixelFormat, DeckLinkVideoConnection, DeckLinkDisplayModeId } from "../types";
@@ -136,6 +136,8 @@ export interface RtmpServerInputSettings extends SourceNodeSettings<RtmpServerIn
136
136
  * @eventProperty
137
137
  */
138
138
  onConnection?: (
139
+ /** The connection ID, unique to this RtmpServer node */
140
+ connectionId: string,
139
141
  /** The RTMP "app" field from the connection string */
140
142
  app: string,
141
143
  /** The full URL of the RTMP connection string */
@@ -150,6 +152,8 @@ export interface RtmpServerInputSettings extends SourceNodeSettings<RtmpServerIn
150
152
  * @eventProperty
151
153
  */
152
154
  onStream?: (
155
+ /** The connection ID, unique to this RtmpServer node */
156
+ connectionId: string,
153
157
  /** The RTMP "app" field from the connection string */
154
158
  app: string,
155
159
  /** The full URL of the RTMP connection string */
@@ -163,6 +167,8 @@ export interface RtmpServerInputSettings extends SourceNodeSettings<RtmpServerIn
163
167
  * @eventProperty
164
168
  */
165
169
  onConnectionStatusChange?: (
170
+ /** The connection ID, unique to this RtmpServer node */
171
+ connectionId: string,
166
172
  /** The new connection state */
167
173
  status: RtmpServerInputStatus,
168
174
  /** The audio and video stream keys that were present in the stream at the time of the status change */
@@ -170,6 +176,16 @@ export interface RtmpServerInputSettings extends SourceNodeSettings<RtmpServerIn
170
176
  audioStreamKey: StreamKeyPB;
171
177
  videoStreamKey: StreamKeyPB;
172
178
  }[]) => void;
179
+ onConnectionError?: (
180
+ /** The connection ID, unique to this RtmpServer node */
181
+ connectionId: string,
182
+ /** The error */
183
+ error: RtmpError_UnsupportedVideo | RtmpError_UnsupportedAudio) => void;
184
+ onConnectionBytesRead?: (
185
+ /** The connection ID, unique to this RtmpServer node */
186
+ connectionId: string,
187
+ /** The number of bytes read, as reported by the peer */
188
+ bytesRead: bigint) => void;
173
189
  }
174
190
  /**
175
191
  * @public
@@ -183,7 +183,7 @@ class RtmpServerInputNode extends common_1.SourceMediaNode {
183
183
  this.grpcStream.write(new media_pb_1.RtmpServerInputMessage((0, utils_1.mkMessageCase)({ initialConfig: config })));
184
184
  this.initialised = new Promise((resolve, reject) => {
185
185
  this.grpcStream.on("data", (data) => {
186
- var _a, _b;
186
+ var _a, _b, _c, _d, _e;
187
187
  switch (data.message.case) {
188
188
  case undefined:
189
189
  break;
@@ -195,8 +195,9 @@ class RtmpServerInputNode extends common_1.SourceMediaNode {
195
195
  }
196
196
  case "onConnection": {
197
197
  let connection = data.message.value;
198
+ let cid = (0, utils_1.mandatory)((_a = data.message.value.connectionId) === null || _a === void 0 ? void 0 : _a.id);
198
199
  let cb = settings.onConnection || ((_app, _url) => ({ accept: true }));
199
- let res = cb(connection.app, connection.url);
200
+ let res = cb(cid, connection.app, connection.url);
200
201
  let response = new media_pb_1.RtmpServerInputMessage();
201
202
  if (res.accept == true) {
202
203
  response.message = {
@@ -220,8 +221,9 @@ class RtmpServerInputNode extends common_1.SourceMediaNode {
220
221
  }
221
222
  case "onStream": {
222
223
  let stream = data.message.value;
224
+ let cid = (0, utils_1.mandatory)((_b = data.message.value.connectionId) === null || _b === void 0 ? void 0 : _b.id);
223
225
  let res = settings.onStream
224
- ? settings.onStream(stream.app, stream.url, stream.streamId, stream.publishingName)
226
+ ? settings.onStream(cid, stream.app, stream.url, stream.streamId, stream.publishingName)
225
227
  : {
226
228
  accept: true,
227
229
  audioStreamKey: {},
@@ -250,12 +252,8 @@ class RtmpServerInputNode extends common_1.SourceMediaNode {
250
252
  });
251
253
  }
252
254
  };
253
- let id = (_a = stream.connectionId) === null || _a === void 0 ? void 0 : _a.id;
254
255
  let response = new media_pb_1.RtmpServerInputMessage();
255
- if (id === undefined) {
256
- throw new Error("Undefined id on stream connection");
257
- }
258
- else if (res.accept == true) {
256
+ if (res.accept == true) {
259
257
  let audioStreamKey = defaultStreamKey(1)(res.audioStreamKey);
260
258
  let videoStreamKey = defaultStreamKey(2)(res.videoStreamKey);
261
259
  response.message = {
@@ -267,9 +265,9 @@ class RtmpServerInputNode extends common_1.SourceMediaNode {
267
265
  videoStreamKey,
268
266
  }),
269
267
  };
270
- this.connections.set(id, [
268
+ this.connections.set(cid, [
271
269
  { videoStreamKey, audioStreamKey },
272
- ...(this.connections.get(id) || []),
270
+ ...(this.connections.get(cid) || []),
273
271
  ]);
274
272
  }
275
273
  else {
@@ -286,11 +284,9 @@ class RtmpServerInputNode extends common_1.SourceMediaNode {
286
284
  break;
287
285
  }
288
286
  case "status": {
289
- let id = (_b = data.message.value.connectionId) === null || _b === void 0 ? void 0 : _b.id;
290
- if (id === undefined)
291
- throw new Error("Missing id on stream status");
287
+ let cid = (0, utils_1.mandatory)((_c = data.message.value.connectionId) === null || _c === void 0 ? void 0 : _c.id);
292
288
  settings.onConnectionStatusChange &&
293
- settings.onConnectionStatusChange((0, types_1.fromRtmpServerInputState)(data.message.value.state), this.connections.get(id) || []);
289
+ settings.onConnectionStatusChange(cid, (0, types_1.fromRtmpServerInputState)(data.message.value.state), this.connections.get(cid) || []);
294
290
  break;
295
291
  }
296
292
  case "outboundContext": {
@@ -303,6 +299,43 @@ class RtmpServerInputNode extends common_1.SourceMediaNode {
303
299
  settings.onStreamStatistics((0, types_1.fromStreamStatistics)(data.message.value, this.outputStreams));
304
300
  break;
305
301
  }
302
+ case "error": {
303
+ let cid = (0, utils_1.mandatory)((_d = data.message.value.connectionId) === null || _d === void 0 ? void 0 : _d.id);
304
+ if (settings.onConnectionError) {
305
+ settings.onConnectionError(cid, (0, utils_1.mandatory)(data.message.value.error.value));
306
+ }
307
+ else {
308
+ var message = "";
309
+ switch (data.message.value.error.case) {
310
+ case "unsupportedVideo": {
311
+ message =
312
+ "Unsupported video format: " +
313
+ data.message.value.error.value.type;
314
+ break;
315
+ }
316
+ case "unsupportedAudio": {
317
+ message =
318
+ "Unsupported audio format: " +
319
+ data.message.value.error.value.type;
320
+ break;
321
+ }
322
+ case undefined:
323
+ break;
324
+ default:
325
+ const exhaustiveCheck = data.message.value.error;
326
+ throw new Error(`Unhandled case: ${exhaustiveCheck}`);
327
+ }
328
+ (0, utils_1.debuglog)("RtmpServerInput Node '%s' received error '%s' on connection '%s'", this.id, message, cid);
329
+ }
330
+ break;
331
+ }
332
+ case "bytesRead": {
333
+ let cid = (0, utils_1.mandatory)((_e = data.message.value.connectionId) === null || _e === void 0 ? void 0 : _e.id);
334
+ if (settings.onConnectionBytesRead) {
335
+ settings.onConnectionBytesRead(cid, data.message.value.bytesRead);
336
+ }
337
+ break;
338
+ }
306
339
  default:
307
340
  const exhaustiveCheck = data.message;
308
341
  throw new Error(`Unhandled case: ${exhaustiveCheck}`);