@observertc/observer-js 0.9.27-beta → 0.30.0-e12fcb4.0

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.
Files changed (298) hide show
  1. package/lib/ObservedCall.d.ts +54 -0
  2. package/lib/ObservedCall.d.ts.map +1 -0
  3. package/lib/ObservedCall.js +166 -0
  4. package/lib/ObservedClient.d.ts +73 -0
  5. package/lib/ObservedClient.d.ts.map +1 -0
  6. package/lib/ObservedClient.js +487 -0
  7. package/lib/ObservedInboundTrack.d.ts +65 -0
  8. package/lib/ObservedInboundTrack.d.ts.map +1 -0
  9. package/lib/ObservedInboundTrack.js +192 -0
  10. package/lib/ObservedOutboundTrack.d.ts +55 -0
  11. package/lib/ObservedOutboundTrack.d.ts.map +1 -0
  12. package/lib/ObservedOutboundTrack.js +166 -0
  13. package/lib/ObservedPeerConnection.d.ts +57 -0
  14. package/lib/ObservedPeerConnection.d.ts.map +1 -0
  15. package/lib/ObservedPeerConnection.js +217 -0
  16. package/lib/Observer.d.ts +26 -1465
  17. package/lib/Observer.d.ts.map +1 -1
  18. package/lib/Observer.js +53 -605
  19. package/lib/{sinks/ObserverSink.d.ts → ReportsCollector.d.ts} +7 -23
  20. package/lib/ReportsCollector.d.ts.map +1 -0
  21. package/lib/{sinks/ObserverSink.js → ReportsCollector.js} +27 -85
  22. package/lib/common/ReportsCollector.d.ts +21 -24
  23. package/lib/common/ReportsCollector.d.ts.map +1 -1
  24. package/lib/common/ReportsCollector.js +24 -0
  25. package/lib/common/SingleExecutor.d.ts +3 -0
  26. package/lib/common/SingleExecutor.d.ts.map +1 -0
  27. package/lib/common/SingleExecutor.js +31 -0
  28. package/lib/common/TypedEventEmitter.d.ts +22 -0
  29. package/lib/common/TypedEventEmitter.d.ts.map +1 -0
  30. package/lib/common/TypedEventEmitter.js +11 -0
  31. package/lib/common/callEventReports.d.ts.map +1 -0
  32. package/lib/common/logger.d.ts +3 -9
  33. package/lib/common/logger.d.ts.map +1 -1
  34. package/lib/common/logger.js +58 -141
  35. package/lib/common/types.d.ts +2 -14
  36. package/lib/common/types.d.ts.map +1 -1
  37. package/lib/common/utils.d.ts +1 -0
  38. package/lib/common/utils.d.ts.map +1 -1
  39. package/lib/common/utils.js +6 -1
  40. package/lib/index.d.ts +8 -19
  41. package/lib/index.d.ts.map +1 -1
  42. package/lib/index.js +7 -2
  43. package/package.json +1 -1
  44. package/src/ObservedCall.ts +201 -0
  45. package/src/ObservedClient.ts +681 -0
  46. package/src/ObservedInboundTrack.ts +238 -0
  47. package/src/ObservedOutboundTrack.ts +205 -0
  48. package/src/ObservedPeerConnection.ts +249 -0
  49. package/src/Observer.ts +86 -442
  50. package/src/{sinks/ObserverSink.ts → ReportsCollector.ts} +29 -94
  51. package/src/common/ReportsCollector.ts +48 -23
  52. package/src/common/SingleExecutor.ts +36 -0
  53. package/src/common/TypedEventEmitter.ts +32 -0
  54. package/src/common/logger.ts +58 -161
  55. package/src/common/types.ts +4 -24
  56. package/src/common/utils.ts +6 -0
  57. package/src/index.ts +12 -23
  58. package/lib/Evaluator.d.ts +0 -43
  59. package/lib/Evaluator.d.ts.map +0 -1
  60. package/lib/Evaluator.js +0 -171
  61. package/lib/common/Semaphore.d.ts +0 -31
  62. package/lib/common/Semaphore.d.ts.map +0 -1
  63. package/lib/common/Semaphore.js +0 -16
  64. package/lib/entries/CallEntry.d.ts +0 -619
  65. package/lib/entries/CallEntry.d.ts.map +0 -1
  66. package/lib/entries/CallEntry.js +0 -75
  67. package/lib/entries/ClientEntry.d.ts +0 -478
  68. package/lib/entries/ClientEntry.d.ts.map +0 -1
  69. package/lib/entries/ClientEntry.js +0 -114
  70. package/lib/entries/InboundTrackEntry.d.ts +0 -682
  71. package/lib/entries/InboundTrackEntry.d.ts.map +0 -1
  72. package/lib/entries/InboundTrackEntry.js +0 -76
  73. package/lib/entries/OutboundTrackEntry.d.ts +0 -682
  74. package/lib/entries/OutboundTrackEntry.d.ts.map +0 -1
  75. package/lib/entries/OutboundTrackEntry.js +0 -73
  76. package/lib/entries/PeerConnectionEntry.d.ts +0 -505
  77. package/lib/entries/PeerConnectionEntry.d.ts.map +0 -1
  78. package/lib/entries/PeerConnectionEntry.js +0 -144
  79. package/lib/entries/SfuEntry.d.ts +0 -150
  80. package/lib/entries/SfuEntry.d.ts.map +0 -1
  81. package/lib/entries/SfuEntry.js +0 -77
  82. package/lib/entries/SfuInboundRtpPadEntry.d.ts +0 -14
  83. package/lib/entries/SfuInboundRtpPadEntry.d.ts.map +0 -1
  84. package/lib/entries/SfuInboundRtpPadEntry.js +0 -49
  85. package/lib/entries/SfuOutboundRtpPadEntry.d.ts +0 -14
  86. package/lib/entries/SfuOutboundRtpPadEntry.d.ts.map +0 -1
  87. package/lib/entries/SfuOutboundRtpPadEntry.js +0 -47
  88. package/lib/entries/SfuSctpChannelEntry.d.ts +0 -12
  89. package/lib/entries/SfuSctpChannelEntry.d.ts.map +0 -1
  90. package/lib/entries/SfuSctpChannelEntry.js +0 -43
  91. package/lib/entries/SfuTransportEntry.d.ts +0 -82
  92. package/lib/entries/SfuTransportEntry.d.ts.map +0 -1
  93. package/lib/entries/SfuTransportEntry.js +0 -122
  94. package/lib/evaluators/SetClientsCoordinateEvaluator.d.ts +0 -9
  95. package/lib/evaluators/SetClientsCoordinateEvaluator.d.ts.map +0 -1
  96. package/lib/evaluators/SetClientsCoordinateEvaluator.js +0 -95
  97. package/lib/middlewares/CallOperationsContext.d.ts +0 -18
  98. package/lib/middlewares/CallOperationsContext.d.ts.map +0 -1
  99. package/lib/middlewares/CallOperationsContext.js +0 -27
  100. package/lib/middlewares/CallProcessor.d.ts +0 -6
  101. package/lib/middlewares/CallProcessor.d.ts.map +0 -1
  102. package/lib/middlewares/CallProcessor.js +0 -36
  103. package/lib/middlewares/CommitTransactionMiddleware.d.ts +0 -6
  104. package/lib/middlewares/CommitTransactionMiddleware.d.ts.map +0 -1
  105. package/lib/middlewares/CommitTransactionMiddleware.js +0 -179
  106. package/lib/middlewares/DeleteOutdatedCallEntries.d.ts +0 -6
  107. package/lib/middlewares/DeleteOutdatedCallEntries.d.ts.map +0 -1
  108. package/lib/middlewares/DeleteOutdatedCallEntries.js +0 -121
  109. package/lib/middlewares/DeleteOutdatedSfuEntries.d.ts +0 -6
  110. package/lib/middlewares/DeleteOutdatedSfuEntries.d.ts.map +0 -1
  111. package/lib/middlewares/DeleteOutdatedSfuEntries.js +0 -127
  112. package/lib/middlewares/Middleware.d.ts +0 -3
  113. package/lib/middlewares/Middleware.d.ts.map +0 -1
  114. package/lib/middlewares/Middleware.js +0 -21
  115. package/lib/middlewares/Processor.d.ts +0 -9
  116. package/lib/middlewares/Processor.d.ts.map +0 -1
  117. package/lib/middlewares/Processor.js +0 -54
  118. package/lib/middlewares/TransactionContext.d.ts +0 -35
  119. package/lib/middlewares/TransactionContext.d.ts.map +0 -1
  120. package/lib/middlewares/TransactionContext.js +0 -90
  121. package/lib/middlewares/TransactoinProcessor.d.ts +0 -6
  122. package/lib/middlewares/TransactoinProcessor.d.ts.map +0 -1
  123. package/lib/middlewares/TransactoinProcessor.js +0 -17
  124. package/lib/middlewares/VisitObservedCallsMiddleware.d.ts +0 -7
  125. package/lib/middlewares/VisitObservedCallsMiddleware.d.ts.map +0 -1
  126. package/lib/middlewares/VisitObservedCallsMiddleware.js +0 -96
  127. package/lib/middlewares/VisitObservedSfusMiddleware.d.ts +0 -6
  128. package/lib/middlewares/VisitObservedSfusMiddleware.d.ts.map +0 -1
  129. package/lib/middlewares/VisitObservedSfusMiddleware.js +0 -151
  130. package/lib/middlewares/visitors/visitClient.d.ts +0 -5
  131. package/lib/middlewares/visitors/visitClient.d.ts.map +0 -1
  132. package/lib/middlewares/visitors/visitClient.js +0 -174
  133. package/lib/middlewares/visitors/visitInboundAudioTrack.d.ts +0 -5
  134. package/lib/middlewares/visitors/visitInboundAudioTrack.d.ts.map +0 -1
  135. package/lib/middlewares/visitors/visitInboundAudioTrack.js +0 -93
  136. package/lib/middlewares/visitors/visitInboundVideoTrack.d.ts +0 -5
  137. package/lib/middlewares/visitors/visitInboundVideoTrack.d.ts.map +0 -1
  138. package/lib/middlewares/visitors/visitInboundVideoTrack.js +0 -94
  139. package/lib/middlewares/visitors/visitOutboundAudioTrack.d.ts +0 -5
  140. package/lib/middlewares/visitors/visitOutboundAudioTrack.d.ts.map +0 -1
  141. package/lib/middlewares/visitors/visitOutboundAudioTrack.js +0 -90
  142. package/lib/middlewares/visitors/visitOutboundVideoTarck.d.ts +0 -5
  143. package/lib/middlewares/visitors/visitOutboundVideoTarck.d.ts.map +0 -1
  144. package/lib/middlewares/visitors/visitOutboundVideoTarck.js +0 -90
  145. package/lib/middlewares/visitors/visitPeerConnection.d.ts +0 -5
  146. package/lib/middlewares/visitors/visitPeerConnection.d.ts.map +0 -1
  147. package/lib/middlewares/visitors/visitPeerConnection.js +0 -111
  148. package/lib/middlewares/visitors/visitSfu.d.ts +0 -5
  149. package/lib/middlewares/visitors/visitSfu.d.ts.map +0 -1
  150. package/lib/middlewares/visitors/visitSfu.js +0 -78
  151. package/lib/middlewares/visitors/visitSfuInboundRtpPad.d.ts +0 -5
  152. package/lib/middlewares/visitors/visitSfuInboundRtpPad.d.ts.map +0 -1
  153. package/lib/middlewares/visitors/visitSfuInboundRtpPad.js +0 -56
  154. package/lib/middlewares/visitors/visitSfuOutboundRtpPad.d.ts +0 -5
  155. package/lib/middlewares/visitors/visitSfuOutboundRtpPad.d.ts.map +0 -1
  156. package/lib/middlewares/visitors/visitSfuOutboundRtpPad.js +0 -56
  157. package/lib/middlewares/visitors/visitSfuSctpChannel.d.ts +0 -5
  158. package/lib/middlewares/visitors/visitSfuSctpChannel.d.ts.map +0 -1
  159. package/lib/middlewares/visitors/visitSfuSctpChannel.js +0 -55
  160. package/lib/middlewares/visitors/visitSfuTransport.d.ts +0 -5
  161. package/lib/middlewares/visitors/visitSfuTransport.d.ts.map +0 -1
  162. package/lib/middlewares/visitors/visitSfuTransport.js +0 -56
  163. package/lib/processes/closePeerConnectionProcess.d.ts +0 -10
  164. package/lib/processes/closePeerConnectionProcess.d.ts.map +0 -1
  165. package/lib/processes/closePeerConnectionProcess.js +0 -51
  166. package/lib/processes/detachClientProcess.d.ts +0 -14
  167. package/lib/processes/detachClientProcess.d.ts.map +0 -1
  168. package/lib/processes/detachClientProcess.js +0 -106
  169. package/lib/processes/findRemoteMatches.d.ts +0 -9
  170. package/lib/processes/findRemoteMatches.d.ts.map +0 -1
  171. package/lib/processes/findRemoteMatches.js +0 -96
  172. package/lib/processes/inboundTrackRemoved.d.ts +0 -9
  173. package/lib/processes/inboundTrackRemoved.d.ts.map +0 -1
  174. package/lib/processes/inboundTrackRemoved.js +0 -22
  175. package/lib/processes/joinClientProcess.d.ts +0 -11
  176. package/lib/processes/joinClientProcess.d.ts.map +0 -1
  177. package/lib/processes/joinClientProcess.js +0 -120
  178. package/lib/processes/outboundTrackRemoved.d.ts +0 -9
  179. package/lib/processes/outboundTrackRemoved.d.ts.map +0 -1
  180. package/lib/processes/outboundTrackRemoved.js +0 -22
  181. package/lib/samples/ObservedCall.d.ts +0 -17
  182. package/lib/samples/ObservedCall.d.ts.map +0 -1
  183. package/lib/samples/ObservedCall.js +0 -29
  184. package/lib/samples/ObservedCalls.d.ts +0 -19
  185. package/lib/samples/ObservedCalls.d.ts.map +0 -1
  186. package/lib/samples/ObservedCalls.js +0 -113
  187. package/lib/samples/ObservedClient.d.ts +0 -28
  188. package/lib/samples/ObservedClient.d.ts.map +0 -1
  189. package/lib/samples/ObservedClient.js +0 -110
  190. package/lib/samples/ObservedInboundAudioTrack.d.ts +0 -17
  191. package/lib/samples/ObservedInboundAudioTrack.d.ts.map +0 -1
  192. package/lib/samples/ObservedInboundAudioTrack.js +0 -17
  193. package/lib/samples/ObservedInboundVideoTrack.d.ts +0 -17
  194. package/lib/samples/ObservedInboundVideoTrack.d.ts.map +0 -1
  195. package/lib/samples/ObservedInboundVideoTrack.js +0 -17
  196. package/lib/samples/ObservedOutboundAudioTrack.d.ts +0 -16
  197. package/lib/samples/ObservedOutboundAudioTrack.d.ts.map +0 -1
  198. package/lib/samples/ObservedOutboundAudioTrack.js +0 -17
  199. package/lib/samples/ObservedOutboundVideoTrack.d.ts +0 -16
  200. package/lib/samples/ObservedOutboundVideoTrack.d.ts.map +0 -1
  201. package/lib/samples/ObservedOutboundVideoTrack.js +0 -17
  202. package/lib/samples/ObservedPeerConnection.d.ts +0 -47
  203. package/lib/samples/ObservedPeerConnection.d.ts.map +0 -1
  204. package/lib/samples/ObservedPeerConnection.js +0 -130
  205. package/lib/samples/ObservedSfu.d.ts +0 -27
  206. package/lib/samples/ObservedSfu.d.ts.map +0 -1
  207. package/lib/samples/ObservedSfu.js +0 -65
  208. package/lib/samples/ObservedSfuInboundRtpPad.d.ts +0 -15
  209. package/lib/samples/ObservedSfuInboundRtpPad.d.ts.map +0 -1
  210. package/lib/samples/ObservedSfuInboundRtpPad.js +0 -17
  211. package/lib/samples/ObservedSfuOutboundRtpPad.d.ts +0 -15
  212. package/lib/samples/ObservedSfuOutboundRtpPad.d.ts.map +0 -1
  213. package/lib/samples/ObservedSfuOutboundRtpPad.js +0 -17
  214. package/lib/samples/ObservedSfuSctpChannel.d.ts +0 -15
  215. package/lib/samples/ObservedSfuSctpChannel.d.ts.map +0 -1
  216. package/lib/samples/ObservedSfuSctpChannel.js +0 -17
  217. package/lib/samples/ObservedSfuTransport.d.ts +0 -30
  218. package/lib/samples/ObservedSfuTransport.d.ts.map +0 -1
  219. package/lib/samples/ObservedSfuTransport.js +0 -86
  220. package/lib/samples/ObservedSfus.d.ts +0 -16
  221. package/lib/samples/ObservedSfus.d.ts.map +0 -1
  222. package/lib/samples/ObservedSfus.js +0 -72
  223. package/lib/sinks/ObserverSink.d.ts.map +0 -1
  224. package/lib/sinks/callEventReports.d.ts.map +0 -1
  225. package/lib/sources/ObservedCallSource.d.ts +0 -18
  226. package/lib/sources/ObservedCallSource.d.ts.map +0 -1
  227. package/lib/sources/ObservedCallSource.js +0 -2
  228. package/lib/sources/ObservedClientSource.d.ts +0 -19
  229. package/lib/sources/ObservedClientSource.d.ts.map +0 -1
  230. package/lib/sources/ObservedClientSource.js +0 -2
  231. package/lib/sources/ObservedSfuSource.d.ts +0 -15
  232. package/lib/sources/ObservedSfuSource.d.ts.map +0 -1
  233. package/lib/sources/ObservedSfuSource.js +0 -2
  234. package/lib/sources/Sources.d.ts +0 -49
  235. package/lib/sources/Sources.d.ts.map +0 -1
  236. package/lib/sources/Sources.js +0 -213
  237. package/src/Evaluator.ts +0 -229
  238. package/src/common/Semaphore.ts +0 -45
  239. package/src/entries/CallEntry.ts +0 -62
  240. package/src/entries/ClientEntry.ts +0 -106
  241. package/src/entries/InboundTrackEntry.ts +0 -74
  242. package/src/entries/OutboundTrackEntry.ts +0 -72
  243. package/src/entries/PeerConnectionEntry.ts +0 -133
  244. package/src/entries/SfuEntry.ts +0 -62
  245. package/src/entries/SfuInboundRtpPadEntry.ts +0 -46
  246. package/src/entries/SfuOutboundRtpPadEntry.ts +0 -44
  247. package/src/entries/SfuSctpChannelEntry.ts +0 -39
  248. package/src/entries/SfuTransportEntry.ts +0 -109
  249. package/src/evaluators/SetClientsCoordinateEvaluator.ts +0 -78
  250. package/src/middlewares/CallOperationsContext.ts +0 -56
  251. package/src/middlewares/CallProcessor.ts +0 -38
  252. package/src/middlewares/CommitTransactionMiddleware.ts +0 -328
  253. package/src/middlewares/DeleteOutdatedCallEntries.ts +0 -159
  254. package/src/middlewares/DeleteOutdatedSfuEntries.ts +0 -168
  255. package/src/middlewares/Middleware.ts +0 -10
  256. package/src/middlewares/Processor.ts +0 -59
  257. package/src/middlewares/TransactionContext.ts +0 -176
  258. package/src/middlewares/TransactoinProcessor.ts +0 -28
  259. package/src/middlewares/VisitObservedCallsMiddleware.ts +0 -172
  260. package/src/middlewares/VisitObservedSfusMiddleware.ts +0 -203
  261. package/src/middlewares/visitors/visitClient.ts +0 -239
  262. package/src/middlewares/visitors/visitInboundAudioTrack.ts +0 -113
  263. package/src/middlewares/visitors/visitInboundVideoTrack.ts +0 -117
  264. package/src/middlewares/visitors/visitOutboundAudioTrack.ts +0 -100
  265. package/src/middlewares/visitors/visitOutboundVideoTarck.ts +0 -102
  266. package/src/middlewares/visitors/visitPeerConnection.ts +0 -151
  267. package/src/middlewares/visitors/visitSfu.ts +0 -70
  268. package/src/middlewares/visitors/visitSfuInboundRtpPad.ts +0 -52
  269. package/src/middlewares/visitors/visitSfuOutboundRtpPad.ts +0 -53
  270. package/src/middlewares/visitors/visitSfuSctpChannel.ts +0 -50
  271. package/src/middlewares/visitors/visitSfuTransport.ts +0 -50
  272. package/src/processes/closePeerConnectionProcess.ts +0 -54
  273. package/src/processes/detachClientProcess.ts +0 -136
  274. package/src/processes/findRemoteMatches.ts +0 -104
  275. package/src/processes/inboundTrackRemoved.ts +0 -22
  276. package/src/processes/joinClientProcess.ts +0 -138
  277. package/src/processes/outboundTrackRemoved.ts +0 -22
  278. package/src/samples/ObservedCall.ts +0 -49
  279. package/src/samples/ObservedCalls.ts +0 -143
  280. package/src/samples/ObservedClient.ts +0 -172
  281. package/src/samples/ObservedInboundAudioTrack.ts +0 -35
  282. package/src/samples/ObservedInboundVideoTrack.ts +0 -36
  283. package/src/samples/ObservedOutboundAudioTrack.ts +0 -35
  284. package/src/samples/ObservedOutboundVideoTrack.ts +0 -35
  285. package/src/samples/ObservedPeerConnection.ts +0 -227
  286. package/src/samples/ObservedSfu.ts +0 -115
  287. package/src/samples/ObservedSfuInboundRtpPad.ts +0 -35
  288. package/src/samples/ObservedSfuOutboundRtpPad.ts +0 -35
  289. package/src/samples/ObservedSfuSctpChannel.ts +0 -35
  290. package/src/samples/ObservedSfuTransport.ts +0 -142
  291. package/src/samples/ObservedSfus.ts +0 -95
  292. package/src/sources/ObservedCallSource.ts +0 -26
  293. package/src/sources/ObservedClientSource.ts +0 -28
  294. package/src/sources/ObservedSfuSource.ts +0 -19
  295. package/src/sources/Sources.ts +0 -301
  296. /package/lib/{sinks → common}/callEventReports.d.ts +0 -0
  297. /package/lib/{sinks → common}/callEventReports.js +0 -0
  298. /package/src/{sinks → common}/callEventReports.ts +0 -0
@@ -0,0 +1,238 @@
1
+ import { EventEmitter } from 'events';
2
+ import { StorageProvider } from './storages/StorageProvider';
3
+ import * as Models from './models/Models';
4
+ import { ObservedPeerConnection } from './ObservedPeerConnection';
5
+ import { InboundAudioTrack, InboundVideoTrack } from '@observertc/sample-schemas-js';
6
+ import { ObservedOutboundTrack } from './ObservedOutboundTrack';
7
+ import { InboundAudioTrackReport, InboundVideoTrackReport } from '@observertc/report-schemas-js';
8
+ import { MediaKind } from './common/types';
9
+ import { createSingleExecutor } from './common/SingleExecutor';
10
+
11
+ export type ObservedInboundTrackConfig<K extends MediaKind> = {
12
+ trackId: string;
13
+ kind: K;
14
+ sfuStreamId?: string;
15
+ sfuSinkId?: string;
16
+ }
17
+
18
+ export type ObservedInboundTrackEvents<K extends MediaKind> = {
19
+ update: [],
20
+ close: [],
21
+ remoteoutboundtrack: [ObservedOutboundTrack<K>],
22
+ };
23
+
24
+ export type ObservedInboundTrackStatsUpdate<K extends MediaKind> = K extends 'audio' ? InboundAudioTrack : InboundVideoTrack;
25
+
26
+ export type ObservedInboundTrackStats<K extends MediaKind> = ObservedInboundTrackStatsUpdate<K> & {
27
+ ssrc: number;
28
+ bitrate: number;
29
+ fractionLost: number;
30
+ rttInMs?: number;
31
+ };
32
+
33
+ // {
34
+ // [Property in keyof ObservedInboundTrackStats<K>]: ObservedInboundTrackStats<K>[Property];
35
+ // }
36
+
37
+ export declare interface ObservedInboundTrack<Kind extends MediaKind> {
38
+ on<U extends keyof ObservedInboundTrackEvents<Kind>>(event: U, listener: (...args: ObservedInboundTrackEvents<Kind>[U]) => void): this;
39
+ off<U extends keyof ObservedInboundTrackEvents<Kind>>(event: U, listener: (...args: ObservedInboundTrackEvents<Kind>[U]) => void): this;
40
+ once<U extends keyof ObservedInboundTrackEvents<Kind>>(event: U, listener: (...args: ObservedInboundTrackEvents<Kind>[U]) => void): this;
41
+ emit<U extends keyof ObservedInboundTrackEvents<Kind>>(event: U, ...args: ObservedInboundTrackEvents<Kind>[U]): boolean;
42
+ update(sample: ObservedInboundTrackStatsUpdate<Kind>, timestamp: number): void;
43
+ }
44
+
45
+ export class ObservedInboundTrack<Kind extends MediaKind> extends EventEmitter {
46
+ public static async create<K extends MediaKind>(
47
+ config: ObservedInboundTrackConfig<K>,
48
+ peerConnection: ObservedPeerConnection,
49
+ storageProvider: StorageProvider,
50
+ ) {
51
+ const model = new Models.InboundTrack({
52
+ serviceId: peerConnection.client.serviceId,
53
+ roomId: peerConnection.client.roomId,
54
+ callId: peerConnection.client.callId,
55
+ clientId: peerConnection.client.clientId,
56
+ mediaUnitId: peerConnection.client.mediaUnitId,
57
+ peerConnectionId: peerConnection.peerConnectionId,
58
+ trackId: config.trackId,
59
+ kind: config.kind,
60
+ sfuStreamId: config.sfuStreamId,
61
+ sfuSinkId: config.sfuSinkId,
62
+ });
63
+
64
+ const alreadyInserted = await storageProvider.inboundTrackStorage.insert(config.trackId, model);
65
+
66
+ if (alreadyInserted) throw new Error(`InboundAudioTrack with id ${config.trackId} already exists`);
67
+
68
+ return new ObservedInboundTrack<K>(model, peerConnection, storageProvider);
69
+ }
70
+
71
+ private readonly _stats = new Map<number, ObservedInboundTrackStats<Kind>>();
72
+ private readonly _execute = createSingleExecutor();
73
+
74
+ private _closed = false;
75
+ private _updated = Date.now();
76
+ private _remoteOutboundTrack?: ObservedOutboundTrack<Kind>;
77
+ public bitrate = -1;
78
+ public rttInMs = -1;
79
+
80
+ private constructor(
81
+ private readonly _model: Models.InboundTrack,
82
+ public readonly peerConnection: ObservedPeerConnection,
83
+ private readonly _storageProvider: StorageProvider,
84
+ ) {
85
+ super();
86
+ }
87
+
88
+ public get serviceId() {
89
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
90
+ return this._model.serviceId!;
91
+ }
92
+
93
+ public get roomId() {
94
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
95
+ return this._model.roomId!;
96
+ }
97
+
98
+ public get callId() {
99
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
100
+ return this._model.callId!;
101
+ }
102
+
103
+ public get clientId() {
104
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
105
+ return this._model.clientId!;
106
+ }
107
+
108
+ public get mediaUnitId() {
109
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
110
+ return this._model.mediaUnitId!;
111
+ }
112
+
113
+ public get peerConnectionId() {
114
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
115
+ return this._model.peerConnectionId!;
116
+ }
117
+
118
+ public get trackId() {
119
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
120
+ return this._model.trackId!;
121
+ }
122
+
123
+ public get kind(): Kind {
124
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
125
+ return this._model.kind! as Kind;
126
+ }
127
+
128
+ public get sfuStreamId() {
129
+ return this._model.sfuStreamId;
130
+ }
131
+
132
+ public get sfuSinkId() {
133
+ return this._model.sfuSinkId;
134
+ }
135
+
136
+ public get updated() {
137
+ return this._updated;
138
+ }
139
+
140
+ public get stats(): ReadonlyMap<number, ObservedInboundTrackStats<Kind>> {
141
+ return this._stats;
142
+ }
143
+
144
+ public get reports() {
145
+ return this.peerConnection.reports;
146
+ }
147
+
148
+ public set remoteOutboundTrack(track: ObservedOutboundTrack<Kind> | undefined) {
149
+ if (this._closed) return;
150
+ if (this._remoteOutboundTrack) return;
151
+ if (!track) return;
152
+ track?.once('close', () => {
153
+ this._remoteOutboundTrack = undefined;
154
+ });
155
+ this._remoteOutboundTrack = track;
156
+ this.emit('remoteoutboundtrack', track);
157
+ }
158
+
159
+ public get remoteOutboundTrack() {
160
+ return this._remoteOutboundTrack;
161
+ }
162
+
163
+ public get closed() {
164
+ return this._closed;
165
+ }
166
+
167
+ public close() {
168
+ if (this._closed) return;
169
+
170
+ this._closed = true;
171
+
172
+ this._execute(() => this._storageProvider.inboundTrackStorage.remove(this.trackId))
173
+ .catch(() => void 0)
174
+ .finally(() => this.emit('close'));
175
+ }
176
+
177
+ public async update(sample: ObservedInboundTrackStatsUpdate<Kind>, timestamp: number) {
178
+ if (this._closed) return;
179
+ let executeSave = false;
180
+
181
+ const report: InboundAudioTrackReport | InboundVideoTrackReport = {
182
+ serviceId: this.peerConnection.client.call.serviceId,
183
+ roomId: this.peerConnection.client.call.roomId,
184
+ callId: this.peerConnection.client.call.callId,
185
+ clientId: this.peerConnection.client.clientId,
186
+ userId: this.peerConnection.client.userId,
187
+ mediaUnitId: this.peerConnection.client.mediaUnitId,
188
+ peerConnectionId: this.peerConnection.peerConnectionId,
189
+ ...sample,
190
+ timestamp,
191
+ sampleSeq: -1,
192
+ };
193
+
194
+ if (this.kind === 'audio') this.reports.addInboundAudioTrackReport(report);
195
+ else if (this.kind === 'video') this.reports.addInboundVideoTrackReport(report);
196
+
197
+ if (!this._model.sfuStreamId && sample.sfuStreamId) {
198
+ this._model.sfuStreamId = sample.sfuStreamId;
199
+ executeSave = true;
200
+ }
201
+
202
+ if (!this._model.sfuSinkId && sample.sfuSinkId) {
203
+ this._model.sfuSinkId = sample.sfuSinkId;
204
+ executeSave = true;
205
+ }
206
+
207
+ const elapsedTimeInMs = Math.max(1, timestamp - this._updated);
208
+ const lastStat = this._stats.get(sample.ssrc);
209
+ const rttInMs = sample.roundTripTime ? sample.roundTripTime * 1000 : undefined;
210
+ const bitrate = ((sample.bytesReceived ?? 0) - (lastStat?.bytesReceived ?? 0)) * 8 / (elapsedTimeInMs / 1000);
211
+ const lostPackets = (sample.packetsLost ?? 0) - (lastStat?.packetsLost ?? 0);
212
+ const receivedPackets = (sample.packetsReceived ?? 0) - (lastStat?.packetsReceived ?? 0);
213
+ const fractionLost = 0 < receivedPackets && 0 < lostPackets ? (lostPackets / (receivedPackets + lostPackets)) : 0;
214
+ const stats: ObservedInboundTrackStats<Kind> = {
215
+ ...sample,
216
+ fractionLost,
217
+ rttInMs,
218
+ bitrate,
219
+ ssrc: sample.ssrc,
220
+ };
221
+
222
+ this._stats.set(sample.ssrc, stats);
223
+
224
+ this.bitrate = [ ...this._stats.values() ].reduce((acc, stat) => acc + stat.bitrate, 0);
225
+ this.rttInMs = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.rttInMs ?? 0), 0) / (this._stats.size || 1);
226
+
227
+ if (executeSave) await this._save();
228
+
229
+ this._updated = timestamp;
230
+ this.emit('update');
231
+ }
232
+
233
+ private async _save() {
234
+ if (this._closed) throw new Error(`OutboundTrack ${this.trackId} is closed`);
235
+
236
+ return this._storageProvider.inboundTrackStorage.set(this.trackId, this._model);
237
+ }
238
+ }
@@ -0,0 +1,205 @@
1
+ import { EventEmitter } from 'events';
2
+ import { StorageProvider } from './storages/StorageProvider';
3
+ import * as Models from './models/Models';
4
+ import { ObservedPeerConnection } from './ObservedPeerConnection';
5
+ import { OutboundAudioTrack, OutboundVideoTrack } from '@observertc/sample-schemas-js';
6
+ import { ObservedInboundTrack } from './ObservedInboundTrack';
7
+ import { OutboundAudioTrackReport, OutboundVideoTrackReport } from '@observertc/report-schemas-js';
8
+ import { MediaKind } from './common/types';
9
+ import { createSingleExecutor } from './common/SingleExecutor';
10
+
11
+ export type ObservedOutboundTrackConfig<K extends MediaKind> = {
12
+ trackId: string;
13
+ kind: K;
14
+ sfuStreamId?: string;
15
+ }
16
+
17
+ export type ObservedOutboundTrackEvents = {
18
+ update: [],
19
+ close: [],
20
+ };
21
+
22
+ export type ObservedOutboundTrackStatsUpdate<K extends MediaKind> = K extends 'audio' ? OutboundAudioTrack : OutboundVideoTrack;
23
+
24
+ export type ObservedOutboundTrackStats<K extends MediaKind> = ObservedOutboundTrackStatsUpdate<K> & {
25
+ ssrc: number;
26
+ bitrate: number;
27
+ rttInMs?: number;
28
+ };
29
+
30
+ // export type ObservedOutboundTrackStatsUpdate<K extends MediaKind> = {
31
+ // [Property in keyof ObservedOutboundTrackStats<K>]: ObservedOutboundTrackStats<K>[Property];
32
+ // }
33
+
34
+ export declare interface ObservedOutboundTrack<Kind extends MediaKind> {
35
+ on<U extends keyof ObservedOutboundTrackEvents>(event: U, listener: (...args: ObservedOutboundTrackEvents[U]) => void): this;
36
+ off<U extends keyof ObservedOutboundTrackEvents>(event: U, listener: (...args: ObservedOutboundTrackEvents[U]) => void): this;
37
+ once<U extends keyof ObservedOutboundTrackEvents>(event: U, listener: (...args: ObservedOutboundTrackEvents[U]) => void): this;
38
+ emit<U extends keyof ObservedOutboundTrackEvents>(event: U, ...args: ObservedOutboundTrackEvents[U]): boolean;
39
+ update(sample: ObservedOutboundTrackStatsUpdate<Kind>, timestamp: number): void;
40
+ }
41
+
42
+ export class ObservedOutboundTrack<Kind extends MediaKind> extends EventEmitter {
43
+ public static async create<K extends MediaKind>(
44
+ config: ObservedOutboundTrackConfig<K>,
45
+ peerConnection: ObservedPeerConnection,
46
+ storageProvider: StorageProvider,
47
+ ) {
48
+ const model = new Models.OutboundTrack({
49
+ serviceId: peerConnection.client.serviceId,
50
+ roomId: peerConnection.client.roomId,
51
+ callId: peerConnection.client.callId,
52
+ clientId: peerConnection.client.clientId,
53
+ mediaUnitId: peerConnection.client.mediaUnitId,
54
+ peerConnectionId: peerConnection.peerConnectionId,
55
+ trackId: config.trackId,
56
+ kind: config.kind,
57
+ sfuStreamId: config.sfuStreamId,
58
+ });
59
+
60
+ const alreadyInserted = await storageProvider.outboundTrackStorage.insert(config.trackId, model);
61
+
62
+ if (alreadyInserted) throw new Error(`OutboundAudioTrack with id ${config.trackId} already exists`);
63
+
64
+ return new ObservedOutboundTrack<K>(model, peerConnection, storageProvider);
65
+ }
66
+
67
+ public bitrate?: number;
68
+ public rttInMs?: number;
69
+
70
+ private readonly _stats = new Map<number, ObservedOutboundTrackStats<Kind>>();
71
+ private readonly _execute = createSingleExecutor();
72
+
73
+ private _closed = false;
74
+ private _updated = Date.now();
75
+ private _remoteInboundTracks = new Map<string, ObservedInboundTrack<Kind>>();
76
+
77
+ private constructor(
78
+ private readonly _model: Models.OutboundTrack,
79
+ public readonly peerConnection: ObservedPeerConnection,
80
+ private readonly _storageProvider: StorageProvider,
81
+ ) {
82
+ super();
83
+ }
84
+
85
+ public get kind(): Kind {
86
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
87
+ return this._model.kind! as Kind;
88
+ }
89
+
90
+ public get trackId() {
91
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
92
+ return this._model.trackId!;
93
+ }
94
+
95
+ public get sfuStreamId() {
96
+ return this._model.sfuStreamId;
97
+ }
98
+
99
+ public get closed() {
100
+ return this._closed;
101
+ }
102
+
103
+ public get remoteInboundTracks(): ReadonlyMap<string, ObservedInboundTrack<Kind>> {
104
+ return this._remoteInboundTracks;
105
+ }
106
+
107
+ public get reports() {
108
+ return this.peerConnection.reports;
109
+ }
110
+
111
+ public get updated() {
112
+ return this._updated;
113
+ }
114
+
115
+ public close() {
116
+ if (this._closed) return;
117
+
118
+ this._closed = true;
119
+
120
+ this._execute(() => this._storageProvider.inboundTrackStorage.remove(this.trackId))
121
+ .catch(() => void 0)
122
+ .finally(() => this.emit('close'));
123
+ }
124
+
125
+ public get stats(): ReadonlyMap<number, ObservedOutboundTrackStats<Kind>> {
126
+ return this._stats;
127
+ }
128
+
129
+ public async update(sample: ObservedOutboundTrackStatsUpdate<Kind>, timestamp: number): Promise<void> {
130
+ if (this._closed) return;
131
+ let executeSave = false;
132
+
133
+ const report: OutboundAudioTrackReport | OutboundVideoTrackReport = {
134
+ serviceId: this.peerConnection.client.serviceId,
135
+ roomId: this.peerConnection.client.call.roomId,
136
+ callId: this.peerConnection.client.call.callId,
137
+ clientId: this.peerConnection.client.clientId,
138
+ userId: this.peerConnection.client.userId,
139
+ mediaUnitId: this.peerConnection.client.mediaUnitId,
140
+ peerConnectionId: this.peerConnection.peerConnectionId,
141
+ ...sample,
142
+ timestamp,
143
+ sampleSeq: -1,
144
+ };
145
+
146
+ if (this.kind === 'audio') this.reports.addOutboundAudioTrackReport(report);
147
+ else if (this.kind === 'video') this.reports.addOutboundVideoTrackReport(report);
148
+
149
+ const elapsedTimeInMs = Math.max(1, timestamp - this._updated);
150
+ const lastStat = this._stats.get(sample.ssrc);
151
+ const rttInMs = sample.roundTripTime ? sample.roundTripTime * 1000 : undefined;
152
+ const bitrate = ((sample.bytesSent ?? 0) - (lastStat?.bytesSent ?? 0)) * 8 / (elapsedTimeInMs / 1000);
153
+ // const lostPackets = (sample.packetsLost ?? 0) - (lastStat?.packetsLost ?? 0);
154
+ // const sentPackets = (sample.packetsSent ?? 0) - (lastStat?.packetsSent ?? 0);
155
+ const stats: ObservedOutboundTrackStats<Kind> = {
156
+ ...sample,
157
+ rttInMs,
158
+ bitrate,
159
+ ssrc: sample.ssrc,
160
+ };
161
+
162
+ this._stats.set(sample.ssrc, stats);
163
+
164
+ this.bitrate = [ ...this._stats.values() ].reduce((acc, stat) => acc + stat.bitrate, 0);
165
+ this.rttInMs = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.rttInMs ?? 0), 0) / (this._stats.size || 1);
166
+
167
+ // setting up sfu connection as it is not always available at the first sample
168
+ if (sample.sfuStreamId && !this._model.sfuStreamId) {
169
+ this._model.sfuStreamId = sample.sfuStreamId;
170
+
171
+ this.once('close', () => {
172
+ if (!this._model.sfuStreamId) return;
173
+ if (this.kind === 'audio') this.peerConnection.client.call.sfuStreamIdToOutboundAudioTrack.delete(this._model.sfuStreamId);
174
+ else if (this.kind === 'video') this.peerConnection.client.call.sfuStreamIdToOutboundVideoTrack.delete(this._model.sfuStreamId);
175
+ });
176
+
177
+ if (this.kind === 'audio') this.peerConnection.client.call.sfuStreamIdToOutboundAudioTrack.set(this._model.sfuStreamId, this as ObservedOutboundTrack<'audio'>);
178
+ else if (this.kind === 'video') this.peerConnection.client.call.sfuStreamIdToOutboundVideoTrack.set(this._model.sfuStreamId, this as ObservedOutboundTrack<'video'>);
179
+
180
+ executeSave = true;
181
+ }
182
+
183
+ if (executeSave) await this._save();
184
+
185
+ this._updated = timestamp;
186
+ this.emit('update');
187
+ }
188
+
189
+ public connectInboundTrack(track: ObservedInboundTrack<Kind>) {
190
+ if (this._closed) return;
191
+
192
+ track.remoteOutboundTrack = this;
193
+ track.once('close', () => {
194
+ this._remoteInboundTracks.delete(track.trackId);
195
+ });
196
+
197
+ this._remoteInboundTracks.set(track.trackId, track);
198
+ }
199
+
200
+ private async _save() {
201
+ if (this._closed) throw new Error(`OutboundTrack ${this.trackId} is closed`);
202
+
203
+ return this._storageProvider.outboundTrackStorage.set(this.trackId, this._model);
204
+ }
205
+ }
@@ -0,0 +1,249 @@
1
+ import { EventEmitter } from 'events';
2
+ import * as Models from './models/Models';
3
+ import { StorageProvider } from './storages/StorageProvider';
4
+ import { PeerConnectionTransport } from '@observertc/sample-schemas-js';
5
+ import { ObservedClient } from './ObservedClient';
6
+ import { ObservedInboundTrack, ObservedInboundTrackConfig } from './ObservedInboundTrack';
7
+ import { ObservedOutboundTrack, ObservedOutboundTrackConfig } from './ObservedOutboundTrack';
8
+ import { PeerConnectionTransportReport } from '@observertc/report-schemas-js';
9
+ import { createSingleExecutor } from './common/SingleExecutor';
10
+
11
+ export type ObservedPeerConnectionEvents = {
12
+ update: [],
13
+ close: [],
14
+ newinboudaudiotrack: [ObservedInboundTrack<'audio'>],
15
+ newinboudvideotrack: [ObservedInboundTrack<'video'>],
16
+ newoutboundaudiotrack: [ObservedOutboundTrack<'audio'>],
17
+ newoutboundvideotrack: [ObservedOutboundTrack<'video'>],
18
+ };
19
+
20
+ export type ObservedPeerConnectionConfig = {
21
+ peerConnectionId: string;
22
+ };
23
+
24
+ export type ObservedPeerConnectionStats = Omit<PeerConnectionTransport, 'transportId' | 'label'>;
25
+
26
+ export declare interface ObservedPeerConnection {
27
+ on<U extends keyof ObservedPeerConnectionEvents>(event: U, listener: (...args: ObservedPeerConnectionEvents[U]) => void): this;
28
+ off<U extends keyof ObservedPeerConnectionEvents>(event: U, listener: (...args: ObservedPeerConnectionEvents[U]) => void): this;
29
+ once<U extends keyof ObservedPeerConnectionEvents>(event: U, listener: (...args: ObservedPeerConnectionEvents[U]) => void): this;
30
+ emit<U extends keyof ObservedPeerConnectionEvents>(event: U, ...args: ObservedPeerConnectionEvents[U]): boolean;
31
+ }
32
+
33
+ export class ObservedPeerConnection extends EventEmitter {
34
+ public static async create(
35
+ config: ObservedPeerConnectionConfig,
36
+ client: ObservedClient,
37
+ storageProvider: StorageProvider,
38
+ ): Promise<ObservedPeerConnection> {
39
+ const model = new Models.PeerConnection({
40
+ roomId: client.roomId,
41
+ serviceId: client.serviceId,
42
+ callId: client.callId,
43
+ clientId: client.clientId,
44
+ peerConnectionId: config.peerConnectionId,
45
+ });
46
+
47
+ const alreadyInserted = await storageProvider.peerConnectionStorage.insert(config.peerConnectionId, model);
48
+
49
+ if (alreadyInserted) throw new Error(`PeerConnection with id ${config.peerConnectionId} already exists`);
50
+
51
+ return new ObservedPeerConnection(model, client, storageProvider);
52
+ }
53
+
54
+ private _closed = false;
55
+ private _updated = Date.now();
56
+ private _sample?: ObservedPeerConnectionStats;
57
+
58
+ private readonly _inboundAudioTracks = new Map<string, ObservedInboundTrack<'audio'>>();
59
+ private readonly _inboundVideoTracks = new Map<string, ObservedInboundTrack<'video'>>();
60
+ private readonly _outboundAudioTracks = new Map<string, ObservedOutboundTrack<'audio'>>();
61
+ private readonly _outboundVideoTracks = new Map<string, ObservedOutboundTrack<'video'>>();
62
+ private readonly _execute = createSingleExecutor();
63
+
64
+ private constructor(
65
+ private readonly _model: Models.PeerConnection,
66
+ public readonly client: ObservedClient,
67
+ private readonly _storageProvider: StorageProvider,
68
+ ) {
69
+ super();
70
+ }
71
+
72
+ public get peerConnectionId(): string {
73
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
74
+ return this._model.peerConnectionId!;
75
+ }
76
+
77
+ public get reports() {
78
+ return this.client.reports;
79
+ }
80
+
81
+ public get stats(): ObservedPeerConnectionStats | undefined {
82
+ return this._sample;
83
+ }
84
+
85
+ public get updated(): number {
86
+ return this._updated;
87
+ }
88
+
89
+ public get inboundAudioTracks(): ReadonlyMap<string, ObservedInboundTrack<'audio'>> {
90
+ return this._inboundAudioTracks;
91
+ }
92
+
93
+ public get inboundVideoTracks(): ReadonlyMap<string, ObservedInboundTrack<'video'>> {
94
+ return this._inboundVideoTracks;
95
+ }
96
+
97
+ public get outboundAudioTracks(): ReadonlyMap<string, ObservedOutboundTrack<'audio'>> {
98
+ return this._outboundAudioTracks;
99
+ }
100
+
101
+ public get outboundVideoTracks(): ReadonlyMap<string, ObservedOutboundTrack<'video'>> {
102
+ return this._outboundVideoTracks;
103
+ }
104
+
105
+ public get closed() {
106
+ return this._closed;
107
+ }
108
+
109
+ public close() {
110
+ if (this._closed) return;
111
+ this._closed = true;
112
+
113
+ Array.from(this._inboundAudioTracks.values()).forEach((track) => track.close());
114
+ Array.from(this._inboundVideoTracks.values()).forEach((track) => track.close());
115
+ Array.from(this._outboundAudioTracks.values()).forEach((track) => track.close());
116
+ Array.from(this._outboundVideoTracks.values()).forEach((track) => track.close());
117
+
118
+ this._execute(() => this._storageProvider.peerConnectionStorage.remove(this.peerConnectionId))
119
+ .catch(() => void 0)
120
+ .finally(() => this.emit('close'));
121
+ }
122
+
123
+ public update(sample: PeerConnectionTransport, timestamp: number) {
124
+ if (this._closed) return;
125
+ if (sample.peerConnectionId !== this._model.peerConnectionId) throw new Error(`TransportId mismatch. PeerConnectionId: ${ this._model.peerConnectionId } TransportId: ${ sample.transportId}`);
126
+
127
+ this._sample = sample;
128
+
129
+ const report: PeerConnectionTransportReport = {
130
+ serviceId: this.client.call.serviceId,
131
+ roomId: this.client.call.roomId,
132
+ callId: this.client.call.callId,
133
+ clientId: this.client.clientId,
134
+ userId: this.client.userId,
135
+ mediaUnitId: this.client.mediaUnitId,
136
+ ...sample,
137
+ timestamp,
138
+ sampleSeq: -1, // deprecated
139
+ };
140
+
141
+ this.reports.addPeerConnectionTransportReports(report);
142
+
143
+ this._updated = timestamp;
144
+ this.emit('update');
145
+ }
146
+
147
+ public async createInboundAudioTrack(config: Omit<ObservedInboundTrackConfig<'audio'>, 'kind'>): Promise<ObservedInboundTrack<'audio'>> {
148
+ if (this._closed) throw new Error(`PeerConnection ${this.peerConnectionId} is closed`);
149
+
150
+ const result = await ObservedInboundTrack.create<'audio'>({
151
+ kind: 'audio',
152
+ trackId: config.trackId,
153
+ }, this, this._storageProvider);
154
+
155
+ result.on('close', () => {
156
+ this._inboundAudioTracks.delete(result.trackId);
157
+ this._model.inboundTrackIds = this._model.inboundTrackIds.filter((id) => id !== result.trackId);
158
+ !this._closed &&this._save().catch(() => void 0);
159
+ });
160
+ this._inboundAudioTracks.set(result.trackId, result);
161
+ this._model.inboundTrackIds = [ ...(new Set<string>([ ...this._model.inboundTrackIds, result.trackId ])) ];
162
+ await this._save();
163
+
164
+ this.emit('newinboudaudiotrack', result);
165
+
166
+ return result;
167
+ }
168
+
169
+ public async createInboundVideoTrack(config: Omit<ObservedInboundTrackConfig<'video'>, 'kind'>): Promise<ObservedInboundTrack<'video'>> {
170
+ if (this._closed) throw new Error(`PeerConnection ${this.peerConnectionId} is closed`);
171
+
172
+ const result = await ObservedInboundTrack.create<'video'>({
173
+ kind: 'video',
174
+ trackId: config.trackId,
175
+ }, this, this._storageProvider);
176
+
177
+ result.on('close', () => {
178
+ this._inboundVideoTracks.delete(result.trackId);
179
+ this._model.inboundTrackIds = this._model.inboundTrackIds.filter((id) => id !== result.trackId);
180
+ !this._closed &&this._save().catch(() => void 0);
181
+ });
182
+ this._inboundVideoTracks.set(result.trackId, result);
183
+ this._model.inboundTrackIds = [ ...(new Set<string>([ ...this._model.inboundTrackIds, result.trackId ])) ];
184
+ await this._save();
185
+
186
+ this.emit('newinboudvideotrack', result);
187
+
188
+ return result;
189
+ }
190
+
191
+ public async createOutboundAudioTrack(config: Omit<ObservedOutboundTrackConfig<'audio'>, 'kind'>): Promise<ObservedOutboundTrack<'audio'>> {
192
+ if (this._closed) throw new Error(`PeerConnection ${this.peerConnectionId} is closed`);
193
+
194
+ const result = await ObservedOutboundTrack.create<'audio'>({
195
+ kind: 'audio',
196
+ trackId: config.trackId,
197
+ }, this, this._storageProvider);
198
+
199
+ result.on('close', () => {
200
+ this._outboundAudioTracks.delete(result.trackId);
201
+ this._model.outboundTrackIds = this._model.outboundTrackIds.filter((id) => id !== result.trackId);
202
+
203
+ result.sfuStreamId && this.client.call.sfuStreamIdToOutboundAudioTrack.delete(result.sfuStreamId);
204
+ !this._closed &&this._save().catch(() => void 0);
205
+ });
206
+ this._outboundAudioTracks.set(result.trackId, result);
207
+ this._model.outboundTrackIds = [ ...(new Set<string>([ ...this._model.outboundTrackIds, result.trackId ])) ];
208
+
209
+ result.sfuStreamId && this.client.call.sfuStreamIdToOutboundAudioTrack.set(result.sfuStreamId, result);
210
+ await this._save();
211
+
212
+ this.emit('newoutboundaudiotrack', result);
213
+
214
+ return result;
215
+ }
216
+
217
+ public async createOutboundVideoTrack(config: Omit<ObservedOutboundTrackConfig<'video'>, 'kind'>): Promise<ObservedOutboundTrack<'video'>> {
218
+ if (this._closed) throw new Error(`PeerConnection ${this.peerConnectionId} is closed`);
219
+
220
+ const result = await ObservedOutboundTrack.create<'video'>({
221
+ kind: 'video',
222
+ trackId: config.trackId,
223
+ }, this, this._storageProvider);
224
+
225
+ result.on('close', () => {
226
+ this._outboundVideoTracks.delete(result.trackId);
227
+ result.sfuStreamId && this.client.call.sfuStreamIdToOutboundVideoTrack.set(result.sfuStreamId, result);
228
+ this._model.outboundTrackIds = this._model.outboundTrackIds.filter((id) => id !== result.trackId);
229
+ !this._closed && this._save().catch(() => void 0);
230
+ });
231
+ this._outboundVideoTracks.set(result.trackId, result);
232
+ result.sfuStreamId && this.client.call.sfuStreamIdToOutboundVideoTrack.set(result.sfuStreamId, result);
233
+ this._model.outboundTrackIds = [ ...(new Set<string>([ ...this._model.outboundTrackIds, result.trackId ])) ];
234
+ await this._save();
235
+
236
+ this.emit('newoutboundvideotrack', result);
237
+
238
+ return result;
239
+ }
240
+
241
+ private async _save() {
242
+ if (this._closed) throw new Error(`PeerConnection ${this.peerConnectionId} is closed`);
243
+
244
+ return this._execute(async () => {
245
+ if (this._closed) throw new Error(`PeerConnection ${this.peerConnectionId} is closed`);
246
+ await this._storageProvider.peerConnectionStorage.set(this.peerConnectionId, this._model);
247
+ });
248
+ }
249
+ }