@observertc/observer-js 1.0.0-beta.5 → 1.0.0-beta.7

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.
package/dist/index.d.ts CHANGED
@@ -1340,6 +1340,25 @@ type CalculatedScore = {
1340
1340
 
1341
1341
  type MediaKind = 'audio' | 'video';
1342
1342
 
1343
+ declare class ObservedMediaPlayout implements MediaPlayoutStats {
1344
+ timestamp: number;
1345
+ id: string;
1346
+ kind: MediaKind;
1347
+ private readonly _peerConnection;
1348
+ private _visited;
1349
+ appData?: Record<string, unknown>;
1350
+ synthesizedSamplesDuration?: number | undefined;
1351
+ synthesizedSamplesEvents?: number | undefined;
1352
+ totalSamplesDuration?: number | undefined;
1353
+ totalPlayoutDelay?: number | undefined;
1354
+ totalSamplesCount?: number | undefined;
1355
+ attachments?: Record<string, unknown> | undefined;
1356
+ constructor(timestamp: number, id: string, kind: MediaKind, _peerConnection: ObservedPeerConnection);
1357
+ get visited(): boolean;
1358
+ getPeerConnection(): ObservedPeerConnection;
1359
+ update(stats: MediaPlayoutStats): void;
1360
+ }
1361
+
1343
1362
  declare class ObservedMediaSource implements MediaSourceStats {
1344
1363
  timestamp: number;
1345
1364
  id: string;
@@ -1579,91 +1598,6 @@ declare class ObservedOutboundRtp implements OutboundRtpStats {
1579
1598
  update(stats: OutboundRtpStats): void;
1580
1599
  }
1581
1600
 
1582
- type InboundAudioTrackReport = {
1583
- trackId: string;
1584
- fractionLostDistribution: {
1585
- lt001: number;
1586
- lt005: number;
1587
- lt010: number;
1588
- lt020: number;
1589
- lt050: number;
1590
- gtOrEq050: number;
1591
- count: number;
1592
- sum: number;
1593
- };
1594
- };
1595
- type InboundVideoTrackReport = {
1596
- trackId: string;
1597
- fractionLostDistribution: {
1598
- lt001: number;
1599
- lt005: number;
1600
- lt010: number;
1601
- lt020: number;
1602
- lt050: number;
1603
- gtOrEq050: number;
1604
- count: number;
1605
- sum: number;
1606
- };
1607
- };
1608
- type OutboundAudioTrackReport = {
1609
- trackId: string;
1610
- };
1611
- type OutboundVideoTrackReport = {
1612
- trackId: string;
1613
- };
1614
- type InboundTrackReport = ({
1615
- kind: 'audio';
1616
- } & InboundAudioTrackReport) | ({
1617
- kind: 'video';
1618
- } & InboundVideoTrackReport);
1619
- type OutboundTrackReport = ({
1620
- kind: 'audio';
1621
- } & OutboundAudioTrackReport) | ({
1622
- kind: 'video';
1623
- } & OutboundVideoTrackReport);
1624
- type TrackReport = ({
1625
- direction: 'inbound';
1626
- } & InboundTrackReport) | ({
1627
- direction: 'outbound';
1628
- } & OutboundTrackReport);
1629
- type ClientReport = {
1630
- callId: string;
1631
- clientId: string;
1632
- totalDataChannelBytesReceived: number;
1633
- totalDataChannelBytesSent: number;
1634
- totalDataChannelMessagesReceived: number;
1635
- totalDataChannelMessagesSent: number;
1636
- totalInboundRtpPacketsReceived: number;
1637
- totalInboundRtpPacketsLost: number;
1638
- totalInboundRtpBytesReceived: number;
1639
- totalOutboundRtpPacketsSent: number;
1640
- totalOutboundRtpBytesSent: number;
1641
- totalAudioBytesReceived: number;
1642
- totalVideoBytesReceived: number;
1643
- totalAudioBytesSent: number;
1644
- totalVideoBytesSent: number;
1645
- totalNumberOfIssues: number;
1646
- issues: Record<string, number>;
1647
- rttDistribution: {
1648
- lt50ms: number;
1649
- lt150ms: number;
1650
- lt300ms: number;
1651
- gtOrEq300ms: number;
1652
- count: number;
1653
- sum: number;
1654
- };
1655
- scoreDistribution: {
1656
- '0': number;
1657
- '1': number;
1658
- '2': number;
1659
- '3': number;
1660
- '4': number;
1661
- '5': number;
1662
- count: number;
1663
- sum: number;
1664
- };
1665
- };
1666
-
1667
1601
  declare class ObservedOutboundTrack implements OutboundTrackSample {
1668
1602
  timestamp: number;
1669
1603
  readonly id: string;
@@ -1673,7 +1607,7 @@ declare class ObservedOutboundTrack implements OutboundTrackSample {
1673
1607
  private readonly _mediaSource?;
1674
1608
  private _visited;
1675
1609
  appData?: Record<string, unknown>;
1676
- readonly report: OutboundTrackReport;
1610
+ readonly remoteInboundTracks: Set<ObservedInboundTrack>;
1677
1611
  readonly calculatedScore: CalculatedScore;
1678
1612
  addedAt?: number | undefined;
1679
1613
  removedAt?: number | undefined;
@@ -1685,29 +1619,9 @@ declare class ObservedOutboundTrack implements OutboundTrackSample {
1685
1619
  getPeerConnection(): ObservedPeerConnection;
1686
1620
  getOutboundRtps(): ObservedOutboundRtp[] | undefined;
1687
1621
  getMediaSource(): ObservedMediaSource | undefined;
1688
- getRemoteInboundTracks(): ObservedInboundTrack[] | undefined;
1689
1622
  update(stats: OutboundTrackSample): void;
1690
1623
  }
1691
1624
 
1692
- declare class ObservedMediaPlayout implements MediaPlayoutStats {
1693
- timestamp: number;
1694
- id: string;
1695
- kind: MediaKind;
1696
- private readonly _peerConnection;
1697
- private _visited;
1698
- appData?: Record<string, unknown>;
1699
- synthesizedSamplesDuration?: number | undefined;
1700
- synthesizedSamplesEvents?: number | undefined;
1701
- totalSamplesDuration?: number | undefined;
1702
- totalPlayoutDelay?: number | undefined;
1703
- totalSamplesCount?: number | undefined;
1704
- attachments?: Record<string, unknown> | undefined;
1705
- constructor(timestamp: number, id: string, kind: MediaKind, _peerConnection: ObservedPeerConnection);
1706
- get visited(): boolean;
1707
- getPeerConnection(): ObservedPeerConnection;
1708
- update(stats: MediaPlayoutStats): void;
1709
- }
1710
-
1711
1625
  declare class ObservedInboundTrack implements InboundTrackSample {
1712
1626
  timestamp: number;
1713
1627
  readonly id: string;
@@ -1717,7 +1631,7 @@ declare class ObservedInboundTrack implements InboundTrackSample {
1717
1631
  private readonly _mediaPlayout?;
1718
1632
  readonly calculatedScore: CalculatedScore;
1719
1633
  appData?: Record<string, unknown>;
1720
- report: InboundTrackReport;
1634
+ remoteOutboundTrack?: ObservedOutboundTrack | undefined;
1721
1635
  private _visited;
1722
1636
  addedAt?: number | undefined;
1723
1637
  removedAt?: number | undefined;
@@ -1729,7 +1643,6 @@ declare class ObservedInboundTrack implements InboundTrackSample {
1729
1643
  getPeerConnection(): ObservedPeerConnection;
1730
1644
  getInboundRtp(): ObservedInboundRtp | undefined;
1731
1645
  getMediaPlayout(): ObservedMediaPlayout | undefined;
1732
- getRemoteOutboundTrack(): ObservedOutboundTrack | undefined;
1733
1646
  update(stats: InboundTrackSample): void;
1734
1647
  }
1735
1648
 
@@ -2237,9 +2150,6 @@ type ObserverEvents = {
2237
2150
  'client-event': [ObservedClientScope & {
2238
2151
  event: ClientEvent;
2239
2152
  }];
2240
- 'client-track-report': [ObservedClientScope & {
2241
- report: TrackReport;
2242
- }];
2243
2153
  'peer-connection-added': [ObservedPeerConnectionScope];
2244
2154
  'peer-connection-updated': [ObservedPeerConnectionScope];
2245
2155
  'peer-connection-closed': [ObservedPeerConnectionScope];
@@ -2479,7 +2389,6 @@ declare class ObservedClient<AppData extends Record<string, unknown> = Record<st
2479
2389
  deltaNumberOfIssues: number;
2480
2390
  totalScoreSum: number;
2481
2391
  numberOfScoreMeasurements: number;
2482
- readonly report: ClientReport;
2483
2392
  readonly mediaDevices: MediaDeviceInfo[];
2484
2393
  issues: ClientIssue[];
2485
2394
  private _injections;
@@ -2508,9 +2417,49 @@ interface ScoreCalculator {
2508
2417
  update(): void;
2509
2418
  }
2510
2419
 
2511
- interface RemoteTrackResolver {
2420
+ type RemoteTrackResolverFactory = (observedCall: ObservedCall) => RemoteTrackResolver;
2421
+ /**
2422
+ * Strategy functions that map a track to its publish/subscribe identity. Two tracks are linked
2423
+ * when a subscribed (inbound) track's **publisher id** equals a published (outbound) track's
2424
+ * **publisher id** — one publisher → many subscribers. The **subscriber id** is optional and is
2425
+ * only used to look an inbound track up via `getInboundTrackBySubscriberId`.
2426
+ *
2427
+ * The "publisher id" is whatever a strategy uses as the link key: mediasoup passes its producerId,
2428
+ * a p2p strategy the SSRC, a generic strategy a shared attachment value.
2429
+ */
2430
+ type RemoteTrackResolvers = {
2431
+ /** The publisher id a subscribed (inbound) track receives. Required — this is the link key. */
2432
+ resolveInboundTrackPublisherId: (inboundTrack: ObservedInboundTrack) => string | undefined;
2433
+ /** The publisher id a published (outbound) track represents. Required — this is the link key. */
2434
+ resolveOutboundTrackPublisherId: (outboundTrack: ObservedOutboundTrack) => string | undefined;
2435
+ /** Optional: the inbound track's own subscription id (enables `getInboundTrackBySubscriberId`). */
2436
+ resolveInboundTrackSubscriberId?: (inboundTrack: ObservedInboundTrack) => string | undefined;
2437
+ };
2438
+ /**
2439
+ * Generic, strategy-driven base resolver. It subscribes to the Observer bus (filtered to one call),
2440
+ * links subscribed↔published tracks by publisher id, and maintains the links directly on the tracks
2441
+ * (`inboundTrack.remoteOutboundTrack`, `outboundTrack.remoteInboundTracks`).
2442
+ *
2443
+ * Concrete strategies (mediasoup, p2p-by-SSRC, generic attachment) are just different
2444
+ * {@link RemoteTrackResolvers} passed to this class. Ids are re-resolved on demand rather than
2445
+ * cached, so the only state kept is the two lookup indexes that back the public getters.
2446
+ */
2447
+ declare class RemoteTrackResolver {
2448
+ readonly observedCall: ObservedCall;
2449
+ private readonly resolvers;
2450
+ private readonly _publisherIdToOutboundTrack;
2451
+ private readonly _subscriberIdToInboundTrack;
2452
+ constructor(observedCall: ObservedCall, resolvers: RemoteTrackResolvers);
2453
+ /** The published (outbound) track for a publisher id, if any. */
2454
+ getOutboundTrackByPublisherId(publisherId: string): ObservedOutboundTrack | undefined;
2455
+ /** The subscribed (inbound) track for a subscriber id, if the strategy resolves subscriber ids. */
2456
+ getInboundTrackBySubscriberId(subscriberId: string): ObservedInboundTrack | undefined;
2512
2457
  resolveRemoteOutboundTrack(inboundTrack: ObservedInboundTrack): ObservedOutboundTrack | undefined;
2513
2458
  resolveRemoteInboundTracks(outboundTrack: ObservedOutboundTrack): ObservedInboundTrack[] | undefined;
2459
+ private _addInboundTrack;
2460
+ private _removeInboundTrack;
2461
+ private _addOutboundTrack;
2462
+ private _removeOutboundTrack;
2514
2463
  }
2515
2464
 
2516
2465
  interface Updater {
@@ -2536,16 +2485,11 @@ declare class Detectors {
2536
2485
  }
2537
2486
 
2538
2487
  type ObservedCallUpdateConfig = {
2539
- updatePolicy: 'update-on-interval';
2540
- updateIntervalInMs: number;
2541
- } | {
2542
2488
  updatePolicy?: 'update-on-any-client-updated' | 'update-when-all-client-updated';
2543
- updateIntervalInMs?: number;
2544
2489
  };
2545
2490
  type ObservedCallSettings<AppData extends Record<string, unknown> = Record<string, unknown>> = ObservedCallUpdateConfig & {
2546
2491
  callId: string;
2547
2492
  appData?: AppData;
2548
- remoteTrackResolvePolicy?: 'p2p' | 'mediasoup-sfu' | 'none';
2549
2493
  closeCallIfEmptyForMs?: number;
2550
2494
  };
2551
2495
  type ObservedCallEvents = {
@@ -2606,6 +2550,22 @@ declare class ObservedCall<AppData extends Record<string, unknown> = Record<stri
2606
2550
  private _notify;
2607
2551
  }
2608
2552
 
2553
+ type Middleware<T> = (input: T, next: (nextInput: T) => void) => void;
2554
+ interface Processor<T> {
2555
+ finalCallback?: Callback<T>;
2556
+ process(value: T): void;
2557
+ addMiddleware(...middlewares: Middleware<T>[]): Processor<T>;
2558
+ removeMiddleware(...middlewares: Middleware<T>[]): Processor<T>;
2559
+ }
2560
+ type Callback<T> = (input: T) => void;
2561
+ declare class MiddlewareProcessor<T> implements Processor<T> {
2562
+ private stack;
2563
+ finalCallback?: Callback<T>;
2564
+ addMiddleware(...middlewares: Middleware<T>[]): Processor<T>;
2565
+ removeMiddleware(...middlewares: Middleware<T>[]): Processor<T>;
2566
+ process(value: T): void;
2567
+ }
2568
+
2609
2569
  type SampleRejectedReason = 'observer-closed' | 'missing-callId' | 'missing-clientId';
2610
2570
 
2611
2571
  /**
@@ -2614,12 +2574,20 @@ type SampleRejectedReason = 'observer-closed' | 'missing-callId' | 'missing-clie
2614
2574
  * merged into the `appData` of entities created during the accept pass.
2615
2575
  */
2616
2576
  type AcceptContext = Record<string, unknown>;
2577
+ /** The payload threaded through `accept()` middlewares: the sample and its optional context. */
2578
+ type AcceptMiddlewarePayload = {
2579
+ sample: ClientSample;
2580
+ context?: AcceptContext;
2581
+ };
2582
+ /**
2583
+ * A global middleware run on every sample passed to `observer.accept()`, in registration order,
2584
+ * **before** the sample is dispatched to any call/client. It may inspect or mutate the sample
2585
+ * (e.g. set/normalize `callId`/`clientId`, enrich, redact) or the context, then call
2586
+ * `next(payload)` to continue the chain. Not calling `next` **drops** the sample.
2587
+ */
2588
+ type AcceptMiddleware = Middleware<AcceptMiddlewarePayload>;
2617
2589
  type ObserverUpdateConfig = {
2618
- updatePolicy: 'update-on-interval';
2619
- updateIntervalInMs: number;
2620
- } | {
2621
2590
  updatePolicy?: 'update-on-any-call-updated' | 'update-when-all-call-updated';
2622
- updateIntervalInMs?: number;
2623
2591
  };
2624
2592
  /** Produces the initial `appData` for a call created without an explicit `appData`. */
2625
2593
  type CallAppDataFactory = (params: {
@@ -2633,7 +2601,6 @@ type ClientAppDataFactory = (params: {
2633
2601
  }) => Record<string, unknown>;
2634
2602
  type ObserverConfig<AppData extends Record<string, unknown> = Record<string, unknown>> = ObserverUpdateConfig & {
2635
2603
  defaultCallUpdatePolicy?: ObservedCallSettings['updatePolicy'];
2636
- defaultCallUpdateIntervalInMs?: number;
2637
2604
  appData?: AppData;
2638
2605
  closeClientIfIdleForMs?: number;
2639
2606
  closeCallIfEmptyForMs?: number;
@@ -2651,6 +2618,13 @@ type ObserverConfig<AppData extends Record<string, unknown> = Record<string, unk
2651
2618
  * can be derived from `callId` / `clientId`.
2652
2619
  */
2653
2620
  createClientSink?: ClientSampleSinkFactory;
2621
+ /**
2622
+ * Optional factory invoked when a call is created, producing the call's `RemoteTrackResolver`
2623
+ * (or `undefined` for none). Use the built-ins
2624
+ * (`createDefaultMediasoupRemoteTrackResolverFactory()` / `createP2pRemoteTrackResolverFactory()`)
2625
+ * or build a `RemoteTrackResolver` with custom publisher/subscriber id resolvers.
2626
+ */
2627
+ createTrackResolver?: RemoteTrackResolverFactory;
2654
2628
  };
2655
2629
  declare interface Observer {
2656
2630
  on<U extends keyof ObserverEvents>(event: U, listener: (...args: ObserverEvents[U]) => void): this;
@@ -2674,7 +2648,8 @@ declare class Observer<AppData extends Record<string, unknown> = Record<string,
2674
2648
  numberOfOutboundRtpStreams: number;
2675
2649
  numberOfDataChannels: number;
2676
2650
  numberOfPeerConnections: number;
2677
- private _timer?;
2651
+ /** Global, pre-dispatch middleware chain run on every accepted sample. */
2652
+ readonly acceptMiddlewares: MiddlewareProcessor<AcceptMiddlewarePayload>;
2678
2653
  constructor(config?: ObserverConfig<AppData>);
2679
2654
  get numberOfCalls(): number;
2680
2655
  get appData(): AppData | undefined;
@@ -2790,6 +2765,7 @@ declare class InMemorySink extends ClientSampleSink {
2790
2765
  }
2791
2766
  declare function createInMemorySink(samples?: ClientSample[]): InMemorySink;
2792
2767
 
2793
- type Middleware<T> = (input: T, next: (nextInput: T) => void) => void;
2768
+ declare function createDefaultMediasoupRemoteTrackResolverFactory(): RemoteTrackResolverFactory;
2769
+ declare function createP2pRemoteTrackResolverFactory(): RemoteTrackResolverFactory;
2794
2770
 
2795
- export { type AcceptContext, type CallAppDataFactory, type ClientAppDataFactory, type ClientEvent, ClientEventTypes, type ClientIssue, type ClientMetaData, ClientMetaTypes, type ClientReport, type ClientSample, ClientSampleSink, type ClientSampleSinkEvents, type ClientSampleSinkFactory, type Detector, Detectors, InMemorySink, JsonlFileSink, type JsonlFileSinkFactoryOptions, type JsonlFileSinkOptions, type Logger, type Middleware, ObservedCall, type ObservedCallScope, ObservedCertificate, ObservedClient, type ObservedClientScope, ObservedCodec, ObservedDataChannel, ObservedIceCandidate, ObservedIceCandidatePair, ObservedIceTransport, ObservedInboundRtp, ObservedInboundTrack, ObservedMediaPlayout, ObservedMediaSource, ObservedOutboundRtp, ObservedOutboundTrack, ObservedPeerConnection, type ObservedPeerConnectionScope, ObservedPeerConnectionTransport, ObservedRemoteInboundRtp, ObservedRemoteOutboundRtp, Observer, type ObserverEventBase, type ObserverEvents, type ObserverLogger, type SampleRejectedReason, type ScoreCalculator, type TrackReport, createInMemorySink, createJsonlFileSink, createJsonlFileSinkFactory, createLogger, setObserverLogger };
2771
+ export { type AcceptContext, type AcceptMiddleware, type AcceptMiddlewarePayload, type CallAppDataFactory, type ClientAppDataFactory, type ClientEvent, ClientEventTypes, type ClientIssue, type ClientMetaData, ClientMetaTypes, type ClientSample, ClientSampleSink, type ClientSampleSinkEvents, type ClientSampleSinkFactory, type Detector, Detectors, InMemorySink, JsonlFileSink, type JsonlFileSinkFactoryOptions, type JsonlFileSinkOptions, type Logger, type Middleware, ObservedCall, type ObservedCallScope, ObservedCertificate, ObservedClient, type ObservedClientScope, ObservedCodec, ObservedDataChannel, ObservedIceCandidate, ObservedIceCandidatePair, ObservedIceTransport, ObservedInboundRtp, ObservedInboundTrack, ObservedMediaPlayout, ObservedMediaSource, ObservedOutboundRtp, ObservedOutboundTrack, ObservedPeerConnection, type ObservedPeerConnectionScope, ObservedPeerConnectionTransport, ObservedRemoteInboundRtp, ObservedRemoteOutboundRtp, Observer, type ObserverEventBase, type ObserverEvents, type ObserverLogger, RemoteTrackResolver, type RemoteTrackResolverFactory, type RemoteTrackResolvers, type SampleRejectedReason, type ScoreCalculator, createDefaultMediasoupRemoteTrackResolverFactory, createInMemorySink, createJsonlFileSink, createJsonlFileSinkFactory, createLogger, createP2pRemoteTrackResolverFactory, setObserverLogger };