werift 0.15.11 → 0.16.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 (79) hide show
  1. package/lib/common/src/index.d.ts +2 -0
  2. package/lib/common/src/index.js +2 -0
  3. package/lib/common/src/index.js.map +1 -1
  4. package/lib/common/src/log.d.ts +11 -0
  5. package/lib/common/src/log.js +17 -0
  6. package/lib/common/src/log.js.map +1 -0
  7. package/lib/common/src/type.d.ts +3 -0
  8. package/lib/common/src/type.js +3 -0
  9. package/lib/common/src/type.js.map +1 -0
  10. package/lib/dtls/src/context/cipher.js.map +1 -1
  11. package/lib/dtls/src/flight/server/flight2.js +10 -0
  12. package/lib/dtls/src/flight/server/flight2.js.map +1 -1
  13. package/lib/ice/src/ice.d.ts +1 -0
  14. package/lib/ice/src/ice.js +4 -0
  15. package/lib/ice/src/ice.js.map +1 -1
  16. package/lib/rtp/src/codec/index.d.ts +18 -0
  17. package/lib/rtp/src/codec/index.js +81 -0
  18. package/lib/rtp/src/codec/index.js.map +1 -0
  19. package/lib/rtp/src/codec/vp8.d.ts +5 -3
  20. package/lib/rtp/src/codec/vp8.js +19 -5
  21. package/lib/rtp/src/codec/vp8.js.map +1 -1
  22. package/lib/rtp/src/container/webm.d.ts +6 -1
  23. package/lib/rtp/src/container/webm.js +9 -2
  24. package/lib/rtp/src/container/webm.js.map +1 -1
  25. package/lib/rtp/src/index.d.ts +2 -6
  26. package/lib/rtp/src/index.js +2 -6
  27. package/lib/rtp/src/index.js.map +1 -1
  28. package/lib/rtp/src/processor/base.d.ts +3 -1
  29. package/lib/rtp/src/processor/base.js +19 -6
  30. package/lib/rtp/src/processor/base.js.map +1 -1
  31. package/lib/rtp/src/processor/jitterBuffer.js +1 -1
  32. package/lib/rtp/src/processor/jitterBuffer.js.map +1 -1
  33. package/lib/rtp/src/processor/lipsync.js +22 -2
  34. package/lib/rtp/src/processor/lipsync.js.map +1 -1
  35. package/lib/rtp/src/processor/webm.d.ts +11 -7
  36. package/lib/rtp/src/processor/webm.js +16 -41
  37. package/lib/rtp/src/processor/webm.js.map +1 -1
  38. package/lib/rtp/src/processor_v2/depacketizer.d.ts +17 -0
  39. package/lib/rtp/src/processor_v2/depacketizer.js +84 -0
  40. package/lib/rtp/src/processor_v2/depacketizer.js.map +1 -0
  41. package/lib/rtp/src/processor_v2/index.d.ts +4 -0
  42. package/lib/rtp/src/processor_v2/index.js +21 -0
  43. package/lib/rtp/src/processor_v2/index.js.map +1 -0
  44. package/lib/rtp/src/processor_v2/jitterBuffer.d.ts +33 -0
  45. package/lib/rtp/src/processor_v2/jitterBuffer.js +154 -0
  46. package/lib/rtp/src/processor_v2/jitterBuffer.js.map +1 -0
  47. package/lib/rtp/src/processor_v2/source/base.d.ts +8 -0
  48. package/lib/rtp/src/processor_v2/source/base.js +16 -0
  49. package/lib/rtp/src/processor_v2/source/base.js.map +1 -0
  50. package/lib/rtp/src/processor_v2/source/index.d.ts +2 -0
  51. package/lib/rtp/src/processor_v2/source/index.js +6 -0
  52. package/lib/rtp/src/processor_v2/source/index.js.map +1 -0
  53. package/lib/rtp/src/processor_v2/source/rtp.d.ts +14 -0
  54. package/lib/rtp/src/processor_v2/source/rtp.js +24 -0
  55. package/lib/rtp/src/processor_v2/source/rtp.js.map +1 -0
  56. package/lib/rtp/src/processor_v2/webmLive.d.ts +51 -0
  57. package/lib/rtp/src/processor_v2/webmLive.js +154 -0
  58. package/lib/rtp/src/processor_v2/webmLive.js.map +1 -0
  59. package/lib/webrtc/src/media/rtpTransceiver.d.ts +1 -1
  60. package/lib/webrtc/src/media/rtpTransceiver.js +3 -2
  61. package/lib/webrtc/src/media/rtpTransceiver.js.map +1 -1
  62. package/lib/webrtc/src/nonstandard/recorder/index.d.ts +5 -1
  63. package/lib/webrtc/src/nonstandard/recorder/index.js +2 -2
  64. package/lib/webrtc/src/nonstandard/recorder/index.js.map +1 -1
  65. package/lib/webrtc/src/nonstandard/recorder/writer/index.d.ts +1 -1
  66. package/lib/webrtc/src/nonstandard/recorder/writer/index.js +1 -1
  67. package/lib/webrtc/src/nonstandard/recorder/writer/index.js.map +1 -1
  68. package/lib/webrtc/src/nonstandard/recorder/writer/webm.d.ts +3 -3
  69. package/lib/webrtc/src/nonstandard/recorder/writer/webm.js +61 -41
  70. package/lib/webrtc/src/nonstandard/recorder/writer/webm.js.map +1 -1
  71. package/lib/webrtc/src/peerConnection.d.ts +9 -1
  72. package/lib/webrtc/src/peerConnection.js +9 -1
  73. package/lib/webrtc/src/peerConnection.js.map +1 -1
  74. package/package.json +2 -2
  75. package/src/media/rtpTransceiver.ts +4 -2
  76. package/src/nonstandard/recorder/index.ts +6 -2
  77. package/src/nonstandard/recorder/writer/index.ts +1 -1
  78. package/src/nonstandard/recorder/writer/webm.ts +105 -57
  79. package/src/peerConnection.ts +26 -2
@@ -1,75 +1,123 @@
1
- import * as fs from "fs/promises";
1
+ import { appendFile, open, unlink } from "fs/promises";
2
+ import { ReadableStreamDefaultReadResult } from "stream/web";
2
3
 
3
4
  import { SupportedCodec } from "../../../../../rtp/src/container/webm";
4
5
  import {
5
- JitterBuffer,
6
+ depacketizeTransformer,
7
+ jitterBufferTransformer,
6
8
  MediaStreamTrack,
7
- SampleBuilder,
8
- WebmOutput,
9
+ RtpSourceStream,
10
+ WebmLiveOutput,
11
+ WebmLiveSink,
12
+ WeriftError,
9
13
  } from "../../..";
10
14
  import { MediaWriter } from ".";
11
15
 
16
+ const sourcePath = "packages/webrtc/src/nonstandard/recorder/writer/webm.ts";
17
+
12
18
  export class WebmFactory extends MediaWriter {
13
- webm?: WebmOutput;
19
+ rtpSources: RtpSourceStream[] = [];
20
+
21
+ async start(tracks: MediaStreamTrack[]) {
22
+ await unlink(this.path).catch((e) => e);
23
+
24
+ const inputTracks = tracks.map((track, i) => {
25
+ const trackNumber = i + 1;
26
+ const payloadType = track.codec!.payloadType;
27
+
28
+ if (track.kind === "video") {
29
+ const codec = ((): SupportedCodec => {
30
+ switch (track.codec?.name.toLowerCase() as SupportedVideoCodec) {
31
+ case "vp8":
32
+ return "VP8";
33
+ case "vp9":
34
+ return "VP9";
35
+ case "h264":
36
+ return "MPEG4/ISO/AVC";
37
+ case "av1x":
38
+ return "AV1";
39
+ default:
40
+ throw new WeriftError({
41
+ message: "unsupported codec",
42
+ payload: { track, path: sourcePath },
43
+ });
44
+ }
45
+ })();
46
+ return {
47
+ kind: "video" as const,
48
+ codec,
49
+ clockRate: 90000,
50
+ trackNumber,
51
+ width: this.options.width,
52
+ height: this.options.height,
53
+ payloadType,
54
+ track,
55
+ };
56
+ } else {
57
+ return {
58
+ kind: "audio" as const,
59
+ codec: "OPUS" as const,
60
+ clockRate: 48000,
61
+ trackNumber,
62
+ payloadType,
63
+ track,
64
+ };
65
+ }
66
+ });
14
67
 
15
- start(tracks: MediaStreamTrack[]) {
16
- this.webm = new WebmOutput(
17
- fs,
18
- this.path,
19
- tracks.map((track, i) => {
20
- const trackNumber = i + 1;
21
- const payloadType = track.codec!.payloadType;
68
+ const webm = new WebmLiveSink(inputTracks, {
69
+ duration: this.options.defaultDuration ?? 1000 * 60 * 60 * 24,
70
+ });
71
+
72
+ this.rtpSources = inputTracks.map(({ track, clockRate, codec }) => {
73
+ const rtpSource = new RtpSourceStream(track.onReceiveRtp);
74
+
75
+ const jitterBuffer = jitterBufferTransformer(clockRate, {
76
+ latency: this.options.jitterBufferLatency,
77
+ bufferSize: this.options.jitterBufferSize,
78
+ });
22
79
 
23
- if (track.kind === "video") {
24
- const codec = ((): SupportedCodec => {
25
- switch (track.codec?.name.toLowerCase() as SupportedVideoCodec) {
26
- case "vp8":
27
- return "VP8";
28
- case "vp9":
29
- return "VP9";
30
- case "h264":
31
- return "MPEG4/ISO/AVC";
32
- case "av1x":
33
- return "AV1";
34
- default:
35
- throw new Error();
36
- }
37
- })();
38
- return {
39
- kind: "video",
40
- clockRate: 90000,
41
- payloadType,
42
- trackNumber,
43
- codec,
44
- width: this.options.width,
45
- height: this.options.height,
46
- };
47
- } else {
48
- return {
49
- kind: "audio",
50
- clockRate: 48000,
51
- payloadType,
52
- trackNumber,
53
- codec: "OPUS",
54
- };
55
- }
56
- })
57
- );
80
+ if (track.kind === "video") {
81
+ rtpSource.readable
82
+ .pipeThrough(jitterBuffer)
83
+ .pipeThrough(
84
+ depacketizeTransformer((h) => h.marker, codec, {
85
+ waitForKeyframe: this.options.waitForKeyframe,
86
+ })
87
+ )
88
+ .pipeTo(webm.videoStream);
89
+ } else {
90
+ rtpSource.readable
91
+ .pipeThrough(jitterBuffer)
92
+ .pipeThrough(depacketizeTransformer(() => true, codec))
93
+ .pipeTo(webm.audioStream);
94
+ }
58
95
 
59
- tracks.forEach((track) => {
60
- const sampleBuilder =
61
- track.kind === "video"
62
- ? new SampleBuilder((h) => !!h.marker).pipe(this.webm!)
63
- : new SampleBuilder(() => true).pipe(this.webm!);
64
- new JitterBuffer({
65
- rtpStream: track.onReceiveRtp,
66
- rtcpStream: track.onReceiveRtcp,
67
- }).pipe(sampleBuilder);
96
+ return rtpSource;
68
97
  });
98
+
99
+ const reader = webm.webmStream.getReader();
100
+ const readChunk = async ({
101
+ value,
102
+ done,
103
+ }: ReadableStreamDefaultReadResult<WebmLiveOutput>) => {
104
+ if (done) return;
105
+
106
+ if (value.packet) {
107
+ await appendFile(this.path, value.packet);
108
+ } else if (value.eol) {
109
+ const { durationElement } = value.eol;
110
+ const handler = await open(this.path, "r+");
111
+ await handler.write(durationElement, 0, durationElement.length, 83);
112
+ await handler.close();
113
+ }
114
+ reader.read().then(readChunk);
115
+ };
116
+ reader.read().then(readChunk);
69
117
  }
70
118
 
71
119
  async stop() {
72
- await this.webm!.stop();
120
+ await Promise.all(this.rtpSources.map((r) => r.stop()));
73
121
  }
74
122
  }
75
123
 
@@ -5,7 +5,16 @@ import Event from "rx.mini";
5
5
  import * as uuid from "uuid";
6
6
 
7
7
  import { Profile } from "../../dtls/src/context/srtp";
8
- import { deepMerge, InterfaceAddresses, Recvonly, Sendonly, Sendrecv } from ".";
8
+ import { Message } from "../../ice/src/stun/message";
9
+ import { Protocol } from "../../ice/src/types/model";
10
+ import {
11
+ Address,
12
+ deepMerge,
13
+ InterfaceAddresses,
14
+ Recvonly,
15
+ Sendonly,
16
+ Sendrecv,
17
+ } from ".";
9
18
  import {
10
19
  codecParametersFromString,
11
20
  DtlsKeys,
@@ -88,6 +97,7 @@ export class RTCPeerConnection extends EventTarget {
88
97
  readonly onTransceiverAdded = new Event<[RTCRtpTransceiver]>();
89
98
  readonly onIceCandidate = new Event<[RTCIceCandidate]>();
90
99
  readonly onNegotiationneeded = new Event<[]>();
100
+ readonly onTrack = new Event<[MediaStreamTrack]>();
91
101
 
92
102
  ondatachannel?: CallbackWithValue<RTCDataChannelEvent>;
93
103
  onicecandidate?: CallbackWithValue<RTCPeerConnectionIceEvent>;
@@ -258,7 +268,7 @@ export class RTCPeerConnection extends EventTarget {
258
268
  }
259
269
  if (transceiver.headerExtensions.length === 0) {
260
270
  transceiver.headerExtensions =
261
- this.config.headerExtensions[transceiver.kind];
271
+ this.config.headerExtensions[transceiver.kind] ?? [];
262
272
  }
263
273
  });
264
274
 
@@ -436,6 +446,9 @@ export class RTCPeerConnection extends EventTarget {
436
446
  forceTurn: this.config.iceTransportPolicy === "relay",
437
447
  portRange: this.config.icePortRange,
438
448
  interfaceAddresses: this.config.iceInterfaceAddresses,
449
+ filterStunResponse: this.config.iceFilterStunResponse,
450
+ useIpv4: this.config.iceUseIpv4,
451
+ useIpv6: this.config.iceUseIpv6,
439
452
  });
440
453
  if (existing) {
441
454
  iceGatherer.connection.localUserName = existing.connection.localUserName;
@@ -1060,6 +1073,7 @@ export class RTCPeerConnection extends EventTarget {
1060
1073
  transceiver,
1061
1074
  receiver: transceiver.receiver,
1062
1075
  };
1076
+ this.onTrack.execute(track);
1063
1077
  this.emit("track", event);
1064
1078
  if (this.ontrack) this.ontrack(event);
1065
1079
  }
@@ -1508,6 +1522,13 @@ export interface PeerConfig {
1508
1522
  /**Minimum port and Maximum port must not be the same value */
1509
1523
  icePortRange: [number, number] | undefined;
1510
1524
  iceInterfaceAddresses: InterfaceAddresses | undefined;
1525
+ iceUseIpv4: boolean;
1526
+ iceUseIpv6: boolean;
1527
+ /** If provided, is called on each STUN request.
1528
+ * Return `true` if a STUN response should be sent, false if it should be skipped. */
1529
+ iceFilterStunResponse:
1530
+ | ((message: Message, addr: Address, protocol: Protocol) => boolean)
1531
+ | undefined;
1511
1532
  dtls: Partial<{
1512
1533
  keys: DtlsKeys;
1513
1534
  }>;
@@ -1572,6 +1593,9 @@ export const defaultPeerConfig: PeerConfig = {
1572
1593
  iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
1573
1594
  icePortRange: undefined,
1574
1595
  iceInterfaceAddresses: undefined,
1596
+ iceUseIpv4: true,
1597
+ iceUseIpv6: true,
1598
+ iceFilterStunResponse: undefined,
1575
1599
  dtls: {},
1576
1600
  bundlePolicy: "max-compat",
1577
1601
  debug: {},