werift 0.18.3 → 0.18.5

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 (100) hide show
  1. package/lib/dtls/src/flight/server/flight2.js +1 -1
  2. package/lib/dtls/src/flight/server/flight2.js.map +1 -1
  3. package/lib/rtp/src/container/ebml/ebml.d.ts +5 -6
  4. package/lib/rtp/src/container/ebml/ebml.js +14 -13
  5. package/lib/rtp/src/container/ebml/ebml.js.map +1 -1
  6. package/lib/rtp/src/container/ebml/typedArrayUtils.d.ts +3 -4
  7. package/lib/rtp/src/container/ebml/typedArrayUtils.js +9 -10
  8. package/lib/rtp/src/container/ebml/typedArrayUtils.js.map +1 -1
  9. package/lib/rtp/src/container/index.d.ts +2 -0
  10. package/lib/rtp/src/{processor/source → container}/index.js +2 -3
  11. package/lib/rtp/src/container/index.js.map +1 -0
  12. package/lib/rtp/src/helper.d.ts +4 -0
  13. package/lib/rtp/src/helper.js +14 -1
  14. package/lib/rtp/src/helper.js.map +1 -1
  15. package/lib/rtp/src/index.d.ts +2 -0
  16. package/lib/rtp/src/index.js +2 -0
  17. package/lib/rtp/src/index.js.map +1 -1
  18. package/lib/rtp/src/processor/depacketizer.d.ts +1 -1
  19. package/lib/rtp/src/processor/depacketizer.js +16 -9
  20. package/lib/rtp/src/processor/depacketizer.js.map +1 -1
  21. package/lib/rtp/src/processor/depacketizerCallback.d.ts +14 -6
  22. package/lib/rtp/src/processor/depacketizerCallback.js +2 -35
  23. package/lib/rtp/src/processor/depacketizerCallback.js.map +1 -1
  24. package/lib/rtp/src/processor/dtx.d.ts +1 -0
  25. package/lib/rtp/src/processor/dtx.js +10 -1
  26. package/lib/rtp/src/processor/dtx.js.map +1 -1
  27. package/lib/rtp/src/processor/dtxCallback.d.ts +14 -5
  28. package/lib/rtp/src/processor/dtxCallback.js +2 -35
  29. package/lib/rtp/src/processor/dtxCallback.js.map +1 -1
  30. package/lib/rtp/src/processor/index.d.ts +3 -1
  31. package/lib/rtp/src/processor/index.js +3 -1
  32. package/lib/rtp/src/processor/index.js.map +1 -1
  33. package/lib/rtp/src/processor/interface.d.ts +17 -0
  34. package/lib/rtp/src/processor/interface.js +57 -0
  35. package/lib/rtp/src/processor/interface.js.map +1 -1
  36. package/lib/rtp/src/processor/jitterBuffer.d.ts +1 -2
  37. package/lib/rtp/src/processor/jitterBuffer.js +3 -1
  38. package/lib/rtp/src/processor/jitterBuffer.js.map +1 -1
  39. package/lib/rtp/src/processor/jitterBufferCallback.d.ts +14 -5
  40. package/lib/rtp/src/processor/jitterBufferCallback.js +2 -35
  41. package/lib/rtp/src/processor/jitterBufferCallback.js.map +1 -1
  42. package/lib/rtp/src/processor/jitterBufferTransformer.d.ts +1 -1
  43. package/lib/rtp/src/processor/lipsync.d.ts +19 -8
  44. package/lib/rtp/src/processor/lipsync.js +131 -83
  45. package/lib/rtp/src/processor/lipsync.js.map +1 -1
  46. package/lib/rtp/src/processor/lipsyncCallback.d.ts +8 -5
  47. package/lib/rtp/src/processor/lipsyncCallback.js +39 -4
  48. package/lib/rtp/src/processor/lipsyncCallback.js.map +1 -1
  49. package/lib/rtp/src/processor/mute.d.ts +17 -4
  50. package/lib/rtp/src/processor/mute.js +121 -40
  51. package/lib/rtp/src/processor/mute.js.map +1 -1
  52. package/lib/rtp/src/processor/muteCallback.d.ts +5 -2
  53. package/lib/rtp/src/processor/muteCallback.js +23 -7
  54. package/lib/rtp/src/processor/muteCallback.js.map +1 -1
  55. package/lib/rtp/src/processor/nack.d.ts +6 -6
  56. package/lib/rtp/src/processor/nack.js +23 -17
  57. package/lib/rtp/src/processor/nack.js.map +1 -1
  58. package/lib/rtp/src/processor/nackHandlerCallback.d.ts +14 -7
  59. package/lib/rtp/src/processor/nackHandlerCallback.js +2 -29
  60. package/lib/rtp/src/processor/nackHandlerCallback.js.map +1 -1
  61. package/lib/rtp/src/processor/ntpTime.d.ts +7 -7
  62. package/lib/rtp/src/processor/ntpTime.js +27 -29
  63. package/lib/rtp/src/processor/ntpTime.js.map +1 -1
  64. package/lib/rtp/src/processor/ntpTimeCallback.d.ts +13 -4
  65. package/lib/rtp/src/processor/ntpTimeCallback.js +2 -29
  66. package/lib/rtp/src/processor/ntpTimeCallback.js.map +1 -1
  67. package/lib/rtp/src/processor/rtcpCallback.d.ts +18 -0
  68. package/lib/rtp/src/processor/{source/rtcpCallback.js → rtcpCallback.js} +25 -3
  69. package/lib/rtp/src/processor/rtcpCallback.js.map +1 -0
  70. package/lib/rtp/src/processor/rtpCallback.d.ts +28 -0
  71. package/lib/rtp/src/processor/rtpCallback.js +127 -0
  72. package/lib/rtp/src/processor/rtpCallback.js.map +1 -0
  73. package/lib/rtp/src/processor/{source/rtpStream.d.ts → rtpStream.d.ts} +1 -1
  74. package/lib/rtp/src/processor/{source/rtpStream.js → rtpStream.js} +4 -2
  75. package/lib/rtp/src/processor/rtpStream.js.map +1 -0
  76. package/lib/rtp/src/processor/rtpTimeCallback.d.ts +13 -5
  77. package/lib/rtp/src/processor/rtpTimeCallback.js +2 -29
  78. package/lib/rtp/src/processor/rtpTimeCallback.js.map +1 -1
  79. package/lib/rtp/src/processor/webm.d.ts +8 -4
  80. package/lib/rtp/src/processor/webm.js +41 -8
  81. package/lib/rtp/src/processor/webm.js.map +1 -1
  82. package/lib/rtp/src/processor/webmCallback.d.ts +6 -5
  83. package/lib/rtp/src/processor/webmCallback.js +21 -7
  84. package/lib/rtp/src/processor/webmCallback.js.map +1 -1
  85. package/lib/webrtc/src/media/rtpSender.js +1 -2
  86. package/lib/webrtc/src/media/rtpSender.js.map +1 -1
  87. package/lib/webrtc/src/nonstandard/userMedia.d.ts +32 -23
  88. package/lib/webrtc/src/nonstandard/userMedia.js +49 -131
  89. package/lib/webrtc/src/nonstandard/userMedia.js.map +1 -1
  90. package/package.json +1 -1
  91. package/src/media/rtpSender.ts +1 -1
  92. package/src/nonstandard/userMedia.ts +69 -75
  93. package/lib/rtp/src/processor/source/index.d.ts +0 -3
  94. package/lib/rtp/src/processor/source/index.js.map +0 -1
  95. package/lib/rtp/src/processor/source/rtcpCallback.d.ts +0 -13
  96. package/lib/rtp/src/processor/source/rtcpCallback.js.map +0 -1
  97. package/lib/rtp/src/processor/source/rtpCallback.d.ts +0 -19
  98. package/lib/rtp/src/processor/source/rtpCallback.js +0 -62
  99. package/lib/rtp/src/processor/source/rtpCallback.js.map +0 -1
  100. package/lib/rtp/src/processor/source/rtpStream.js.map +0 -1
@@ -8,42 +8,38 @@ const uuid_1 = require("uuid");
8
8
  const src_1 = require("../../../common/src");
9
9
  const src_2 = require("../../../rtp/src");
10
10
  const track_1 = require("../media/track");
11
- const getUserMedia = async (path, loop) => {
11
+ const getUserMedia = async ({ path, loop, width, height, }) => {
12
12
  const audioPort = await (0, src_1.randomPort)();
13
13
  const videoPort = await (0, src_1.randomPort)();
14
14
  if (path.endsWith(".mp4")) {
15
- return new MediaPlayerMp4(audioPort, videoPort, path, loop);
15
+ return new MediaPlayerMp4({
16
+ audioPort,
17
+ videoPort,
18
+ path,
19
+ loop,
20
+ width,
21
+ height,
22
+ });
16
23
  }
17
24
  else {
18
- return new MediaPlayerWebm(audioPort, videoPort, path, loop);
25
+ return new MediaPlayerWebm({
26
+ audioPort,
27
+ videoPort,
28
+ path,
29
+ loop,
30
+ width,
31
+ height,
32
+ });
19
33
  }
20
34
  };
21
35
  exports.getUserMedia = getUserMedia;
22
- class MediaPlayerMp4 {
23
- constructor(videoPort, audioPort, path, loop) {
24
- Object.defineProperty(this, "videoPort", {
36
+ class MediaPlayer {
37
+ constructor(props) {
38
+ Object.defineProperty(this, "props", {
25
39
  enumerable: true,
26
40
  configurable: true,
27
41
  writable: true,
28
- value: videoPort
29
- });
30
- Object.defineProperty(this, "audioPort", {
31
- enumerable: true,
32
- configurable: true,
33
- writable: true,
34
- value: audioPort
35
- });
36
- Object.defineProperty(this, "path", {
37
- enumerable: true,
38
- configurable: true,
39
- writable: true,
40
- value: path
41
- });
42
- Object.defineProperty(this, "loop", {
43
- enumerable: true,
44
- configurable: true,
45
- writable: true,
46
- value: loop
42
+ value: props
47
43
  });
48
44
  Object.defineProperty(this, "streamId", {
49
45
  enumerable: true,
@@ -97,22 +93,39 @@ class MediaPlayerMp4 {
97
93
  });
98
94
  }
99
95
  });
100
- this.setupTrack(audioPort, this.audio);
101
- this.setupTrack(videoPort, this.video);
96
+ this.setupTrack(props.audioPort, this.audio);
97
+ this.setupTrack(props.videoPort, this.video);
98
+ }
99
+ stop() {
100
+ this.stopped = true;
101
+ this.process.kill("SIGINT");
102
102
  }
103
+ }
104
+ class MediaPlayerMp4 extends MediaPlayer {
103
105
  async start() {
104
106
  let payloadType = 96;
105
107
  const run = async () => {
106
108
  if (payloadType > 100)
107
109
  payloadType = 96;
108
- const cmd = `gst-launch-1.0 filesrc location= ${this.path} ! \
110
+ let cmd = "";
111
+ if (this.props.width && this.props.height) {
112
+ cmd = `gst-launch-1.0 filesrc location= ${this.props.path} ! \
113
+ decodebin ! videoscale ! video/x-raw,width=${this.props.width},height=${this.props.height} ! x264enc ! \
114
+ h264parse ! rtph264pay config-interval=10 pt=${payloadType++} ! \
115
+ udpsink host=127.0.0.1 port=${this.props.videoPort}`;
116
+ }
117
+ else {
118
+ cmd = `gst-launch-1.0 filesrc location= ${this.props.path} ! \
109
119
  qtdemux name=d ! \
110
120
  queue ! h264parse ! rtph264pay config-interval=10 pt=${payloadType++} ! \
111
- udpsink host=127.0.0.1 port=${this.videoPort} d. ! \
121
+ udpsink host=127.0.0.1 port=${this.props.videoPort} d. ! \
112
122
  queue ! aacparse ! avdec_aac ! audioresample ! audioconvert ! opusenc ! rtpopuspay pt=${payloadType++} ! \
113
- udpsink host=127.0.0.1 port=${this.audioPort}`;
123
+ udpsink host=127.0.0.1 port=${this.props.audioPort}`;
124
+ }
125
+ console.log(cmd);
114
126
  this.process = (0, child_process_1.exec)(cmd);
115
- if (this.loop) {
127
+ this.process.on("error", (e) => console.error("gst error", e));
128
+ if (this.props.loop) {
116
129
  await new Promise((r) => this.process.on("close", r));
117
130
  if (!this.stopped) {
118
131
  run();
@@ -122,112 +135,21 @@ udpsink host=127.0.0.1 port=${this.audioPort}`;
122
135
  await (0, promises_1.setImmediate)();
123
136
  run();
124
137
  }
125
- stop() {
126
- this.stopped = true;
127
- this.process.kill("SIGINT");
128
- }
129
138
  }
130
139
  exports.MediaPlayerMp4 = MediaPlayerMp4;
131
- class MediaPlayerWebm {
132
- constructor(videoPort, audioPort, path, loop) {
133
- Object.defineProperty(this, "videoPort", {
134
- enumerable: true,
135
- configurable: true,
136
- writable: true,
137
- value: videoPort
138
- });
139
- Object.defineProperty(this, "audioPort", {
140
- enumerable: true,
141
- configurable: true,
142
- writable: true,
143
- value: audioPort
144
- });
145
- Object.defineProperty(this, "path", {
146
- enumerable: true,
147
- configurable: true,
148
- writable: true,
149
- value: path
150
- });
151
- Object.defineProperty(this, "loop", {
152
- enumerable: true,
153
- configurable: true,
154
- writable: true,
155
- value: loop
156
- });
157
- Object.defineProperty(this, "streamId", {
158
- enumerable: true,
159
- configurable: true,
160
- writable: true,
161
- value: (0, uuid_1.v4)()
162
- });
163
- Object.defineProperty(this, "audio", {
164
- enumerable: true,
165
- configurable: true,
166
- writable: true,
167
- value: new track_1.MediaStreamTrack({ kind: "audio", streamId: this.streamId })
168
- });
169
- Object.defineProperty(this, "video", {
170
- enumerable: true,
171
- configurable: true,
172
- writable: true,
173
- value: new track_1.MediaStreamTrack({ kind: "video", streamId: this.streamId })
174
- });
175
- Object.defineProperty(this, "process", {
176
- enumerable: true,
177
- configurable: true,
178
- writable: true,
179
- value: void 0
180
- });
181
- Object.defineProperty(this, "stopped", {
182
- enumerable: true,
183
- configurable: true,
184
- writable: true,
185
- value: false
186
- });
187
- Object.defineProperty(this, "setupTrack", {
188
- enumerable: true,
189
- configurable: true,
190
- writable: true,
191
- value: (port, track) => {
192
- let payloadType = 0;
193
- let latestTimestamp = 0;
194
- let timestampDiff = 0;
195
- const socket = (0, dgram_1.createSocket)("udp4");
196
- socket.bind(port);
197
- socket.on("message", async (buf) => {
198
- const rtp = src_2.RtpPacket.deSerialize(buf);
199
- if (!payloadType) {
200
- payloadType = rtp.header.payloadType;
201
- }
202
- // detect gStreamer restarted
203
- if (payloadType !== rtp.header.payloadType) {
204
- payloadType = rtp.header.payloadType;
205
- track.onSourceChanged.execute(rtp.header);
206
- timestampDiff = (0, src_1.uint32Add)(rtp.header.timestamp, -latestTimestamp);
207
- console.log({ timestampDiff });
208
- }
209
- latestTimestamp = rtp.header.timestamp;
210
- rtp.header.timestamp = (0, src_1.uint32Add)(rtp.header.timestamp, -timestampDiff);
211
- track.writeRtp(rtp.serialize());
212
- });
213
- }
214
- });
215
- this.setupTrack(audioPort, this.audio);
216
- this.setupTrack(videoPort, this.video);
217
- }
140
+ class MediaPlayerWebm extends MediaPlayer {
218
141
  async start() {
219
142
  let payloadType = 96;
220
143
  const run = async () => {
221
144
  if (payloadType > 100)
222
145
  payloadType = 96;
223
- const cmd = `gst-launch-1.0 filesrc location=${this.path} ! matroskademux name=d \
146
+ const cmd = `gst-launch-1.0 filesrc location=${this.props.path} ! matroskademux name=d \
224
147
  d.video_0 ! queue ! rtpvp8pay pt=${payloadType++} ! \
225
- udpsink host=127.0.0.1 port=${this.videoPort} \
148
+ udpsink host=127.0.0.1 port=${this.props.videoPort} \
226
149
  d.audio_0 ! queue ! rtpopuspay pt=${payloadType++} ! \
227
- udpsink host=127.0.0.1 port=${this.audioPort}`;
150
+ udpsink host=127.0.0.1 port=${this.props.audioPort}`;
228
151
  this.process = (0, child_process_1.exec)(cmd);
229
- console.log(cmd);
230
- if (this.loop) {
152
+ if (this.props.loop) {
231
153
  await new Promise((r) => this.process.on("close", r));
232
154
  if (!this.stopped) {
233
155
  run();
@@ -237,10 +159,6 @@ udpsink host=127.0.0.1 port=${this.audioPort}`;
237
159
  await (0, promises_1.setImmediate)();
238
160
  run();
239
161
  }
240
- stop() {
241
- this.stopped = true;
242
- this.process.kill("SIGINT");
243
- }
244
162
  }
245
163
  exports.MediaPlayerWebm = MediaPlayerWebm;
246
164
  //# sourceMappingURL=userMedia.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"userMedia.js","sourceRoot":"","sources":["../../../../src/nonstandard/userMedia.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChildProcess, exec } from \"child_process\";\nimport { createSocket } from \"dgram\";\nimport { setImmediate } from \"timers/promises\";\nimport { v4 } from \"uuid\";\n\nimport { randomPort, uint32Add } from \"../../../common/src\";\nimport { RtpPacket } from \"../../../rtp/src\";\nimport { MediaStreamTrack } from \"../media/track\";\n\nexport const getUserMedia = async (path: string, loop?: boolean) => {\n const audioPort = await randomPort();\n const videoPort = await randomPort();\n\n if (path.endsWith(\".mp4\")) {\n return new MediaPlayerMp4(audioPort, videoPort, path, loop);\n } else {\n return new MediaPlayerWebm(audioPort, videoPort, path, loop);\n }\n};\n\nexport class MediaPlayerMp4 {\n private streamId = v4();\n audio = new MediaStreamTrack({ kind: \"audio\", streamId: this.streamId });\n video = new MediaStreamTrack({ kind: \"video\", streamId: this.streamId });\n private process!: ChildProcess;\n stopped = false;\n\n constructor(\n private videoPort: number,\n private audioPort: number,\n private path: string,\n private loop?: boolean\n ) {\n this.setupTrack(audioPort, this.audio);\n this.setupTrack(videoPort, this.video);\n }\n\n private setupTrack = (port: number, track: MediaStreamTrack) => {\n let payloadType = 0;\n\n const socket = createSocket(\"udp4\");\n socket.bind(port);\n socket.on(\"message\", async (buf) => {\n const rtp = RtpPacket.deSerialize(buf);\n if (!payloadType) {\n payloadType = rtp.header.payloadType;\n }\n\n // detect gStreamer restarted\n if (payloadType !== rtp.header.payloadType) {\n payloadType = rtp.header.payloadType;\n track.onSourceChanged.execute(rtp.header);\n }\n\n track.writeRtp(buf);\n });\n };\n\n async start() {\n let payloadType = 96;\n const run = async () => {\n if (payloadType > 100) payloadType = 96;\n\n const cmd = `gst-launch-1.0 filesrc location= ${this.path} ! \\\nqtdemux name=d ! \\\nqueue ! h264parse ! rtph264pay config-interval=10 pt=${payloadType++} ! \\\nudpsink host=127.0.0.1 port=${this.videoPort} d. ! \\\nqueue ! aacparse ! avdec_aac ! audioresample ! audioconvert ! opusenc ! rtpopuspay pt=${payloadType++} ! \\\nudpsink host=127.0.0.1 port=${this.audioPort}`;\n this.process = exec(cmd);\n\n if (this.loop) {\n await new Promise((r) => this.process.on(\"close\", r));\n if (!this.stopped) {\n run();\n }\n }\n };\n await setImmediate();\n run();\n }\n\n stop() {\n this.stopped = true;\n this.process.kill(\"SIGINT\");\n }\n}\n\nexport class MediaPlayerWebm {\n private streamId = v4();\n audio = new MediaStreamTrack({ kind: \"audio\", streamId: this.streamId });\n video = new MediaStreamTrack({ kind: \"video\", streamId: this.streamId });\n private process!: ChildProcess;\n stopped = false;\n\n constructor(\n private videoPort: number,\n private audioPort: number,\n private path: string,\n private loop?: boolean\n ) {\n this.setupTrack(audioPort, this.audio);\n this.setupTrack(videoPort, this.video);\n }\n\n private setupTrack = (port: number, track: MediaStreamTrack) => {\n let payloadType = 0;\n let latestTimestamp = 0;\n let timestampDiff = 0;\n\n const socket = createSocket(\"udp4\");\n socket.bind(port);\n socket.on(\"message\", async (buf) => {\n const rtp = RtpPacket.deSerialize(buf);\n if (!payloadType) {\n payloadType = rtp.header.payloadType;\n }\n\n // detect gStreamer restarted\n if (payloadType !== rtp.header.payloadType) {\n payloadType = rtp.header.payloadType;\n track.onSourceChanged.execute(rtp.header);\n timestampDiff = uint32Add(rtp.header.timestamp, -latestTimestamp);\n console.log({ timestampDiff });\n }\n latestTimestamp = rtp.header.timestamp;\n rtp.header.timestamp = uint32Add(rtp.header.timestamp, -timestampDiff);\n track.writeRtp(rtp.serialize());\n });\n };\n\n async start() {\n let payloadType = 96;\n const run = async () => {\n if (payloadType > 100) payloadType = 96;\n\n const cmd = `gst-launch-1.0 filesrc location=${\n this.path\n } ! matroskademux name=d \\\nd.video_0 ! queue ! rtpvp8pay pt=${payloadType++} ! \\\nudpsink host=127.0.0.1 port=${this.videoPort} \\\nd.audio_0 ! queue ! rtpopuspay pt=${payloadType++} ! \\\nudpsink host=127.0.0.1 port=${this.audioPort}`;\n this.process = exec(cmd);\n console.log(cmd);\n\n if (this.loop) {\n await new Promise((r) => this.process.on(\"close\", r));\n if (!this.stopped) {\n run();\n }\n }\n };\n await setImmediate();\n run();\n }\n\n stop() {\n this.stopped = true;\n this.process.kill(\"SIGINT\");\n }\n}\n"]}
1
+ {"version":3,"file":"userMedia.js","sourceRoot":"","sources":["../../../../src/nonstandard/userMedia.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChildProcess, exec } from \"child_process\";\nimport { createSocket } from \"dgram\";\nimport { setImmediate } from \"timers/promises\";\nimport { v4 } from \"uuid\";\n\nimport { randomPort } from \"../../../common/src\";\nimport { RtpPacket } from \"../../../rtp/src\";\nimport { MediaStreamTrack } from \"../media/track\";\n\nexport const getUserMedia = async ({\n path,\n loop,\n width,\n height,\n}: {\n path: string;\n loop?: boolean;\n width?: number;\n height?: number;\n}) => {\n const audioPort = await randomPort();\n const videoPort = await randomPort();\n\n if (path.endsWith(\".mp4\")) {\n return new MediaPlayerMp4({\n audioPort,\n videoPort,\n path,\n loop,\n width,\n height,\n });\n } else {\n return new MediaPlayerWebm({\n audioPort,\n videoPort,\n path,\n loop,\n width,\n height,\n });\n }\n};\n\nabstract class MediaPlayer {\n protected streamId = v4();\n audio = new MediaStreamTrack({ kind: \"audio\", streamId: this.streamId });\n video = new MediaStreamTrack({ kind: \"video\", streamId: this.streamId });\n protected process!: ChildProcess;\n stopped = false;\n\n constructor(\n protected props: {\n videoPort: number;\n audioPort: number;\n path: string;\n loop?: boolean;\n width?: number;\n height?: number;\n }\n ) {\n this.setupTrack(props.audioPort, this.audio);\n this.setupTrack(props.videoPort, this.video);\n }\n\n private setupTrack = (port: number, track: MediaStreamTrack) => {\n let payloadType = 0;\n\n const socket = createSocket(\"udp4\");\n socket.bind(port);\n socket.on(\"message\", async (buf) => {\n const rtp = RtpPacket.deSerialize(buf);\n if (!payloadType) {\n payloadType = rtp.header.payloadType;\n }\n\n // detect gStreamer restarted\n if (payloadType !== rtp.header.payloadType) {\n payloadType = rtp.header.payloadType;\n track.onSourceChanged.execute(rtp.header);\n }\n\n track.writeRtp(buf);\n });\n };\n\n stop() {\n this.stopped = true;\n this.process.kill(\"SIGINT\");\n }\n}\n\nexport class MediaPlayerMp4 extends MediaPlayer {\n async start() {\n let payloadType = 96;\n const run = async () => {\n if (payloadType > 100) payloadType = 96;\n\n let cmd = \"\";\n if (this.props.width && this.props.height) {\n cmd = `gst-launch-1.0 filesrc location= ${this.props.path} ! \\\ndecodebin ! videoscale ! video/x-raw,width=${this.props.width},height=${\n this.props.height\n } ! x264enc ! \\\nh264parse ! rtph264pay config-interval=10 pt=${payloadType++} ! \\\nudpsink host=127.0.0.1 port=${this.props.videoPort}`;\n } else {\n cmd = `gst-launch-1.0 filesrc location= ${this.props.path} ! \\\nqtdemux name=d ! \\\nqueue ! h264parse ! rtph264pay config-interval=10 pt=${payloadType++} ! \\\nudpsink host=127.0.0.1 port=${this.props.videoPort} d. ! \\\nqueue ! aacparse ! avdec_aac ! audioresample ! audioconvert ! opusenc ! rtpopuspay pt=${payloadType++} ! \\\nudpsink host=127.0.0.1 port=${this.props.audioPort}`;\n }\n console.log(cmd);\n this.process = exec(cmd);\n this.process.on(\"error\", (e) => console.error(\"gst error\", e));\n\n if (this.props.loop) {\n await new Promise((r) => this.process.on(\"close\", r));\n if (!this.stopped) {\n run();\n }\n }\n };\n await setImmediate();\n run();\n }\n}\n\nexport class MediaPlayerWebm extends MediaPlayer {\n async start() {\n let payloadType = 96;\n const run = async () => {\n if (payloadType > 100) payloadType = 96;\n\n const cmd = `gst-launch-1.0 filesrc location=${\n this.props.path\n } ! matroskademux name=d \\\nd.video_0 ! queue ! rtpvp8pay pt=${payloadType++} ! \\\nudpsink host=127.0.0.1 port=${this.props.videoPort} \\\nd.audio_0 ! queue ! rtpopuspay pt=${payloadType++} ! \\\nudpsink host=127.0.0.1 port=${this.props.audioPort}`;\n this.process = exec(cmd);\n\n if (this.props.loop) {\n await new Promise((r) => this.process.on(\"close\", r));\n if (!this.stopped) {\n run();\n }\n }\n };\n await setImmediate();\n run();\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "werift",
3
- "version": "0.18.3",
3
+ "version": "0.18.5",
4
4
  "description": "WebRTC Implementation for TypeScript (Node.js)",
5
5
  "keywords": [
6
6
  "WebRTC",
@@ -126,7 +126,7 @@ export class RTCRtpSender {
126
126
  typeof this.trackOrKind === "string"
127
127
  ? this.trackOrKind
128
128
  : this.trackOrKind.kind;
129
- if (trackOrKind instanceof MediaStreamTrack) {
129
+ if (typeof trackOrKind !== "string") {
130
130
  if (trackOrKind.streamId) {
131
131
  this.streamId = trackOrKind.streamId;
132
132
  }
@@ -3,36 +3,64 @@ import { createSocket } from "dgram";
3
3
  import { setImmediate } from "timers/promises";
4
4
  import { v4 } from "uuid";
5
5
 
6
- import { randomPort, uint32Add } from "../../../common/src";
6
+ import { randomPort } from "../../../common/src";
7
7
  import { RtpPacket } from "../../../rtp/src";
8
8
  import { MediaStreamTrack } from "../media/track";
9
9
 
10
- export const getUserMedia = async (path: string, loop?: boolean) => {
10
+ export const getUserMedia = async ({
11
+ path,
12
+ loop,
13
+ width,
14
+ height,
15
+ }: {
16
+ path: string;
17
+ loop?: boolean;
18
+ width?: number;
19
+ height?: number;
20
+ }) => {
11
21
  const audioPort = await randomPort();
12
22
  const videoPort = await randomPort();
13
23
 
14
24
  if (path.endsWith(".mp4")) {
15
- return new MediaPlayerMp4(audioPort, videoPort, path, loop);
25
+ return new MediaPlayerMp4({
26
+ audioPort,
27
+ videoPort,
28
+ path,
29
+ loop,
30
+ width,
31
+ height,
32
+ });
16
33
  } else {
17
- return new MediaPlayerWebm(audioPort, videoPort, path, loop);
34
+ return new MediaPlayerWebm({
35
+ audioPort,
36
+ videoPort,
37
+ path,
38
+ loop,
39
+ width,
40
+ height,
41
+ });
18
42
  }
19
43
  };
20
44
 
21
- export class MediaPlayerMp4 {
22
- private streamId = v4();
45
+ abstract class MediaPlayer {
46
+ protected streamId = v4();
23
47
  audio = new MediaStreamTrack({ kind: "audio", streamId: this.streamId });
24
48
  video = new MediaStreamTrack({ kind: "video", streamId: this.streamId });
25
- private process!: ChildProcess;
49
+ protected process!: ChildProcess;
26
50
  stopped = false;
27
51
 
28
52
  constructor(
29
- private videoPort: number,
30
- private audioPort: number,
31
- private path: string,
32
- private loop?: boolean
53
+ protected props: {
54
+ videoPort: number;
55
+ audioPort: number;
56
+ path: string;
57
+ loop?: boolean;
58
+ width?: number;
59
+ height?: number;
60
+ }
33
61
  ) {
34
- this.setupTrack(audioPort, this.audio);
35
- this.setupTrack(videoPort, this.video);
62
+ this.setupTrack(props.audioPort, this.audio);
63
+ this.setupTrack(props.videoPort, this.video);
36
64
  }
37
65
 
38
66
  private setupTrack = (port: number, track: MediaStreamTrack) => {
@@ -56,20 +84,39 @@ export class MediaPlayerMp4 {
56
84
  });
57
85
  };
58
86
 
87
+ stop() {
88
+ this.stopped = true;
89
+ this.process.kill("SIGINT");
90
+ }
91
+ }
92
+
93
+ export class MediaPlayerMp4 extends MediaPlayer {
59
94
  async start() {
60
95
  let payloadType = 96;
61
96
  const run = async () => {
62
97
  if (payloadType > 100) payloadType = 96;
63
98
 
64
- const cmd = `gst-launch-1.0 filesrc location= ${this.path} ! \
99
+ let cmd = "";
100
+ if (this.props.width && this.props.height) {
101
+ cmd = `gst-launch-1.0 filesrc location= ${this.props.path} ! \
102
+ decodebin ! videoscale ! video/x-raw,width=${this.props.width},height=${
103
+ this.props.height
104
+ } ! x264enc ! \
105
+ h264parse ! rtph264pay config-interval=10 pt=${payloadType++} ! \
106
+ udpsink host=127.0.0.1 port=${this.props.videoPort}`;
107
+ } else {
108
+ cmd = `gst-launch-1.0 filesrc location= ${this.props.path} ! \
65
109
  qtdemux name=d ! \
66
110
  queue ! h264parse ! rtph264pay config-interval=10 pt=${payloadType++} ! \
67
- udpsink host=127.0.0.1 port=${this.videoPort} d. ! \
111
+ udpsink host=127.0.0.1 port=${this.props.videoPort} d. ! \
68
112
  queue ! aacparse ! avdec_aac ! audioresample ! audioconvert ! opusenc ! rtpopuspay pt=${payloadType++} ! \
69
- udpsink host=127.0.0.1 port=${this.audioPort}`;
113
+ udpsink host=127.0.0.1 port=${this.props.audioPort}`;
114
+ }
115
+ console.log(cmd);
70
116
  this.process = exec(cmd);
117
+ this.process.on("error", (e) => console.error("gst error", e));
71
118
 
72
- if (this.loop) {
119
+ if (this.props.loop) {
73
120
  await new Promise((r) => this.process.on("close", r));
74
121
  if (!this.stopped) {
75
122
  run();
@@ -79,72 +126,24 @@ udpsink host=127.0.0.1 port=${this.audioPort}`;
79
126
  await setImmediate();
80
127
  run();
81
128
  }
82
-
83
- stop() {
84
- this.stopped = true;
85
- this.process.kill("SIGINT");
86
- }
87
129
  }
88
130
 
89
- export class MediaPlayerWebm {
90
- private streamId = v4();
91
- audio = new MediaStreamTrack({ kind: "audio", streamId: this.streamId });
92
- video = new MediaStreamTrack({ kind: "video", streamId: this.streamId });
93
- private process!: ChildProcess;
94
- stopped = false;
95
-
96
- constructor(
97
- private videoPort: number,
98
- private audioPort: number,
99
- private path: string,
100
- private loop?: boolean
101
- ) {
102
- this.setupTrack(audioPort, this.audio);
103
- this.setupTrack(videoPort, this.video);
104
- }
105
-
106
- private setupTrack = (port: number, track: MediaStreamTrack) => {
107
- let payloadType = 0;
108
- let latestTimestamp = 0;
109
- let timestampDiff = 0;
110
-
111
- const socket = createSocket("udp4");
112
- socket.bind(port);
113
- socket.on("message", async (buf) => {
114
- const rtp = RtpPacket.deSerialize(buf);
115
- if (!payloadType) {
116
- payloadType = rtp.header.payloadType;
117
- }
118
-
119
- // detect gStreamer restarted
120
- if (payloadType !== rtp.header.payloadType) {
121
- payloadType = rtp.header.payloadType;
122
- track.onSourceChanged.execute(rtp.header);
123
- timestampDiff = uint32Add(rtp.header.timestamp, -latestTimestamp);
124
- console.log({ timestampDiff });
125
- }
126
- latestTimestamp = rtp.header.timestamp;
127
- rtp.header.timestamp = uint32Add(rtp.header.timestamp, -timestampDiff);
128
- track.writeRtp(rtp.serialize());
129
- });
130
- };
131
-
131
+ export class MediaPlayerWebm extends MediaPlayer {
132
132
  async start() {
133
133
  let payloadType = 96;
134
134
  const run = async () => {
135
135
  if (payloadType > 100) payloadType = 96;
136
136
 
137
137
  const cmd = `gst-launch-1.0 filesrc location=${
138
- this.path
138
+ this.props.path
139
139
  } ! matroskademux name=d \
140
140
  d.video_0 ! queue ! rtpvp8pay pt=${payloadType++} ! \
141
- udpsink host=127.0.0.1 port=${this.videoPort} \
141
+ udpsink host=127.0.0.1 port=${this.props.videoPort} \
142
142
  d.audio_0 ! queue ! rtpopuspay pt=${payloadType++} ! \
143
- udpsink host=127.0.0.1 port=${this.audioPort}`;
143
+ udpsink host=127.0.0.1 port=${this.props.audioPort}`;
144
144
  this.process = exec(cmd);
145
- console.log(cmd);
146
145
 
147
- if (this.loop) {
146
+ if (this.props.loop) {
148
147
  await new Promise((r) => this.process.on("close", r));
149
148
  if (!this.stopped) {
150
149
  run();
@@ -154,9 +153,4 @@ udpsink host=127.0.0.1 port=${this.audioPort}`;
154
153
  await setImmediate();
155
154
  run();
156
155
  }
157
-
158
- stop() {
159
- this.stopped = true;
160
- this.process.kill("SIGINT");
161
- }
162
156
  }
@@ -1,3 +0,0 @@
1
- export * from "./rtcpCallback";
2
- export * from "./rtpCallback";
3
- export * from "./rtpStream";
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../rtp/src/processor/source/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA+B;AAC/B,gDAA8B;AAC9B,8CAA4B","sourcesContent":["export * from \"./rtcpCallback\";\nexport * from \"./rtpCallback\";\nexport * from \"./rtpStream\";\n"]}
@@ -1,13 +0,0 @@
1
- import Event from "rx.mini";
2
- import { RtcpPacket } from "../../rtcp/rtcp";
3
- export interface RtcpOutput {
4
- rtcp?: RtcpPacket;
5
- eol?: boolean;
6
- }
7
- export declare class RtcpSourceCallback {
8
- private cb?;
9
- onStopped: Event<any[]>;
10
- pipe(cb: (chunk: RtcpOutput) => void): void;
11
- input: (rtcp: RtcpPacket) => void;
12
- stop(): void;
13
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"rtcpCallback.js","sourceRoot":"","sources":["../../../../../../rtp/src/processor/source/rtcpCallback.ts"],"names":[],"mappings":";;;;;;AAAA,sDAA4B;AAS5B,MAAa,kBAAkB;IAA/B;QACE;;;;;WAAyC;QAEzC;;;;mBAAY,IAAI,iBAAK,EAAE;WAAC;QAMxB;;;;mBAAQ,CAAC,IAAgB,EAAE,EAAE;gBAC3B,IAAI,IAAI,CAAC,EAAE,EAAE;oBACX,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;iBACnB;YACH,CAAC;WAAC;IAWJ,CAAC;IAnBC,IAAI,CAAC,EAA+B;QAClC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACf,CAAC;IAQD,IAAI;QACF,IAAI,IAAI,CAAC,EAAE,EAAE;YACX,IAAI,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;SACxB;QACD,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;QAEzB,IAAI,CAAC,EAAE,GAAG,SAAS,CAAC;QACpB,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,CAAC;IAClC,CAAC;CACF;AAxBD,gDAwBC","sourcesContent":["import Event from \"rx.mini\";\n\nimport { RtcpPacket } from \"../../rtcp/rtcp\";\n\nexport interface RtcpOutput {\n rtcp?: RtcpPacket;\n eol?: boolean;\n}\n\nexport class RtcpSourceCallback {\n private cb?: (chunk: RtcpOutput) => void;\n\n onStopped = new Event();\n\n pipe(cb: (chunk: RtcpOutput) => void) {\n this.cb = cb;\n }\n\n input = (rtcp: RtcpPacket) => {\n if (this.cb) {\n this.cb({ rtcp });\n }\n };\n\n stop() {\n if (this.cb) {\n this.cb({ eol: true });\n }\n this.onStopped.execute();\n\n this.cb = undefined;\n this.onStopped.allUnsubscribe();\n }\n}\n"]}
@@ -1,19 +0,0 @@
1
- /// <reference types="node" />
2
- import Event from "rx.mini";
3
- import { RtpPacket } from "../../rtp/rtp";
4
- export interface RtpOutput {
5
- rtp?: RtpPacket;
6
- eol?: boolean;
7
- }
8
- export declare class RtpSourceCallback {
9
- private options;
10
- private cb?;
11
- onStopped: Event<any[]>;
12
- constructor(options?: {
13
- payloadType?: number;
14
- clearInvalidPTPacket?: boolean;
15
- });
16
- pipe(cb: (chunk: RtpOutput) => void): void;
17
- input: (packet: Buffer | RtpPacket) => void;
18
- stop(): void;
19
- }
@@ -1,62 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.RtpSourceCallback = void 0;
7
- const rx_mini_1 = __importDefault(require("rx.mini"));
8
- const rtp_1 = require("../../rtp/rtp");
9
- class RtpSourceCallback {
10
- constructor(options = {}) {
11
- Object.defineProperty(this, "options", {
12
- enumerable: true,
13
- configurable: true,
14
- writable: true,
15
- value: options
16
- });
17
- Object.defineProperty(this, "cb", {
18
- enumerable: true,
19
- configurable: true,
20
- writable: true,
21
- value: void 0
22
- });
23
- Object.defineProperty(this, "onStopped", {
24
- enumerable: true,
25
- configurable: true,
26
- writable: true,
27
- value: new rx_mini_1.default()
28
- });
29
- Object.defineProperty(this, "input", {
30
- enumerable: true,
31
- configurable: true,
32
- writable: true,
33
- value: (packet) => {
34
- const rtp = packet instanceof rtp_1.RtpPacket ? packet : rtp_1.RtpPacket.deSerialize(packet);
35
- if (this.options.payloadType != undefined &&
36
- this.options.payloadType !== rtp.header.payloadType) {
37
- if (this.options.clearInvalidPTPacket) {
38
- rtp.clear();
39
- }
40
- return;
41
- }
42
- if (this.cb) {
43
- this.cb({ rtp });
44
- }
45
- }
46
- });
47
- options.clearInvalidPTPacket = options.clearInvalidPTPacket ?? true;
48
- }
49
- pipe(cb) {
50
- this.cb = cb;
51
- }
52
- stop() {
53
- if (this.cb) {
54
- this.cb({ eol: true });
55
- }
56
- this.onStopped.execute();
57
- this.cb = undefined;
58
- this.onStopped.allUnsubscribe();
59
- }
60
- }
61
- exports.RtpSourceCallback = RtpSourceCallback;
62
- //# sourceMappingURL=rtpCallback.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rtpCallback.js","sourceRoot":"","sources":["../../../../../../rtp/src/processor/source/rtpCallback.ts"],"names":[],"mappings":";;;;;;AAAA,sDAA4B;AAE5B,uCAA0C;AAO1C,MAAa,iBAAiB;IAK5B,YACU,UAGJ,EAAE;;;;;mBAHE;;QALV;;;;;WAAwC;QAExC;;;;mBAAY,IAAI,iBAAK,EAAE;WAAC;QAexB;;;;mBAAQ,CAAC,MAA0B,EAAE,EAAE;gBACrC,MAAM,GAAG,GACP,MAAM,YAAY,eAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,eAAS,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;gBAEvE,IACE,IAAI,CAAC,OAAO,CAAC,WAAW,IAAI,SAAS;oBACrC,IAAI,CAAC,OAAO,CAAC,WAAW,KAAK,GAAG,CAAC,MAAM,CAAC,WAAW,EACnD;oBACA,IAAI,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE;wBACrC,GAAG,CAAC,KAAK,EAAE,CAAC;qBACb;oBACD,OAAO;iBACR;gBAED,IAAI,IAAI,CAAC,EAAE,EAAE;oBACX,IAAI,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;iBAClB;YACH,CAAC;WAAC;QAxBA,OAAO,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,IAAI,IAAI,CAAC;IACtE,CAAC;IAED,IAAI,CAAC,EAA8B;QACjC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACf,CAAC;IAqBD,IAAI;QACF,IAAI,IAAI,CAAC,EAAE,EAAE;YACX,IAAI,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;SACxB;QACD,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;QAEzB,IAAI,CAAC,EAAE,GAAG,SAAS,CAAC;QACpB,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,CAAC;IAClC,CAAC;CACF;AA9CD,8CA8CC","sourcesContent":["import Event from \"rx.mini\";\n\nimport { RtpPacket } from \"../../rtp/rtp\";\n\nexport interface RtpOutput {\n rtp?: RtpPacket;\n eol?: boolean;\n}\n\nexport class RtpSourceCallback {\n private cb?: (chunk: RtpOutput) => void;\n\n onStopped = new Event();\n\n constructor(\n private options: {\n payloadType?: number;\n clearInvalidPTPacket?: boolean;\n } = {}\n ) {\n options.clearInvalidPTPacket = options.clearInvalidPTPacket ?? true;\n }\n\n pipe(cb: (chunk: RtpOutput) => void) {\n this.cb = cb;\n }\n\n input = (packet: Buffer | RtpPacket) => {\n const rtp =\n packet instanceof RtpPacket ? packet : RtpPacket.deSerialize(packet);\n\n if (\n this.options.payloadType != undefined &&\n this.options.payloadType !== rtp.header.payloadType\n ) {\n if (this.options.clearInvalidPTPacket) {\n rtp.clear();\n }\n return;\n }\n\n if (this.cb) {\n this.cb({ rtp });\n }\n };\n\n stop() {\n if (this.cb) {\n this.cb({ eol: true });\n }\n this.onStopped.execute();\n\n this.cb = undefined;\n this.onStopped.allUnsubscribe();\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"rtpStream.js","sourceRoot":"","sources":["../../../../../../rtp/src/processor/source/rtpStream.ts"],"names":[],"mappings":";;;AAAA,oCAAsE;AAEtE,uCAA0C;AAG1C,MAAa,eAAe;IAK1B,YACU,UAGJ,EAAE;;;;;mBAHE;;QALV;;;;;WAAoC;QACpC;;;;;WAAmC;QACnC;;;;;WAA2D;QAkB3D;;;;mBAAO,CAAC,MAA0B,EAAE,EAAE;gBACpC,MAAM,GAAG,GACP,MAAM,YAAY,eAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,eAAS,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;gBAEvE,IACE,IAAI,CAAC,OAAO,CAAC,WAAW,IAAI,SAAS;oBACrC,IAAI,CAAC,OAAO,CAAC,WAAW,KAAK,GAAG,CAAC,MAAM,CAAC,WAAW,EACnD;oBACA,IAAI,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE;wBACrC,GAAG,CAAC,KAAK,EAAE,CAAC;qBACb;oBACD,OAAO;iBACR;gBAED,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;YACtB,CAAC;WAAC;QAzBA,OAAO,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,IAAI,IAAI,CAAC;QAEpE,IAAI,CAAC,QAAQ,GAAG,IAAI,oBAAc,CAAC;YACjC,KAAK,EAAE,CAAC,UAAU,EAAE,EAAE;gBACpB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;gBAC7B,IAAI,CAAC,KAAK,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACpD,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IAmBD,IAAI;QACF,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;CACF;AAzCD,0CAyCC","sourcesContent":["import { ReadableStream, ReadableStreamController } from \"stream/web\";\n\nimport { RtpPacket } from \"../../rtp/rtp\";\nimport { RtpOutput } from \"./rtpCallback\";\n\nexport class RtpSourceStream {\n readable: ReadableStream<RtpOutput>;\n write!: (chunk: RtpOutput) => void;\n protected controller!: ReadableStreamController<RtpOutput>;\n\n constructor(\n private options: {\n payloadType?: number;\n clearInvalidPTPacket?: boolean;\n } = {}\n ) {\n options.clearInvalidPTPacket = options.clearInvalidPTPacket ?? true;\n\n this.readable = new ReadableStream({\n start: (controller) => {\n this.controller = controller;\n this.write = (chunk) => controller.enqueue(chunk);\n },\n });\n }\n\n push = (packet: Buffer | RtpPacket) => {\n const rtp =\n packet instanceof RtpPacket ? packet : RtpPacket.deSerialize(packet);\n\n if (\n this.options.payloadType != undefined &&\n this.options.payloadType !== rtp.header.payloadType\n ) {\n if (this.options.clearInvalidPTPacket) {\n rtp.clear();\n }\n return;\n }\n\n this.write({ rtp });\n };\n\n stop() {\n this.controller.enqueue({ eol: true });\n }\n}\n"]}