werift 0.19.6 → 0.19.8

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.
@@ -1,30 +1,37 @@
1
1
  import Event from "rx.mini";
2
- import type { PassThrough } from "stream";
3
2
  import type { MediaStreamTrack } from "../../media/track";
4
- import type { MediaWriter } from "./writer";
3
+ import type { MediaWriter, StreamEvent } from "./writer";
5
4
  export declare class MediaRecorder {
6
- props: Partial<MediaRecorderOptions> & {
5
+ props: Partial<MediaRecorderOptions> & ({
7
6
  numOfTracks: number;
8
- } & ({
7
+ tracks?: MediaStreamTrack[];
8
+ } | {
9
+ numOfTracks?: number;
10
+ tracks: MediaStreamTrack[];
11
+ }) & ({
9
12
  path: string;
10
- stream?: PassThrough;
13
+ stream?: StreamEvent;
11
14
  } | {
12
15
  path?: string;
13
- stream: PassThrough;
16
+ stream: StreamEvent;
14
17
  });
15
18
  writer: MediaWriter;
16
19
  ext?: string;
17
20
  tracks: MediaStreamTrack[];
18
21
  started: boolean;
19
22
  onError: Event<[Error]>;
20
- constructor(props: Partial<MediaRecorderOptions> & {
23
+ constructor(props: Partial<MediaRecorderOptions> & ({
21
24
  numOfTracks: number;
22
- } & ({
25
+ tracks?: MediaStreamTrack[];
26
+ } | {
27
+ numOfTracks?: number;
28
+ tracks: MediaStreamTrack[];
29
+ }) & ({
23
30
  path: string;
24
- stream?: PassThrough;
31
+ stream?: StreamEvent;
25
32
  } | {
26
33
  path?: string;
27
- stream: PassThrough;
34
+ stream: StreamEvent;
28
35
  }));
29
36
  addTrack(track: MediaStreamTrack): Promise<void>;
30
37
  private start;
@@ -35,6 +42,7 @@ export interface MediaRecorderOptions {
35
42
  height: number;
36
43
  jitterBufferLatency: number;
37
44
  jitterBufferSize: number;
45
+ disableLipSync: boolean;
38
46
  waitForKeyframe: boolean;
39
47
  defaultDuration: number;
40
48
  tracks: MediaStreamTrack[];
@@ -68,7 +68,8 @@ class MediaRecorder {
68
68
  stream: stream,
69
69
  });
70
70
  }
71
- if (this.tracks.length === props.numOfTracks) {
71
+ if (this.tracks.length > 0) {
72
+ this.props.numOfTracks = this.tracks.length;
72
73
  this.start().catch((error) => {
73
74
  this.onError.execute(error);
74
75
  });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/nonstandard/recorder/index.ts"],"names":[],"mappings":";;;;;;AAAA,sDAA4B;AAK5B,wCAA4C;AAE5C,MAAa,aAAa;IAOxB,YACS,KAWJ;QAXH;;;;mBAAO,KAAK;WAWT;QAlBL;;;;;WAAoB;QACpB;;;;;WAAa;QACb;;;;mBAA6B,EAAE;WAAC;QAChC;;;;mBAAU,KAAK;WAAC;QAChB;;;;mBAAU,IAAI,iBAAK,EAAW;WAAC;QAgB7B,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;QAE1C,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;QAE/B,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxC,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,EAAE;gBAClB,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC;oBACjB,KAAK,MAAM;wBACT,OAAO,IAAI,kBAAW,CAAC;4BACrB,GAAG,KAAK;4BACR,IAAI,EAAE,IAAK;4BACX,MAAM,EAAE,MAAO;yBAChB,CAAC,CAAC;oBACL;wBACE,MAAM,IAAI,KAAK,EAAE,CAAC;gBACtB,CAAC;YACH,CAAC,CAAC,EAAE,CAAC;QACP,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,GAAG,IAAI,kBAAW,CAAC;gBAC5B,GAAG,KAAK;gBACR,IAAI,EAAE,IAAK;gBACX,MAAM,EAAE,MAAO;aAChB,CAAC,CAAC;QACL,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC;YAC7C,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBAC3B,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAuB;QACpC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAEO,KAAK,CAAC,KAAK;QACjB,IACE,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,WAAW;YAC7C,IAAI,CAAC,OAAO,KAAK,KAAK,EACtB,CAAC;YACD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC3B,CAAC;CACF;AAxED,sCAwEC","sourcesContent":["import Event from \"rx.mini\";\n\nimport type { PassThrough } from \"stream\";\nimport type { MediaStreamTrack } from \"../../media/track\";\nimport type { MediaWriter } from \"./writer\";\nimport { WebmFactory } from \"./writer/webm\";\n\nexport class MediaRecorder {\n writer: MediaWriter;\n ext?: string;\n tracks: MediaStreamTrack[] = [];\n started = false;\n onError = new Event<[Error]>();\n\n constructor(\n public props: Partial<MediaRecorderOptions> & {\n numOfTracks: number;\n } & (\n | {\n path: string;\n stream?: PassThrough;\n }\n | {\n path?: string;\n stream: PassThrough;\n }\n ),\n ) {\n this.tracks = props.tracks ?? this.tracks;\n\n const { path, stream } = props;\n\n if (path) {\n this.ext = path.split(\".\").slice(-1)[0];\n this.writer = (() => {\n switch (this.ext) {\n case \"webm\":\n return new WebmFactory({\n ...props,\n path: path!,\n stream: stream!,\n });\n default:\n throw new Error();\n }\n })();\n } else {\n this.writer = new WebmFactory({\n ...props,\n path: path!,\n stream: stream!,\n });\n }\n\n if (this.tracks.length === props.numOfTracks) {\n this.start().catch((error) => {\n this.onError.execute(error);\n });\n }\n }\n\n async addTrack(track: MediaStreamTrack) {\n this.tracks.push(track);\n await this.start();\n }\n\n private async start() {\n if (\n this.tracks.length === this.props.numOfTracks &&\n this.started === false\n ) {\n this.started = true;\n await this.writer.start(this.tracks);\n }\n }\n\n async stop() {\n await this.writer.stop();\n }\n}\n\nexport interface MediaRecorderOptions {\n width: number;\n height: number;\n jitterBufferLatency: number;\n jitterBufferSize: number;\n waitForKeyframe: boolean;\n defaultDuration: number;\n tracks: MediaStreamTrack[];\n disableNtp: boolean;\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/nonstandard/recorder/index.ts"],"names":[],"mappings":";;;;;;AAAA,sDAA4B;AAG5B,wCAA4C;AAE5C,MAAa,aAAa;IAOxB,YACS,KAoBJ;QApBH;;;;mBAAO,KAAK;WAoBT;QA3BL;;;;;WAAoB;QACpB;;;;;WAAa;QACb;;;;mBAA6B,EAAE;WAAC;QAChC;;;;mBAAU,KAAK;WAAC;QAChB;;;;mBAAU,IAAI,iBAAK,EAAW;WAAC;QAyB7B,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;QAE1C,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;QAE/B,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxC,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,EAAE;gBAClB,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC;oBACjB,KAAK,MAAM;wBACT,OAAO,IAAI,kBAAW,CAAC;4BACrB,GAAG,KAAK;4BACR,IAAI,EAAE,IAAK;4BACX,MAAM,EAAE,MAAO;yBAChB,CAAC,CAAC;oBACL;wBACE,MAAM,IAAI,KAAK,EAAE,CAAC;gBACtB,CAAC;YACH,CAAC,CAAC,EAAE,CAAC;QACP,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,GAAG,IAAI,kBAAW,CAAC;gBAC5B,GAAG,KAAK;gBACR,IAAI,EAAE,IAAK;gBACX,MAAM,EAAE,MAAO;aAChB,CAAC,CAAC;QACL,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;YAC5C,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBAC3B,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAuB;QACpC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAEO,KAAK,CAAC,KAAK;QACjB,IACE,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,WAAW;YAC7C,IAAI,CAAC,OAAO,KAAK,KAAK,EACtB,CAAC;YACD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC3B,CAAC;CACF;AAlFD,sCAkFC","sourcesContent":["import Event from \"rx.mini\";\nimport type { MediaStreamTrack } from \"../../media/track\";\nimport type { MediaWriter, StreamEvent } from \"./writer\";\nimport { WebmFactory } from \"./writer/webm\";\n\nexport class MediaRecorder {\n writer: MediaWriter;\n ext?: string;\n tracks: MediaStreamTrack[] = [];\n started = false;\n onError = new Event<[Error]>();\n\n constructor(\n public props: Partial<MediaRecorderOptions> &\n (\n | {\n numOfTracks: number;\n tracks?: MediaStreamTrack[];\n }\n | {\n numOfTracks?: number;\n tracks: MediaStreamTrack[];\n }\n ) &\n (\n | {\n path: string;\n stream?: StreamEvent;\n }\n | {\n path?: string;\n stream: StreamEvent;\n }\n ),\n ) {\n this.tracks = props.tracks ?? this.tracks;\n\n const { path, stream } = props;\n\n if (path) {\n this.ext = path.split(\".\").slice(-1)[0];\n this.writer = (() => {\n switch (this.ext) {\n case \"webm\":\n return new WebmFactory({\n ...props,\n path: path!,\n stream: stream!,\n });\n default:\n throw new Error();\n }\n })();\n } else {\n this.writer = new WebmFactory({\n ...props,\n path: path!,\n stream: stream!,\n });\n }\n\n if (this.tracks.length > 0) {\n this.props.numOfTracks = this.tracks.length;\n this.start().catch((error) => {\n this.onError.execute(error);\n });\n }\n }\n\n async addTrack(track: MediaStreamTrack) {\n this.tracks.push(track);\n await this.start();\n }\n\n private async start() {\n if (\n this.tracks.length === this.props.numOfTracks &&\n this.started === false\n ) {\n this.started = true;\n await this.writer.start(this.tracks);\n }\n }\n\n async stop() {\n await this.writer.stop();\n }\n}\n\nexport interface MediaRecorderOptions {\n width: number;\n height: number;\n jitterBufferLatency: number;\n jitterBufferSize: number;\n disableLipSync: boolean;\n waitForKeyframe: boolean;\n defaultDuration: number;\n tracks: MediaStreamTrack[];\n disableNtp: boolean;\n}\n"]}
@@ -1,21 +1,23 @@
1
- import type { PassThrough } from "stream";
1
+ import type { Event } from "rx.mini";
2
2
  import type { MediaRecorderOptions } from "..";
3
3
  import type { MediaStreamTrack } from "../../..";
4
+ import type { WebmOutput } from "../../../../../rtp/src/extra";
4
5
  export declare abstract class MediaWriter {
5
6
  protected props: Partial<MediaRecorderOptions> & {
6
7
  path: string;
7
- stream?: PassThrough;
8
+ stream?: StreamEvent;
8
9
  } & {
9
10
  path?: string;
10
- stream: PassThrough;
11
+ stream: StreamEvent;
11
12
  };
12
13
  constructor(props: Partial<MediaRecorderOptions> & {
13
14
  path: string;
14
- stream?: PassThrough;
15
+ stream?: StreamEvent;
15
16
  } & {
16
17
  path?: string;
17
- stream: PassThrough;
18
+ stream: StreamEvent;
18
19
  });
19
20
  start(tracks: MediaStreamTrack[]): Promise<void>;
20
21
  stop(): Promise<void>;
21
22
  }
23
+ export type StreamEvent = Event<[WebmOutput]>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/nonstandard/recorder/writer/index.ts"],"names":[],"mappings":";;;AAIA,MAAsB,WAAW;IAC/B,YACY,KAGgC;QAH1C;;;;mBAAU,KAAK;WAG2B;IACzC,CAAC;IAEJ,KAAK,CAAC,KAAK,CAAC,MAA0B,IAAG,CAAC;IAE1C,KAAK,CAAC,IAAI,KAAI,CAAC;CAChB;AAXD,kCAWC","sourcesContent":["import type { PassThrough } from \"stream\";\nimport type { MediaRecorderOptions } from \"..\";\nimport type { MediaStreamTrack } from \"../../..\";\n\nexport abstract class MediaWriter {\n constructor(\n protected props: Partial<MediaRecorderOptions> & {\n path: string;\n stream?: PassThrough;\n } & { path?: string; stream: PassThrough },\n ) {}\n\n async start(tracks: MediaStreamTrack[]) {}\n\n async stop() {}\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/nonstandard/recorder/writer/index.ts"],"names":[],"mappings":";;;AAKA,MAAsB,WAAW;IAC/B,YACY,KAGgC;QAH1C;;;;mBAAU,KAAK;WAG2B;IACzC,CAAC;IAEJ,KAAK,CAAC,KAAK,CAAC,MAA0B,IAAG,CAAC;IAE1C,KAAK,CAAC,IAAI,KAAI,CAAC;CAChB;AAXD,kCAWC","sourcesContent":["import type { Event } from \"rx.mini\";\nimport type { MediaRecorderOptions } from \"..\";\nimport type { MediaStreamTrack } from \"../../..\";\nimport type { WebmOutput } from \"../../../../../rtp/src/extra\";\n\nexport abstract class MediaWriter {\n constructor(\n protected props: Partial<MediaRecorderOptions> & {\n path: string;\n stream?: StreamEvent;\n } & { path?: string; stream: StreamEvent },\n ) {}\n\n async start(tracks: MediaStreamTrack[]) {}\n\n async stop() {}\n}\n\nexport type StreamEvent = Event<[WebmOutput]>;\n"]}
@@ -94,21 +94,34 @@ class WebmFactory extends _1.MediaWriter {
94
94
  const depacketizer = new extra_1.DepacketizeCallback(codec, {
95
95
  isFinalPacketInSequence: (h) => h.marker,
96
96
  });
97
- const jitterBuffer = new extra_1.JitterBufferCallback(clockRate);
97
+ const jitterBuffer = new extra_1.JitterBufferCallback(clockRate, {
98
+ bufferSize: this.props.jitterBufferSize,
99
+ latency: this.props.jitterBufferLatency,
100
+ });
98
101
  rtpSource.pipe(jitterBuffer.input);
99
102
  rtcpSource.pipe(time.input);
100
103
  jitterBuffer.pipe(time.input);
101
104
  time.pipe(depacketizer.input);
102
- depacketizer.pipe(lipsync.inputVideo);
103
- lipsync.pipeVideo(webm.inputVideo);
105
+ if (this.props.disableLipSync) {
106
+ depacketizer.pipe(webm.inputVideo);
107
+ }
108
+ else {
109
+ depacketizer.pipe(lipsync.inputVideo);
110
+ lipsync.pipeVideo(webm.inputVideo);
111
+ }
104
112
  }
105
113
  else {
106
114
  const depacketizer = new extra_1.DepacketizeCallback(codec);
107
115
  rtpSource.pipe(time.input);
108
116
  rtcpSource.pipe(time.input);
109
117
  time.pipe(depacketizer.input);
110
- depacketizer.pipe(lipsync.inputAudio);
111
- lipsync.pipeAudio(webm.inputAudio);
118
+ if (this.props.disableLipSync) {
119
+ depacketizer.pipe(webm.inputAudio);
120
+ }
121
+ else {
122
+ depacketizer.pipe(lipsync.inputAudio);
123
+ lipsync.pipeAudio(webm.inputAudio);
124
+ }
112
125
  }
113
126
  return rtpSource;
114
127
  });
@@ -117,7 +130,7 @@ class WebmFactory extends _1.MediaWriter {
117
130
  }
118
131
  else if (this.props.stream) {
119
132
  webm.pipe(async (o) => {
120
- this.props.stream.write(o);
133
+ this.props.stream.execute(o);
121
134
  });
122
135
  }
123
136
  }
@@ -1 +1 @@
1
- {"version":3,"file":"webm.js","sourceRoot":"","sources":["../../../../../../src/nonstandard/recorder/writer/webm.ts"],"names":[],"mappings":"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","sourcesContent":["import { unlink } from \"fs/promises\";\nimport { EventDisposer } from \"rx.mini\";\n\nimport { MediaWriter } from \".\";\nimport { type MediaStreamTrack, WeriftError } from \"../../..\";\nimport {\n DepacketizeCallback,\n JitterBufferCallback,\n LipsyncCallback,\n NtpTimeCallback,\n RtcpSourceCallback,\n RtpSourceCallback,\n RtpTimeCallback,\n type SupportedCodec,\n WebmCallback,\n saveToFileSystem,\n} from \"../../../../../rtp/src/extra\";\n\nconst sourcePath = \"packages/webrtc/src/nonstandard/recorder/writer/webm.ts\";\n\nexport class WebmFactory extends MediaWriter {\n rtpSources: RtpSourceCallback[] = [];\n\n unSubscribers = new EventDisposer();\n\n async start(tracks: MediaStreamTrack[]) {\n if (this.props.path) {\n await unlink(this.props.path).catch((e) => e);\n }\n\n const inputTracks = tracks.map((track, i) => {\n const trackNumber = i + 1;\n const payloadType = track.codec!.payloadType;\n\n if (track.kind === \"video\") {\n const codec = ((): SupportedCodec => {\n switch (track.codec?.name.toLowerCase() as SupportedVideoCodec) {\n case \"vp8\":\n return \"VP8\";\n case \"vp9\":\n return \"VP9\";\n case \"h264\":\n return \"MPEG4/ISO/AVC\";\n case \"av1x\":\n return \"AV1\";\n default:\n throw new WeriftError({\n message: \"unsupported codec\",\n payload: { track, path: sourcePath },\n });\n }\n })();\n return {\n kind: \"video\" as const,\n codec,\n clockRate: 90000,\n trackNumber,\n width: this.props.width ?? 640,\n height: this.props.height ?? 360,\n payloadType,\n track,\n };\n } else {\n return {\n kind: \"audio\" as const,\n codec: \"OPUS\" as const,\n clockRate: 48000,\n trackNumber,\n payloadType,\n track,\n };\n }\n });\n\n const webm = new WebmCallback(inputTracks, {\n duration: this.props.defaultDuration ?? 1000 * 60 * 60 * 24,\n });\n const lipsync = new LipsyncCallback();\n\n this.rtpSources = inputTracks.map(({ track, clockRate, codec }) => {\n const rtpSource = new RtpSourceCallback();\n const rtcpSource = new RtcpSourceCallback();\n track.onReceiveRtp\n .subscribe((rtp) => {\n rtpSource.input(rtp.clone());\n })\n .disposer(this.unSubscribers);\n track.onReceiveRtcp\n .subscribe((rtcp) => {\n rtcpSource.input(rtcp);\n })\n .disposer(this.unSubscribers);\n const time = this.props.disableNtp\n ? new RtpTimeCallback(clockRate)\n : new NtpTimeCallback(clockRate);\n\n if (track.kind === \"video\") {\n const depacketizer = new DepacketizeCallback(codec, {\n isFinalPacketInSequence: (h) => h.marker,\n });\n const jitterBuffer = new JitterBufferCallback(clockRate);\n\n rtpSource.pipe(jitterBuffer.input);\n rtcpSource.pipe(time.input);\n\n jitterBuffer.pipe(time.input);\n time.pipe(depacketizer.input);\n depacketizer.pipe(lipsync.inputVideo);\n lipsync.pipeVideo(webm.inputVideo);\n } else {\n const depacketizer = new DepacketizeCallback(codec);\n\n rtpSource.pipe(time.input);\n rtcpSource.pipe(time.input);\n\n time.pipe(depacketizer.input);\n depacketizer.pipe(lipsync.inputAudio);\n lipsync.pipeAudio(webm.inputAudio);\n }\n\n return rtpSource;\n });\n if (this.props.path) {\n webm.pipe(saveToFileSystem(this.props.path));\n } else if (this.props.stream) {\n webm.pipe(async (o) => {\n this.props.stream.write(o);\n });\n }\n }\n\n async stop() {\n await Promise.all(this.rtpSources.map((r) => r.stop()));\n this.unSubscribers.dispose();\n }\n}\n\nconst supportedVideoCodecs = [\"h264\", \"vp8\", \"vp9\", \"av1x\"] as const;\ntype SupportedVideoCodec = (typeof supportedVideoCodecs)[number];\n"]}
1
+ {"version":3,"file":"webm.js","sourceRoot":"","sources":["../../../../../../src/nonstandard/recorder/writer/webm.ts"],"names":[],"mappings":"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","sourcesContent":["import { unlink } from \"fs/promises\";\nimport { EventDisposer } from \"rx.mini\";\n\nimport { MediaWriter } from \".\";\nimport { type MediaStreamTrack, WeriftError } from \"../../..\";\nimport {\n DepacketizeCallback,\n JitterBufferCallback,\n LipsyncCallback,\n NtpTimeCallback,\n RtcpSourceCallback,\n RtpSourceCallback,\n RtpTimeCallback,\n type SupportedCodec,\n WebmCallback,\n saveToFileSystem,\n} from \"../../../../../rtp/src/extra\";\n\nconst sourcePath = \"packages/webrtc/src/nonstandard/recorder/writer/webm.ts\";\n\nexport class WebmFactory extends MediaWriter {\n rtpSources: RtpSourceCallback[] = [];\n\n unSubscribers = new EventDisposer();\n\n async start(tracks: MediaStreamTrack[]) {\n if (this.props.path) {\n await unlink(this.props.path).catch((e) => e);\n }\n\n const inputTracks = tracks.map((track, i) => {\n const trackNumber = i + 1;\n const payloadType = track.codec!.payloadType;\n\n if (track.kind === \"video\") {\n const codec = ((): SupportedCodec => {\n switch (track.codec?.name.toLowerCase() as SupportedVideoCodec) {\n case \"vp8\":\n return \"VP8\";\n case \"vp9\":\n return \"VP9\";\n case \"h264\":\n return \"MPEG4/ISO/AVC\";\n case \"av1x\":\n return \"AV1\";\n default:\n throw new WeriftError({\n message: \"unsupported codec\",\n payload: { track, path: sourcePath },\n });\n }\n })();\n return {\n kind: \"video\" as const,\n codec,\n clockRate: 90000,\n trackNumber,\n width: this.props.width ?? 640,\n height: this.props.height ?? 360,\n payloadType,\n track,\n };\n } else {\n return {\n kind: \"audio\" as const,\n codec: \"OPUS\" as const,\n clockRate: 48000,\n trackNumber,\n payloadType,\n track,\n };\n }\n });\n\n const webm = new WebmCallback(inputTracks, {\n duration: this.props.defaultDuration ?? 1000 * 60 * 60 * 24,\n });\n const lipsync = new LipsyncCallback();\n\n this.rtpSources = inputTracks.map(({ track, clockRate, codec }) => {\n const rtpSource = new RtpSourceCallback();\n const rtcpSource = new RtcpSourceCallback();\n track.onReceiveRtp\n .subscribe((rtp) => {\n rtpSource.input(rtp.clone());\n })\n .disposer(this.unSubscribers);\n track.onReceiveRtcp\n .subscribe((rtcp) => {\n rtcpSource.input(rtcp);\n })\n .disposer(this.unSubscribers);\n const time = this.props.disableNtp\n ? new RtpTimeCallback(clockRate)\n : new NtpTimeCallback(clockRate);\n\n if (track.kind === \"video\") {\n const depacketizer = new DepacketizeCallback(codec, {\n isFinalPacketInSequence: (h) => h.marker,\n });\n const jitterBuffer = new JitterBufferCallback(clockRate, {\n bufferSize: this.props.jitterBufferSize,\n latency: this.props.jitterBufferLatency,\n });\n\n rtpSource.pipe(jitterBuffer.input);\n rtcpSource.pipe(time.input);\n\n jitterBuffer.pipe(time.input);\n time.pipe(depacketizer.input);\n if (this.props.disableLipSync) {\n depacketizer.pipe(webm.inputVideo);\n } else {\n depacketizer.pipe(lipsync.inputVideo);\n lipsync.pipeVideo(webm.inputVideo);\n }\n } else {\n const depacketizer = new DepacketizeCallback(codec);\n\n rtpSource.pipe(time.input);\n rtcpSource.pipe(time.input);\n\n time.pipe(depacketizer.input);\n if (this.props.disableLipSync) {\n depacketizer.pipe(webm.inputAudio);\n } else {\n depacketizer.pipe(lipsync.inputAudio);\n lipsync.pipeAudio(webm.inputAudio);\n }\n }\n\n return rtpSource;\n });\n if (this.props.path) {\n webm.pipe(saveToFileSystem(this.props.path));\n } else if (this.props.stream) {\n webm.pipe(async (o) => {\n this.props.stream.execute(o);\n });\n }\n }\n\n async stop() {\n await Promise.all(this.rtpSources.map((r) => r.stop()));\n this.unSubscribers.dispose();\n }\n}\n\nconst supportedVideoCodecs = [\"h264\", \"vp8\", \"vp9\", \"av1x\"] as const;\ntype SupportedVideoCodec = (typeof supportedVideoCodecs)[number];\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "werift",
3
- "version": "0.19.6",
3
+ "version": "0.19.8",
4
4
  "description": "WebRTC Implementation for TypeScript (Node.js)",
5
5
  "keywords": [
6
6
  "WebRTC",
@@ -1,8 +1,6 @@
1
1
  import Event from "rx.mini";
2
-
3
- import type { PassThrough } from "stream";
4
2
  import type { MediaStreamTrack } from "../../media/track";
5
- import type { MediaWriter } from "./writer";
3
+ import type { MediaWriter, StreamEvent } from "./writer";
6
4
  import { WebmFactory } from "./writer/webm";
7
5
 
8
6
  export class MediaRecorder {
@@ -13,16 +11,25 @@ export class MediaRecorder {
13
11
  onError = new Event<[Error]>();
14
12
 
15
13
  constructor(
16
- public props: Partial<MediaRecorderOptions> & {
17
- numOfTracks: number;
18
- } & (
14
+ public props: Partial<MediaRecorderOptions> &
15
+ (
16
+ | {
17
+ numOfTracks: number;
18
+ tracks?: MediaStreamTrack[];
19
+ }
20
+ | {
21
+ numOfTracks?: number;
22
+ tracks: MediaStreamTrack[];
23
+ }
24
+ ) &
25
+ (
19
26
  | {
20
27
  path: string;
21
- stream?: PassThrough;
28
+ stream?: StreamEvent;
22
29
  }
23
30
  | {
24
31
  path?: string;
25
- stream: PassThrough;
32
+ stream: StreamEvent;
26
33
  }
27
34
  ),
28
35
  ) {
@@ -52,7 +59,8 @@ export class MediaRecorder {
52
59
  });
53
60
  }
54
61
 
55
- if (this.tracks.length === props.numOfTracks) {
62
+ if (this.tracks.length > 0) {
63
+ this.props.numOfTracks = this.tracks.length;
56
64
  this.start().catch((error) => {
57
65
  this.onError.execute(error);
58
66
  });
@@ -84,6 +92,7 @@ export interface MediaRecorderOptions {
84
92
  height: number;
85
93
  jitterBufferLatency: number;
86
94
  jitterBufferSize: number;
95
+ disableLipSync: boolean;
87
96
  waitForKeyframe: boolean;
88
97
  defaultDuration: number;
89
98
  tracks: MediaStreamTrack[];
@@ -1,16 +1,19 @@
1
- import type { PassThrough } from "stream";
1
+ import type { Event } from "rx.mini";
2
2
  import type { MediaRecorderOptions } from "..";
3
3
  import type { MediaStreamTrack } from "../../..";
4
+ import type { WebmOutput } from "../../../../../rtp/src/extra";
4
5
 
5
6
  export abstract class MediaWriter {
6
7
  constructor(
7
8
  protected props: Partial<MediaRecorderOptions> & {
8
9
  path: string;
9
- stream?: PassThrough;
10
- } & { path?: string; stream: PassThrough },
10
+ stream?: StreamEvent;
11
+ } & { path?: string; stream: StreamEvent },
11
12
  ) {}
12
13
 
13
14
  async start(tracks: MediaStreamTrack[]) {}
14
15
 
15
16
  async stop() {}
16
17
  }
18
+
19
+ export type StreamEvent = Event<[WebmOutput]>;
@@ -98,15 +98,22 @@ export class WebmFactory extends MediaWriter {
98
98
  const depacketizer = new DepacketizeCallback(codec, {
99
99
  isFinalPacketInSequence: (h) => h.marker,
100
100
  });
101
- const jitterBuffer = new JitterBufferCallback(clockRate);
101
+ const jitterBuffer = new JitterBufferCallback(clockRate, {
102
+ bufferSize: this.props.jitterBufferSize,
103
+ latency: this.props.jitterBufferLatency,
104
+ });
102
105
 
103
106
  rtpSource.pipe(jitterBuffer.input);
104
107
  rtcpSource.pipe(time.input);
105
108
 
106
109
  jitterBuffer.pipe(time.input);
107
110
  time.pipe(depacketizer.input);
108
- depacketizer.pipe(lipsync.inputVideo);
109
- lipsync.pipeVideo(webm.inputVideo);
111
+ if (this.props.disableLipSync) {
112
+ depacketizer.pipe(webm.inputVideo);
113
+ } else {
114
+ depacketizer.pipe(lipsync.inputVideo);
115
+ lipsync.pipeVideo(webm.inputVideo);
116
+ }
110
117
  } else {
111
118
  const depacketizer = new DepacketizeCallback(codec);
112
119
 
@@ -114,8 +121,12 @@ export class WebmFactory extends MediaWriter {
114
121
  rtcpSource.pipe(time.input);
115
122
 
116
123
  time.pipe(depacketizer.input);
117
- depacketizer.pipe(lipsync.inputAudio);
118
- lipsync.pipeAudio(webm.inputAudio);
124
+ if (this.props.disableLipSync) {
125
+ depacketizer.pipe(webm.inputAudio);
126
+ } else {
127
+ depacketizer.pipe(lipsync.inputAudio);
128
+ lipsync.pipeAudio(webm.inputAudio);
129
+ }
119
130
  }
120
131
 
121
132
  return rtpSource;
@@ -124,7 +135,7 @@ export class WebmFactory extends MediaWriter {
124
135
  webm.pipe(saveToFileSystem(this.props.path));
125
136
  } else if (this.props.stream) {
126
137
  webm.pipe(async (o) => {
127
- this.props.stream.write(o);
138
+ this.props.stream.execute(o);
128
139
  });
129
140
  }
130
141
  }