werift 0.12.8 → 0.13.2
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/lib/common/src/binary.d.ts +9 -0
- package/lib/common/src/binary.js +37 -1
- package/lib/common/src/binary.js.map +1 -1
- package/lib/dtls/src/context/srtp.d.ts +6 -2
- package/lib/dtls/src/context/srtp.js +9 -3
- package/lib/dtls/src/context/srtp.js.map +1 -1
- package/lib/dtls/src/flight/client/flight5.js.map +1 -1
- package/lib/dtls/src/flight/server/flight2.js.map +1 -1
- package/lib/dtls/src/socket.d.ts +3 -3
- package/lib/dtls/src/socket.js +6 -8
- package/lib/dtls/src/socket.js.map +1 -1
- package/lib/ice/src/utils.d.ts +1 -0
- package/lib/ice/src/utils.js +5 -1
- package/lib/ice/src/utils.js.map +1 -1
- package/lib/rtp/src/codec/base.d.ts +8 -0
- package/lib/rtp/src/codec/base.js +16 -0
- package/lib/rtp/src/codec/base.js.map +1 -0
- package/lib/rtp/src/codec/h264.d.ts +23 -2
- package/lib/rtp/src/codec/h264.js +66 -3
- package/lib/rtp/src/codec/h264.js.map +1 -1
- package/lib/rtp/src/codec/opus.d.ts +9 -0
- package/lib/rtp/src/codec/opus.js +18 -0
- package/lib/rtp/src/codec/opus.js.map +1 -0
- package/lib/rtp/src/codec/vp8.d.ts +18 -11
- package/lib/rtp/src/codec/vp8.js +51 -29
- package/lib/rtp/src/codec/vp8.js.map +1 -1
- package/lib/rtp/src/codec/vp9.d.ts +38 -10
- package/lib/rtp/src/codec/vp9.js +115 -26
- package/lib/rtp/src/codec/vp9.js.map +1 -1
- package/lib/rtp/src/index.d.ts +2 -0
- package/lib/rtp/src/index.js +2 -0
- package/lib/rtp/src/index.js.map +1 -1
- package/lib/rtp/src/rtcp/psfb/index.d.ts +2 -2
- package/lib/rtp/src/rtcp/psfb/index.js.map +1 -1
- package/lib/rtp/src/rtcp/rr.d.ts +2 -2
- package/lib/rtp/src/rtcp/rr.js.map +1 -1
- package/lib/rtp/src/rtcp/rtpfb/index.d.ts +2 -2
- package/lib/rtp/src/rtcp/rtpfb/index.js.map +1 -1
- package/lib/rtp/src/rtcp/sdes.d.ts +2 -2
- package/lib/rtp/src/rtcp/sdes.js.map +1 -1
- package/lib/rtp/src/rtcp/sr.d.ts +2 -2
- package/lib/rtp/src/rtcp/sr.js +36 -0
- package/lib/rtp/src/rtcp/sr.js.map +1 -1
- package/lib/rtp/src/rtp/rtp.d.ts +2 -0
- package/lib/rtp/src/rtp/rtp.js +2 -0
- package/lib/rtp/src/rtp/rtp.js.map +1 -1
- package/lib/rtp/src/srtp/cipher/ctr.d.ts +17 -0
- package/lib/rtp/src/srtp/cipher/ctr.js +103 -0
- package/lib/rtp/src/srtp/cipher/ctr.js.map +1 -0
- package/lib/rtp/src/srtp/cipher/gcm.d.ts +15 -0
- package/lib/rtp/src/srtp/cipher/gcm.js +106 -0
- package/lib/rtp/src/srtp/cipher/gcm.js.map +1 -0
- package/lib/rtp/src/srtp/cipher/index.d.ts +14 -0
- package/lib/rtp/src/srtp/cipher/index.js +25 -0
- package/lib/rtp/src/srtp/cipher/index.js.map +1 -0
- package/lib/rtp/src/srtp/const.d.ts +5 -0
- package/lib/rtp/src/srtp/const.js +23 -0
- package/lib/rtp/src/srtp/const.js.map +1 -0
- package/lib/rtp/src/srtp/context/context.d.ts +13 -11
- package/lib/rtp/src/srtp/context/context.js +23 -23
- package/lib/rtp/src/srtp/context/context.js.map +1 -1
- package/lib/rtp/src/srtp/context/srtcp.d.ts +3 -2
- package/lib/rtp/src/srtp/context/srtcp.js +10 -34
- package/lib/rtp/src/srtp/context/srtcp.js.map +1 -1
- package/lib/rtp/src/srtp/context/srtp.d.ts +4 -3
- package/lib/rtp/src/srtp/context/srtp.js +9 -28
- package/lib/rtp/src/srtp/context/srtp.js.map +1 -1
- package/lib/rtp/src/srtp/srtp.js +2 -2
- package/lib/rtp/src/srtp/srtp.js.map +1 -1
- package/lib/webrtc/src/const.d.ts +4 -3
- package/lib/webrtc/src/const.js +5 -4
- package/lib/webrtc/src/const.js.map +1 -1
- package/lib/webrtc/src/helper.d.ts +2 -2
- package/lib/webrtc/src/helper.js +2 -2
- package/lib/webrtc/src/helper.js.map +1 -1
- package/lib/webrtc/src/index.d.ts +6 -2
- package/lib/webrtc/src/index.js +6 -2
- package/lib/webrtc/src/index.js.map +1 -1
- package/lib/webrtc/src/{extension → media/extension}/rtcpFeedback.d.ts +1 -1
- package/lib/webrtc/src/{extension → media/extension}/rtcpFeedback.js +0 -0
- package/lib/webrtc/src/media/extension/rtcpFeedback.js.map +1 -0
- package/lib/webrtc/src/{extension → media/extension}/rtpExtension.d.ts +1 -1
- package/lib/webrtc/src/{extension → media/extension}/rtpExtension.js +1 -1
- package/lib/webrtc/src/media/extension/rtpExtension.js.map +1 -0
- package/lib/webrtc/src/media/{nack.d.ts → receiver/nack.d.ts} +2 -2
- package/lib/webrtc/src/media/{nack.js → receiver/nack.js} +2 -2
- package/lib/webrtc/src/media/receiver/nack.js.map +1 -0
- package/lib/webrtc/src/media/{statistics.d.ts → receiver/statistics.d.ts} +1 -1
- package/lib/webrtc/src/media/{statistics.js → receiver/statistics.js} +1 -1
- package/lib/webrtc/src/media/receiver/statistics.js.map +1 -0
- package/lib/webrtc/src/media/router.js +1 -1
- package/lib/webrtc/src/media/router.js.map +1 -1
- package/lib/webrtc/src/media/rtpReceiver.d.ts +4 -2
- package/lib/webrtc/src/media/rtpReceiver.js +13 -6
- package/lib/webrtc/src/media/rtpReceiver.js.map +1 -1
- package/lib/webrtc/src/media/rtpSender.d.ts +4 -4
- package/lib/webrtc/src/media/rtpSender.js +12 -6
- package/lib/webrtc/src/media/rtpSender.js.map +1 -1
- package/lib/webrtc/src/media/{senderBWE → sender}/cumulativeResult.d.ts +0 -0
- package/lib/webrtc/src/media/{senderBWE → sender}/cumulativeResult.js +0 -0
- package/lib/webrtc/src/media/sender/cumulativeResult.js.map +1 -0
- package/lib/webrtc/src/media/{senderBWE → sender}/senderBWE.d.ts +0 -0
- package/lib/webrtc/src/media/{senderBWE → sender}/senderBWE.js +0 -0
- package/lib/webrtc/src/media/sender/senderBWE.js.map +1 -0
- package/lib/webrtc/src/media/track.d.ts +3 -0
- package/lib/webrtc/src/media/track.js +2 -0
- package/lib/webrtc/src/media/track.js.map +1 -1
- package/lib/webrtc/src/nonstandard/jitterBuffer.d.ts +12 -0
- package/lib/webrtc/src/nonstandard/jitterBuffer.js +48 -0
- package/lib/webrtc/src/nonstandard/jitterBuffer.js.map +1 -0
- package/lib/webrtc/src/nonstandard/lipsync.d.ts +20 -0
- package/lib/webrtc/src/nonstandard/lipsync.js +39 -0
- package/lib/webrtc/src/nonstandard/lipsync.js.map +1 -0
- package/lib/webrtc/src/nonstandard/recorder.d.ts +18 -0
- package/lib/webrtc/src/nonstandard/recorder.js +25 -0
- package/lib/webrtc/src/nonstandard/recorder.js.map +1 -0
- package/lib/webrtc/src/nonstandard/sampleBuilder.d.ts +18 -0
- package/lib/webrtc/src/nonstandard/sampleBuilder.js +60 -0
- package/lib/webrtc/src/nonstandard/sampleBuilder.js.map +1 -0
- package/lib/webrtc/src/nonstandard/userMedia.d.ts +15 -0
- package/lib/webrtc/src/nonstandard/userMedia.js +67 -0
- package/lib/webrtc/src/nonstandard/userMedia.js.map +1 -0
- package/lib/webrtc/src/nonstandard/webm.d.ts +24 -0
- package/lib/webrtc/src/nonstandard/webm.js +308 -0
- package/lib/webrtc/src/nonstandard/webm.js.map +1 -0
- package/lib/webrtc/src/peerConnection.js +1 -0
- package/lib/webrtc/src/peerConnection.js.map +1 -1
- package/lib/webrtc/src/transport/dtls.d.ts +2 -1
- package/lib/webrtc/src/transport/dtls.js +7 -3
- package/lib/webrtc/src/transport/dtls.js.map +1 -1
- package/lib/webrtc/src/utils.d.ts +3 -0
- package/lib/webrtc/src/utils.js +13 -9
- package/lib/webrtc/src/utils.js.map +1 -1
- package/package.json +5 -4
- package/src/const.ts +8 -3
- package/src/helper.ts +4 -4
- package/src/index.ts +6 -2
- package/src/{extension → media/extension}/rtcpFeedback.ts +1 -1
- package/src/{extension → media/extension}/rtpExtension.ts +1 -1
- package/src/media/{nack.ts → receiver/nack.ts} +3 -3
- package/src/media/{statistics.ts → receiver/statistics.ts} +2 -2
- package/src/media/router.ts +1 -1
- package/src/media/rtpReceiver.ts +11 -7
- package/src/media/rtpSender.ts +19 -9
- package/src/media/{senderBWE → sender}/cumulativeResult.ts +0 -0
- package/src/media/{senderBWE → sender}/senderBWE.ts +0 -0
- package/src/media/track.ts +6 -0
- package/src/nonstandard/jitterBuffer.ts +47 -0
- package/src/nonstandard/lipsync.ts +55 -0
- package/src/nonstandard/recorder.ts +26 -0
- package/src/nonstandard/sampleBuilder.ts +71 -0
- package/src/nonstandard/userMedia.ts +74 -0
- package/src/nonstandard/webm.ts +421 -0
- package/src/peerConnection.ts +3 -1
- package/src/transport/dtls.ts +12 -4
- package/src/utils.ts +20 -12
- package/lib/webrtc/src/extension/rtcpFeedback.js.map +0 -1
- package/lib/webrtc/src/extension/rtpExtension.js.map +0 -1
- package/lib/webrtc/src/media/nack.js.map +0 -1
- package/lib/webrtc/src/media/senderBWE/cumulativeResult.js.map +0 -1
- package/lib/webrtc/src/media/senderBWE/senderBWE.js.map +0 -1
- package/lib/webrtc/src/media/statistics.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "werift",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.2",
|
|
4
4
|
"description": "WebRTC Implementation for TypeScript (Node.js)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"WebRTC",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"@fidm/x509": "^1.2.1",
|
|
37
37
|
"@peculiar/webcrypto": "^1.1.6",
|
|
38
38
|
"@peculiar/x509": "^1.2.2",
|
|
39
|
+
"@shinyoshiaki/ebml-builder": "^0.0.1",
|
|
39
40
|
"aes-js": "^3.1.2",
|
|
40
41
|
"big-integer": "^1.6.48",
|
|
41
42
|
"binary-data": "^0.6.0",
|
|
@@ -58,12 +59,12 @@
|
|
|
58
59
|
"@types/aes-js": "^3.1.1",
|
|
59
60
|
"@types/big-integer": "^0.0.31",
|
|
60
61
|
"@types/buffer-crc32": "^0.2.0",
|
|
61
|
-
"@types/debug": "^4.1.
|
|
62
|
+
"@types/debug": "^4.1.7",
|
|
62
63
|
"@types/elliptic": "^6.4.12",
|
|
63
64
|
"@types/ip": "^1.1.0",
|
|
64
|
-
"@types/lodash": "^4.14.
|
|
65
|
+
"@types/lodash": "^4.14.172",
|
|
65
66
|
"@types/uuid": "^8.3.0",
|
|
66
|
-
"typedoc": "^0.21.
|
|
67
|
+
"typedoc": "^0.21.5"
|
|
67
68
|
},
|
|
68
69
|
"engines": {
|
|
69
70
|
"node": ">=15"
|
package/src/const.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ProtectionProfileAeadAes128Gcm,
|
|
3
|
+
ProtectionProfileAes128CmHmacSha1_80,
|
|
4
|
+
} from "../../dtls/src/context/srtp";
|
|
1
5
|
import { DtlsRole } from "./transport/dtls";
|
|
2
6
|
|
|
3
7
|
// data channel export constants
|
|
@@ -47,9 +51,10 @@ export const FMTP_INT_PARAMETERS = [
|
|
|
47
51
|
|
|
48
52
|
export const SSRC_INFO_ATTRS = ["cname", "msid", "mslabel", "label"];
|
|
49
53
|
|
|
50
|
-
export
|
|
51
|
-
SRTP_AES128_CM_HMAC_SHA1_80
|
|
52
|
-
|
|
54
|
+
export const SRTP_PROFILE = {
|
|
55
|
+
SRTP_AES128_CM_HMAC_SHA1_80: ProtectionProfileAes128CmHmacSha1_80,
|
|
56
|
+
SRTP_AEAD_AES_128_GCM: ProtectionProfileAeadAes128Gcm,
|
|
57
|
+
} as const;
|
|
53
58
|
|
|
54
59
|
export const SenderDirections = ["sendonly", "sendrecv"];
|
|
55
60
|
export const NotSenderDirections = ["inactive", "recvonly"];
|
package/src/helper.ts
CHANGED
|
@@ -10,21 +10,21 @@ export function divide(from: string, split: string): [string, string] {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export class PromiseQueue {
|
|
13
|
-
queue: { promise: () => Promise<any>;
|
|
13
|
+
queue: { promise: () => Promise<any>; done: () => void }[] = [];
|
|
14
14
|
running = false;
|
|
15
15
|
|
|
16
16
|
push = (promise: () => Promise<any>) =>
|
|
17
17
|
new Promise<void>((r) => {
|
|
18
|
-
this.queue.push({ promise,
|
|
18
|
+
this.queue.push({ promise, done: r });
|
|
19
19
|
if (!this.running) this.run();
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
async run() {
|
|
22
|
+
private async run() {
|
|
23
23
|
const task = this.queue.shift();
|
|
24
24
|
if (task) {
|
|
25
25
|
this.running = true;
|
|
26
26
|
await task.promise();
|
|
27
|
-
task.
|
|
27
|
+
task.done();
|
|
28
28
|
|
|
29
29
|
this.run();
|
|
30
30
|
} else {
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
export * from "../../ice/src";
|
|
2
2
|
export * from "../../rtp/src";
|
|
3
3
|
export * from "./dataChannel";
|
|
4
|
-
export * from "./extension/rtcpFeedback";
|
|
5
|
-
export * from "./extension/rtpExtension";
|
|
6
4
|
export * from "./helper";
|
|
5
|
+
export * from "./media/extension/rtcpFeedback";
|
|
6
|
+
export * from "./media/extension/rtpExtension";
|
|
7
7
|
export * from "./media/parameters";
|
|
8
8
|
export * from "./media/rtpTransceiver";
|
|
9
9
|
export * from "./media/track";
|
|
10
|
+
export * from "./nonstandard/lipsync";
|
|
11
|
+
export * from "./nonstandard/recorder";
|
|
12
|
+
export * from "./nonstandard/sampleBuilder";
|
|
13
|
+
export * from "./nonstandard/userMedia";
|
|
10
14
|
export * from "./peerConnection";
|
|
11
15
|
export * from "./sdp";
|
|
12
16
|
export * from "./transport/dtls";
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { range } from "lodash";
|
|
2
2
|
import Event from "rx.mini";
|
|
3
3
|
|
|
4
|
-
import { uint16Add } from "
|
|
4
|
+
import { uint16Add } from "../../../../common/src";
|
|
5
5
|
import {
|
|
6
6
|
GenericNack,
|
|
7
7
|
RtcpTransportLayerFeedback,
|
|
8
8
|
RtpPacket,
|
|
9
|
-
} from "
|
|
10
|
-
import { RTCRtpReceiver } from "
|
|
9
|
+
} from "../../../../rtp/src";
|
|
10
|
+
import { RTCRtpReceiver } from "../rtpReceiver";
|
|
11
11
|
|
|
12
12
|
const LOST_SIZE = 30 * 5;
|
|
13
13
|
|
package/src/media/router.ts
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
RtcpTransportLayerFeedback,
|
|
13
13
|
RtpPacket,
|
|
14
14
|
} from "../../../rtp/src";
|
|
15
|
-
import { RTP_EXTENSION_URI } from "
|
|
15
|
+
import { RTP_EXTENSION_URI } from "./extension/rtpExtension";
|
|
16
16
|
import {
|
|
17
17
|
RTCRtpReceiveParameters,
|
|
18
18
|
RTCRtpSimulcastParameters,
|
package/src/media/rtpReceiver.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { debug } from "debug";
|
|
2
2
|
import { jspack } from "jspack";
|
|
3
|
+
import Event from "rx.mini";
|
|
3
4
|
import { setTimeout } from "timers/promises";
|
|
4
5
|
import { v4 as uuid } from "uuid";
|
|
5
6
|
|
|
@@ -14,14 +15,15 @@ import {
|
|
|
14
15
|
RtpHeader,
|
|
15
16
|
RtpPacket,
|
|
16
17
|
} from "../../../rtp/src";
|
|
17
|
-
import { RTP_EXTENSION_URI } from "../extension/rtpExtension";
|
|
18
18
|
import { RTCDtlsTransport } from "../transport/dtls";
|
|
19
19
|
import { Kind } from "../types/domain";
|
|
20
|
-
import {
|
|
20
|
+
import { compactNtp } from "../utils";
|
|
21
|
+
import { RTP_EXTENSION_URI } from "./extension/rtpExtension";
|
|
21
22
|
import { RTCRtpCodecParameters, RTCRtpReceiveParameters } from "./parameters";
|
|
23
|
+
import { Nack } from "./receiver/nack";
|
|
22
24
|
import { ReceiverTWCC } from "./receiver/receiverTwcc";
|
|
25
|
+
import { StreamStatistics } from "./receiver/statistics";
|
|
23
26
|
import { Extensions } from "./router";
|
|
24
|
-
import { StreamStatistics } from "./statistics";
|
|
25
27
|
import { MediaStreamTrack } from "./track";
|
|
26
28
|
|
|
27
29
|
const log = debug("werift:packages/webrtc/src/media/rtpReceiver.ts");
|
|
@@ -37,9 +39,10 @@ export class RTCRtpReceiver {
|
|
|
37
39
|
readonly trackBySSRC: { [ssrc: string]: MediaStreamTrack } = {};
|
|
38
40
|
readonly trackByRID: { [rid: string]: MediaStreamTrack } = {};
|
|
39
41
|
// last senderReport
|
|
40
|
-
readonly lsr: { [ssrc: number]:
|
|
42
|
+
readonly lsr: { [ssrc: number]: number } = {};
|
|
41
43
|
readonly lsrTime: { [ssrc: number]: number } = {};
|
|
42
44
|
readonly onPacketLost = this.nack.onPacketLost;
|
|
45
|
+
readonly onRtcp = new Event<[RtcpPacket]>();
|
|
43
46
|
|
|
44
47
|
sdesMid?: string;
|
|
45
48
|
latestRid?: string;
|
|
@@ -128,7 +131,7 @@ export class RTCRtpReceiver {
|
|
|
128
131
|
|
|
129
132
|
const reports = Object.entries(this.remoteStreams).map(
|
|
130
133
|
([ssrc, stream]) => {
|
|
131
|
-
let lsr =
|
|
134
|
+
let lsr = 0,
|
|
132
135
|
dlsr = 0;
|
|
133
136
|
if (this.lsr[ssrc]) {
|
|
134
137
|
lsr = this.lsr[ssrc];
|
|
@@ -144,7 +147,7 @@ export class RTCRtpReceiver {
|
|
|
144
147
|
packetsLost: stream.packets_lost,
|
|
145
148
|
highestSequence: stream.max_seq,
|
|
146
149
|
jitter: stream.jitter,
|
|
147
|
-
lsr
|
|
150
|
+
lsr,
|
|
148
151
|
dlsr,
|
|
149
152
|
});
|
|
150
153
|
}
|
|
@@ -184,11 +187,12 @@ export class RTCRtpReceiver {
|
|
|
184
187
|
case RtcpSrPacket.type:
|
|
185
188
|
{
|
|
186
189
|
const sr = packet as RtcpSrPacket;
|
|
187
|
-
this.lsr[sr.ssrc] = (sr.senderInfo.ntpTimestamp
|
|
190
|
+
this.lsr[sr.ssrc] = compactNtp(sr.senderInfo.ntpTimestamp);
|
|
188
191
|
this.lsrTime[sr.ssrc] = Date.now() / 1000;
|
|
189
192
|
}
|
|
190
193
|
break;
|
|
191
194
|
}
|
|
195
|
+
this.onRtcp.execute(packet);
|
|
192
196
|
}
|
|
193
197
|
|
|
194
198
|
handleRtpBySsrc = (packet: RtpPacket, extensions: Extensions) => {
|
package/src/media/rtpSender.ts
CHANGED
|
@@ -29,16 +29,16 @@ import {
|
|
|
29
29
|
SourceDescriptionItem,
|
|
30
30
|
TransportWideCC,
|
|
31
31
|
} from "../../../rtp/src";
|
|
32
|
-
import { RTP_EXTENSION_URI } from "../extension/rtpExtension";
|
|
33
32
|
import { RTCDtlsTransport } from "../transport/dtls";
|
|
34
33
|
import { Kind } from "../types/domain";
|
|
35
|
-
import { milliTime, ntpTime } from "../utils";
|
|
34
|
+
import { compactNtp, milliTime, ntpTime } from "../utils";
|
|
35
|
+
import { RTP_EXTENSION_URI } from "./extension/rtpExtension";
|
|
36
36
|
import {
|
|
37
37
|
RTCRtpCodecParameters,
|
|
38
38
|
RTCRtpHeaderExtensionParameters,
|
|
39
39
|
RTCRtpSendParameters,
|
|
40
40
|
} from "./parameters";
|
|
41
|
-
import { SenderBandwidthEstimator, SentInfo } from "./
|
|
41
|
+
import { SenderBandwidthEstimator, SentInfo } from "./sender/senderBWE";
|
|
42
42
|
import { MediaStreamTrack } from "./track";
|
|
43
43
|
|
|
44
44
|
const log = debug("werift:packages/webrtc/src/media/rtpSender.ts");
|
|
@@ -54,7 +54,7 @@ export class RTCRtpSender {
|
|
|
54
54
|
: this.trackOrKind.kind;
|
|
55
55
|
readonly ssrc = jspack.Unpack("!L", randomBytes(4))[0];
|
|
56
56
|
readonly rtxSsrc = jspack.Unpack("!L", randomBytes(4))[0];
|
|
57
|
-
|
|
57
|
+
streamId = uuid.v4();
|
|
58
58
|
readonly trackId = uuid.v4();
|
|
59
59
|
readonly onReady = new Event();
|
|
60
60
|
readonly onRtcp = new Event<[RtcpPacket]>();
|
|
@@ -72,7 +72,7 @@ export class RTCRtpSender {
|
|
|
72
72
|
private disposeTrack?: () => void;
|
|
73
73
|
|
|
74
74
|
// # stats
|
|
75
|
-
private lsr?:
|
|
75
|
+
private lsr?: number;
|
|
76
76
|
private lsrTime: number = Date.now() / 1000;
|
|
77
77
|
private ntpTimestamp = 0n;
|
|
78
78
|
private rtpTimestamp = 0;
|
|
@@ -104,6 +104,9 @@ export class RTCRtpSender {
|
|
|
104
104
|
}
|
|
105
105
|
});
|
|
106
106
|
if (trackOrKind instanceof MediaStreamTrack) {
|
|
107
|
+
if (trackOrKind.streamId) {
|
|
108
|
+
this.streamId = trackOrKind.streamId;
|
|
109
|
+
}
|
|
107
110
|
this.registerTrack(trackOrKind);
|
|
108
111
|
}
|
|
109
112
|
}
|
|
@@ -149,6 +152,10 @@ export class RTCRtpSender {
|
|
|
149
152
|
if (this.codec) {
|
|
150
153
|
track.codec = this.codec;
|
|
151
154
|
}
|
|
155
|
+
|
|
156
|
+
track.onSourceChanged.subscribe((header) => {
|
|
157
|
+
this.replaceRTP(header);
|
|
158
|
+
});
|
|
152
159
|
}
|
|
153
160
|
|
|
154
161
|
async replaceTrack(track: MediaStreamTrack | null) {
|
|
@@ -167,7 +174,7 @@ export class RTCRtpSender {
|
|
|
167
174
|
}
|
|
168
175
|
|
|
169
176
|
this.registerTrack(track);
|
|
170
|
-
log("replaceTrack", track.ssrc, track.rid);
|
|
177
|
+
log("replaceTrack", "ssrc", track.ssrc, "rid", track.rid);
|
|
171
178
|
}
|
|
172
179
|
|
|
173
180
|
stop() {
|
|
@@ -199,7 +206,7 @@ export class RTCRtpSender {
|
|
|
199
206
|
}),
|
|
200
207
|
}),
|
|
201
208
|
];
|
|
202
|
-
this.lsr = (this.ntpTimestamp
|
|
209
|
+
this.lsr = compactNtp(this.ntpTimestamp);
|
|
203
210
|
this.lsrTime = Date.now() / 1000;
|
|
204
211
|
|
|
205
212
|
if (this.cname) {
|
|
@@ -227,7 +234,10 @@ export class RTCRtpSender {
|
|
|
227
234
|
} catch (error) {}
|
|
228
235
|
}
|
|
229
236
|
|
|
230
|
-
|
|
237
|
+
replaceRTP({
|
|
238
|
+
sequenceNumber,
|
|
239
|
+
timestamp,
|
|
240
|
+
}: Pick<RtpHeader, "sequenceNumber" | "timestamp">) {
|
|
231
241
|
if (this.sequenceNumber != undefined) {
|
|
232
242
|
this.seqOffset = uint16Add(this.sequenceNumber, -sequenceNumber);
|
|
233
243
|
}
|
|
@@ -330,7 +340,7 @@ export class RTCRtpSender {
|
|
|
330
340
|
packet.reports
|
|
331
341
|
.filter((report) => report.ssrc === this.ssrc)
|
|
332
342
|
.forEach((report) => {
|
|
333
|
-
if (this.lsr ===
|
|
343
|
+
if (this.lsr === report.lsr && report.dlsr) {
|
|
334
344
|
const rtt =
|
|
335
345
|
Date.now() / 1000 - this.lsrTime - report.dlsr / 65536;
|
|
336
346
|
if (this.rtt === undefined) {
|
|
File without changes
|
|
File without changes
|
package/src/media/track.ts
CHANGED
|
@@ -8,6 +8,8 @@ import { RTCRtpCodecParameters } from "./parameters";
|
|
|
8
8
|
|
|
9
9
|
export class MediaStreamTrack extends EventTarget {
|
|
10
10
|
readonly uuid = v4();
|
|
11
|
+
/**MediaStream ID*/
|
|
12
|
+
streamId?: string;
|
|
11
13
|
remote = false;
|
|
12
14
|
label: string;
|
|
13
15
|
kind!: Kind;
|
|
@@ -21,6 +23,9 @@ export class MediaStreamTrack extends EventTarget {
|
|
|
21
23
|
enabled = true;
|
|
22
24
|
|
|
23
25
|
readonly onReceiveRtp = new Event<[RtpPacket]>();
|
|
26
|
+
readonly onSourceChanged = new Event<
|
|
27
|
+
[Pick<RtpHeader, "sequenceNumber" | "timestamp">]
|
|
28
|
+
>();
|
|
24
29
|
|
|
25
30
|
stopped = false;
|
|
26
31
|
muted = true;
|
|
@@ -64,6 +69,7 @@ export class MediaStream {
|
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
addTrack(track: MediaStreamTrack) {
|
|
72
|
+
track.streamId = this.id;
|
|
67
73
|
this.tracks.push(track);
|
|
68
74
|
}
|
|
69
75
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { debug } from "debug";
|
|
2
|
+
|
|
3
|
+
import { uint16Add } from "../../../common/src";
|
|
4
|
+
import { RtpPacket } from "../../../rtp/src";
|
|
5
|
+
|
|
6
|
+
const log = debug("werift:packages/webrtc/src/nonstandard/jitterBuffer.ts");
|
|
7
|
+
|
|
8
|
+
export class JitterBuffer {
|
|
9
|
+
static MaxRetry = 100;
|
|
10
|
+
retry = 0;
|
|
11
|
+
head?: number;
|
|
12
|
+
buffer: { [sequenceNumber: number]: RtpPacket } = {};
|
|
13
|
+
|
|
14
|
+
constructor(public maxRetry = JitterBuffer.MaxRetry) {}
|
|
15
|
+
|
|
16
|
+
push(p: RtpPacket) {
|
|
17
|
+
this.buffer[p.header.sequenceNumber] = p;
|
|
18
|
+
|
|
19
|
+
if (this.head == undefined) {
|
|
20
|
+
this.head = p.header.sequenceNumber;
|
|
21
|
+
} else if (p.header.sequenceNumber != uint16Add(this.head, 1)) {
|
|
22
|
+
if (this.retry++ >= this.maxRetry) {
|
|
23
|
+
log("give up packet lost");
|
|
24
|
+
this.head = uint16Add(this.head, 2);
|
|
25
|
+
} else {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
this.head = uint16Add(this.head, 1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const packets: RtpPacket[] = [];
|
|
33
|
+
let tail = this.head;
|
|
34
|
+
for (; ; tail = uint16Add(tail, 1)) {
|
|
35
|
+
const p = this.buffer[tail];
|
|
36
|
+
if (p) {
|
|
37
|
+
packets.push(p);
|
|
38
|
+
delete this.buffer[tail];
|
|
39
|
+
} else {
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
this.head = uint16Add(tail, -1);
|
|
44
|
+
|
|
45
|
+
return packets;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { bufferReader, bufferWriter } from "../../../common/src";
|
|
2
|
+
import { RtcpSrPacket, RtpPacket } from "../../../rtp/src";
|
|
3
|
+
|
|
4
|
+
export class LipSync {
|
|
5
|
+
baseNtpTimestamp?: bigint;
|
|
6
|
+
baseRtpTimestamp?: number;
|
|
7
|
+
|
|
8
|
+
constructor(public clockRate: number) {}
|
|
9
|
+
|
|
10
|
+
srReceived(sr: RtcpSrPacket) {
|
|
11
|
+
const { ntpTimestamp, rtpTimestamp } = sr.senderInfo;
|
|
12
|
+
this.baseNtpTimestamp = ntpTimestamp;
|
|
13
|
+
this.baseRtpTimestamp = rtpTimestamp;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
calcNtpTime(rtpTimestamp: number) {
|
|
17
|
+
if (!this.baseRtpTimestamp || !this.baseNtpTimestamp) {
|
|
18
|
+
return 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// base rtpTimestamp is rollover
|
|
22
|
+
if (rtpTimestamp - this.baseRtpTimestamp > Max32bit - this.clockRate * 60) {
|
|
23
|
+
this.baseRtpTimestamp += Max32bit;
|
|
24
|
+
}
|
|
25
|
+
// target rtpTimestamp is rollover
|
|
26
|
+
else if (
|
|
27
|
+
rtpTimestamp + (Max32bit - this.clockRate * 60) - this.baseRtpTimestamp <
|
|
28
|
+
0
|
|
29
|
+
) {
|
|
30
|
+
rtpTimestamp += Max32bit;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const elapsed = (rtpTimestamp - this.baseRtpTimestamp) / this.clockRate;
|
|
34
|
+
|
|
35
|
+
return ntpTime2Time(this.baseNtpTimestamp) + elapsed;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const ntpTime2Time = (ntp: bigint) => {
|
|
40
|
+
const [ntpSec, ntpMsec] = bufferReader(bufferWriter([8], [ntp]), [4, 4]);
|
|
41
|
+
|
|
42
|
+
return Number(`${ntpSec}.${ntpMsec}`);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**4294967295 */
|
|
46
|
+
export const Max32bit = Number((0x01n << 32n) - 1n);
|
|
47
|
+
|
|
48
|
+
export interface BufferResolve {
|
|
49
|
+
packets: {
|
|
50
|
+
packet: RtpPacket;
|
|
51
|
+
offset: number;
|
|
52
|
+
}[];
|
|
53
|
+
/**NTP seconds */
|
|
54
|
+
startAtNtpTime: number;
|
|
55
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { MediaStreamTrack } from "../media/track";
|
|
2
|
+
import { WebmFactory } from "./webm";
|
|
3
|
+
|
|
4
|
+
export class MediaRecorder {
|
|
5
|
+
webm?: WebmFactory;
|
|
6
|
+
|
|
7
|
+
constructor(
|
|
8
|
+
public tracks: MediaStreamTrack[],
|
|
9
|
+
public path: string,
|
|
10
|
+
public options: Partial<{ width: number; height: number }> = {}
|
|
11
|
+
) {}
|
|
12
|
+
|
|
13
|
+
addTrack(track: MediaStreamTrack) {
|
|
14
|
+
this.tracks.push(track);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async start() {
|
|
18
|
+
this.webm = new WebmFactory(this.tracks, this.path, this.options);
|
|
19
|
+
await this.webm.start();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async stop() {
|
|
23
|
+
if (!this.webm) throw new Error();
|
|
24
|
+
await this.webm.stop();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { debug } from "debug";
|
|
2
|
+
|
|
3
|
+
import { int } from "../../../common/src";
|
|
4
|
+
import { DePacketizerBase, RtpPacket } from "../../../rtp/src";
|
|
5
|
+
import { enumerate } from "../helper";
|
|
6
|
+
import { JitterBuffer } from "./jitterBuffer";
|
|
7
|
+
|
|
8
|
+
const log = debug("werift:packages/webrtc/src/nonstandard/sampleBuilder.ts");
|
|
9
|
+
|
|
10
|
+
export class SampleBuilder {
|
|
11
|
+
private readonly jitterBuffer = new JitterBuffer();
|
|
12
|
+
private buffer: RtpPacket[] = [];
|
|
13
|
+
private baseTimestamp?: number;
|
|
14
|
+
relativeTimestamp = 0;
|
|
15
|
+
|
|
16
|
+
constructor(
|
|
17
|
+
readonly DePacketizer: typeof DePacketizerBase,
|
|
18
|
+
public clockRate: number
|
|
19
|
+
) {}
|
|
20
|
+
|
|
21
|
+
push(p: RtpPacket) {
|
|
22
|
+
const buf = this.jitterBuffer.push(p);
|
|
23
|
+
this.buffer = [...this.buffer, ...buf];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
resetTimestamp() {
|
|
27
|
+
this.baseTimestamp = undefined;
|
|
28
|
+
this.relativeTimestamp = 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
build() {
|
|
32
|
+
let tail: number | undefined;
|
|
33
|
+
for (const [i, p] of enumerate(this.buffer)) {
|
|
34
|
+
if (this.DePacketizer.isDetectedFinalPacketInSequence(p.header)) {
|
|
35
|
+
tail = i;
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (tail == undefined) return;
|
|
41
|
+
if (this.baseTimestamp == undefined) {
|
|
42
|
+
this.baseTimestamp = this.buffer[tail].header.timestamp;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const tailTimestamp = this.buffer[tail].header.timestamp;
|
|
46
|
+
const rotate =
|
|
47
|
+
Math.abs(tailTimestamp - this.baseTimestamp) > (Max32Uint / 4) * 3;
|
|
48
|
+
if (rotate) log({ rotate }, tailTimestamp, this.baseTimestamp);
|
|
49
|
+
|
|
50
|
+
const elapsed = rotate
|
|
51
|
+
? tailTimestamp + Max32Uint - this.baseTimestamp
|
|
52
|
+
: tailTimestamp - this.baseTimestamp;
|
|
53
|
+
|
|
54
|
+
const relativeTimestamp = int((elapsed / this.clockRate) * 1000);
|
|
55
|
+
this.relativeTimestamp = relativeTimestamp;
|
|
56
|
+
|
|
57
|
+
const frames = this.buffer.slice(0, tail + 1).map((p) => {
|
|
58
|
+
const frame = this.DePacketizer.deSerialize(p.payload);
|
|
59
|
+
return frame;
|
|
60
|
+
});
|
|
61
|
+
const isKeyframe = !!frames.find((f) => f.isKeyframe);
|
|
62
|
+
const data = Buffer.concat(frames.map((f) => f.payload));
|
|
63
|
+
|
|
64
|
+
this.buffer = this.buffer.slice(tail + 1);
|
|
65
|
+
|
|
66
|
+
return { data, relativeTimestamp, isKeyframe };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**4294967295 */
|
|
71
|
+
const Max32Uint = Number(0x01n << 32n) - 1;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { exec } from "child_process";
|
|
2
|
+
import { createSocket } from "dgram";
|
|
3
|
+
import { setImmediate } from "timers/promises";
|
|
4
|
+
import { v4 } from "uuid";
|
|
5
|
+
|
|
6
|
+
import { randomPort } from "../../../ice/src";
|
|
7
|
+
import { RtpPacket } from "../../../rtp/src";
|
|
8
|
+
import { MediaStreamTrack } from "../media/track";
|
|
9
|
+
|
|
10
|
+
export const getUserMp4 = async (path: string, loop?: boolean) => {
|
|
11
|
+
const audioPort = await randomPort();
|
|
12
|
+
const videoPort = await randomPort();
|
|
13
|
+
|
|
14
|
+
return new MediaMp4(audioPort, videoPort, path, loop);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
class MediaMp4 {
|
|
18
|
+
private streamId = v4();
|
|
19
|
+
audio = new MediaStreamTrack({ kind: "audio", streamId: this.streamId });
|
|
20
|
+
video = new MediaStreamTrack({ kind: "video", streamId: this.streamId });
|
|
21
|
+
|
|
22
|
+
constructor(
|
|
23
|
+
private videoPort: number,
|
|
24
|
+
private audioPort: number,
|
|
25
|
+
private path: string,
|
|
26
|
+
private loop?: boolean
|
|
27
|
+
) {
|
|
28
|
+
this.setupTrack(audioPort, this.audio);
|
|
29
|
+
this.setupTrack(videoPort, this.video);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private setupTrack = (port: number, track: MediaStreamTrack) => {
|
|
33
|
+
let payloadType = 0;
|
|
34
|
+
|
|
35
|
+
const socket = createSocket("udp4");
|
|
36
|
+
socket.bind(port);
|
|
37
|
+
socket.on("message", async (buf) => {
|
|
38
|
+
const rtp = RtpPacket.deSerialize(buf);
|
|
39
|
+
if (!payloadType) {
|
|
40
|
+
payloadType = rtp.header.payloadType;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// detect gStreamer restarted
|
|
44
|
+
if (payloadType !== rtp.header.payloadType) {
|
|
45
|
+
payloadType = rtp.header.payloadType;
|
|
46
|
+
track.onSourceChanged.execute(rtp.header);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
track.writeRtp(buf);
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
async start() {
|
|
54
|
+
let payloadType = 96;
|
|
55
|
+
const run = async () => {
|
|
56
|
+
if (payloadType > 100) payloadType = 96;
|
|
57
|
+
|
|
58
|
+
const cmd = `gst-launch-1.0 filesrc location= ${this.path} ! \
|
|
59
|
+
qtdemux name=d ! \
|
|
60
|
+
queue ! h264parse ! rtph264pay config-interval=10 pt=${payloadType++} ! \
|
|
61
|
+
udpsink host=127.0.0.1 port=${this.videoPort} d. ! \
|
|
62
|
+
queue ! aacparse ! avdec_aac ! audioresample ! audioconvert ! opusenc ! rtpopuspay pt=${payloadType++} ! \
|
|
63
|
+
udpsink host=127.0.0.1 port=${this.audioPort}`;
|
|
64
|
+
const process = exec(cmd);
|
|
65
|
+
|
|
66
|
+
if (this.loop) {
|
|
67
|
+
await new Promise((r) => process.on("close", r));
|
|
68
|
+
run();
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
await setImmediate();
|
|
72
|
+
run();
|
|
73
|
+
}
|
|
74
|
+
}
|