werift 0.17.2 → 0.17.3

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.
@@ -18,11 +18,14 @@ export declare class AVBufferBase {
18
18
  })[][];
19
19
  stopped: boolean;
20
20
  private interval;
21
+ private started;
21
22
  constructor(audioOutput: (output: AVBufferOutput) => void, videoOutput: (output: AVBufferOutput) => void, options?: Partial<AvBufferOptions>);
23
+ private start;
22
24
  processAudioInput: (input: AVBufferInput) => void;
23
25
  processVideoInput: (input: AVBufferInput) => void;
24
26
  private calcElapsed;
25
27
  }
26
28
  export interface AvBufferOptions {
27
29
  interval: number;
30
+ bufferLength: number;
28
31
  }
@@ -8,7 +8,7 @@ class AVBufferBase {
8
8
  this.audioOutput = audioOutput;
9
9
  this.videoOutput = videoOutput;
10
10
  this.options = options;
11
- this.bufferLength = 50;
11
+ this.bufferLength = this.options.bufferLength ?? 50;
12
12
  this.audioBuffer = [
13
13
  ...new Array(this.bufferLength),
14
14
  ].map(() => []);
@@ -17,6 +17,7 @@ class AVBufferBase {
17
17
  ].map(() => []);
18
18
  this.stopped = false;
19
19
  this.interval = this.options.interval ?? 500;
20
+ this.started = false;
20
21
  this.processAudioInput = (input) => {
21
22
  if (!input.frame) {
22
23
  this.stopped = true;
@@ -35,6 +36,7 @@ class AVBufferBase {
35
36
  }
36
37
  const index = (0, src_1.int)(elapsed / this.interval) % this.bufferLength;
37
38
  this.audioBuffer[index].push({ ...input, elapsed, kind: "audio" });
39
+ this.start();
38
40
  };
39
41
  this.processVideoInput = (input) => {
40
42
  if (!input.frame) {
@@ -54,20 +56,26 @@ class AVBufferBase {
54
56
  }
55
57
  const index = (0, src_1.int)(elapsed / this.interval) % this.bufferLength;
56
58
  this.videoBuffer[index].push({ ...input, elapsed, kind: "video" });
59
+ this.start();
57
60
  };
61
+ }
62
+ start() {
63
+ if (this.started) {
64
+ return;
65
+ }
66
+ this.started = true;
58
67
  let index = 0;
59
68
  setInterval(() => {
60
69
  const joined = [...this.audioBuffer[index], ...this.videoBuffer[index]];
61
70
  const sorted = joined.sort((a, b) => a.elapsed - b.elapsed);
62
71
  this.audioBuffer[index] = [];
63
72
  this.videoBuffer[index] = [];
64
- // console.log(sorted.map((v) => ({ elapsed: v.elapsed, kind: v.kind })));
65
73
  for (const output of sorted) {
66
74
  if (output.kind === "audio") {
67
- audioOutput(output);
75
+ this.audioOutput(output);
68
76
  }
69
77
  else {
70
- videoOutput(output);
78
+ this.videoOutput(output);
71
79
  }
72
80
  }
73
81
  index++;
@@ -1 +1 @@
1
- {"version":3,"file":"avBuffer.js","sourceRoot":"","sources":["../../../../../rtp/src/processor/avBuffer.ts"],"names":[],"mappings":"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","sourcesContent":["import { int } from \"../../../common/src\";\nimport { DepacketizerOutput } from \"./depacketizer\";\nimport { Max32Uint } from \"./webm\";\n\nexport type AVBufferInput = DepacketizerOutput;\n\nexport type AVBufferOutput = AVBufferInput;\n\nexport class AVBufferBase {\n bufferLength = 50;\n baseAudioTimestamp?: number;\n baseVideoTimestamp?: number;\n audioBuffer: (AVBufferInput & { elapsed: number; kind: string })[][] = [\n ...new Array(this.bufferLength),\n ].map(() => []);\n videoBuffer: (AVBufferInput & { elapsed: number; kind: string })[][] = [\n ...new Array(this.bufferLength),\n ].map(() => []);\n stopped = false;\n private interval = this.options.interval ?? 500;\n\n constructor(\n private audioOutput: (output: AVBufferOutput) => void,\n private videoOutput: (output: AVBufferOutput) => void,\n private options: Partial<AvBufferOptions> = {}\n ) {\n let index = 0;\n setInterval(() => {\n const joined = [...this.audioBuffer[index], ...this.videoBuffer[index]];\n const sorted = joined.sort((a, b) => a.elapsed - b.elapsed);\n this.audioBuffer[index] = [];\n this.videoBuffer[index] = [];\n\n // console.log(sorted.map((v) => ({ elapsed: v.elapsed, kind: v.kind })));\n\n for (const output of sorted) {\n if (output.kind === \"audio\") {\n audioOutput(output);\n } else {\n videoOutput(output);\n }\n }\n\n index++;\n if (index === this.bufferLength) {\n index = 0;\n }\n }, this.interval);\n }\n\n processAudioInput = (input: AVBufferInput) => {\n if (!input.frame) {\n this.stopped = true;\n this.audioOutput(input);\n return;\n }\n if (this.stopped) {\n return;\n }\n\n if (this.baseAudioTimestamp == undefined) {\n this.baseAudioTimestamp = input.frame?.timestamp;\n }\n\n const { elapsed, rotate } = this.calcElapsed(\n this.baseAudioTimestamp,\n input.frame.timestamp,\n 48000\n );\n if (rotate) {\n this.baseAudioTimestamp = input.frame?.timestamp;\n }\n\n const index = int(elapsed / this.interval) % this.bufferLength;\n this.audioBuffer[index].push({ ...input, elapsed, kind: \"audio\" });\n };\n\n processVideoInput = (input: AVBufferInput) => {\n if (!input.frame) {\n this.stopped = true;\n this.videoOutput(input);\n return;\n }\n if (this.stopped) {\n return;\n }\n\n if (this.baseVideoTimestamp == undefined) {\n this.baseVideoTimestamp = input.frame?.timestamp;\n }\n\n const { elapsed, rotate } = this.calcElapsed(\n this.baseVideoTimestamp,\n input.frame.timestamp,\n 90000\n );\n if (rotate) {\n this.baseVideoTimestamp = input.frame?.timestamp;\n }\n\n const index = int(elapsed / this.interval) % this.bufferLength;\n this.videoBuffer[index].push({ ...input, elapsed, kind: \"video\" });\n };\n\n private calcElapsed(base: number, timestamp: number, clockRate: number) {\n const rotate = Math.abs(timestamp - base) > (Max32Uint / 4) * 3;\n if (rotate) {\n console.log(rotate);\n }\n\n const diff = rotate ? timestamp + Max32Uint - base : timestamp - base;\n /**ms */\n const elapsed = int((diff / clockRate) * 1000);\n return { elapsed, rotate };\n }\n}\n\nexport interface AvBufferOptions {\n interval: number;\n}\n"]}
1
+ {"version":3,"file":"avBuffer.js","sourceRoot":"","sources":["../../../../../rtp/src/processor/avBuffer.ts"],"names":[],"mappings":";;;AAAA,6CAA0C;AAE1C,iCAAmC;AAMnC,MAAa,YAAY;IAcvB,YACU,WAA6C,EAC7C,WAA6C,EAC7C,UAAoC,EAAE;QAFtC,gBAAW,GAAX,WAAW,CAAkC;QAC7C,gBAAW,GAAX,WAAW,CAAkC;QAC7C,YAAO,GAAP,OAAO,CAA+B;QAhBhD,iBAAY,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC;QAG/C,gBAAW,GAA4D;YACrE,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC;SAChC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAChB,gBAAW,GAA4D;YACrE,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC;SAChC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAChB,YAAO,GAAG,KAAK,CAAC;QACR,aAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,GAAG,CAAC;QACxC,YAAO,GAAG,KAAK,CAAC;QAoCxB,sBAAiB,GAAG,CAAC,KAAoB,EAAE,EAAE;YAC3C,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;gBAChB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;gBACpB,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBACxB,OAAO;aACR;YACD,IAAI,IAAI,CAAC,OAAO,EAAE;gBAChB,OAAO;aACR;YAED,IAAI,IAAI,CAAC,kBAAkB,IAAI,SAAS,EAAE;gBACxC,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC;aAClD;YAED,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAC1C,IAAI,CAAC,kBAAkB,EACvB,KAAK,CAAC,KAAK,CAAC,SAAS,EACrB,KAAK,CACN,CAAC;YACF,IAAI,MAAM,EAAE;gBACV,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC;aAClD;YAED,MAAM,KAAK,GAAG,IAAA,SAAG,EAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC;YAC/D,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YAEnE,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC,CAAC;QAEF,sBAAiB,GAAG,CAAC,KAAoB,EAAE,EAAE;YAC3C,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;gBAChB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;gBACpB,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBACxB,OAAO;aACR;YACD,IAAI,IAAI,CAAC,OAAO,EAAE;gBAChB,OAAO;aACR;YAED,IAAI,IAAI,CAAC,kBAAkB,IAAI,SAAS,EAAE;gBACxC,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC;aAClD;YAED,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAC1C,IAAI,CAAC,kBAAkB,EACvB,KAAK,CAAC,KAAK,CAAC,SAAS,EACrB,KAAK,CACN,CAAC;YACF,IAAI,MAAM,EAAE;gBACV,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC;aAClD;YAED,MAAM,KAAK,GAAG,IAAA,SAAG,EAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC;YAC/D,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YAEnE,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC,CAAC;IAtFC,CAAC;IAEI,KAAK;QACX,IAAI,IAAI,CAAC,OAAO,EAAE;YAChB,OAAO;SACR;QACD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QAEpB,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,WAAW,CAAC,GAAG,EAAE;YACf,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;YACxE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;YAC5D,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YAC7B,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YAE7B,KAAK,MAAM,MAAM,IAAI,MAAM,EAAE;gBAC3B,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE;oBAC3B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;iBAC1B;qBAAM;oBACL,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;iBAC1B;aACF;YAED,KAAK,EAAE,CAAC;YACR,IAAI,KAAK,KAAK,IAAI,CAAC,YAAY,EAAE;gBAC/B,KAAK,GAAG,CAAC,CAAC;aACX;QACH,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpB,CAAC;IA4DO,WAAW,CAAC,IAAY,EAAE,SAAiB,EAAE,SAAiB;QACpE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAS,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QAChE,IAAI,MAAM,EAAE;YACV,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;SACrB;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,GAAG,gBAAS,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC;QACtE,QAAQ;QACR,MAAM,OAAO,GAAG,IAAA,SAAG,EAAC,CAAC,IAAI,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;QAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAC7B,CAAC;CACF;AArHD,oCAqHC","sourcesContent":["import { int } from \"../../../common/src\";\nimport { DepacketizerOutput } from \"./depacketizer\";\nimport { Max32Uint } from \"./webm\";\n\nexport type AVBufferInput = DepacketizerOutput;\n\nexport type AVBufferOutput = AVBufferInput;\n\nexport class AVBufferBase {\n bufferLength = this.options.bufferLength ?? 50;\n baseAudioTimestamp?: number;\n baseVideoTimestamp?: number;\n audioBuffer: (AVBufferInput & { elapsed: number; kind: string })[][] = [\n ...new Array(this.bufferLength),\n ].map(() => []);\n videoBuffer: (AVBufferInput & { elapsed: number; kind: string })[][] = [\n ...new Array(this.bufferLength),\n ].map(() => []);\n stopped = false;\n private interval = this.options.interval ?? 500;\n private started = false;\n\n constructor(\n private audioOutput: (output: AVBufferOutput) => void,\n private videoOutput: (output: AVBufferOutput) => void,\n private options: Partial<AvBufferOptions> = {}\n ) {}\n\n private start() {\n if (this.started) {\n return;\n }\n this.started = true;\n\n let index = 0;\n setInterval(() => {\n const joined = [...this.audioBuffer[index], ...this.videoBuffer[index]];\n const sorted = joined.sort((a, b) => a.elapsed - b.elapsed);\n this.audioBuffer[index] = [];\n this.videoBuffer[index] = [];\n\n for (const output of sorted) {\n if (output.kind === \"audio\") {\n this.audioOutput(output);\n } else {\n this.videoOutput(output);\n }\n }\n\n index++;\n if (index === this.bufferLength) {\n index = 0;\n }\n }, this.interval);\n }\n\n processAudioInput = (input: AVBufferInput) => {\n if (!input.frame) {\n this.stopped = true;\n this.audioOutput(input);\n return;\n }\n if (this.stopped) {\n return;\n }\n\n if (this.baseAudioTimestamp == undefined) {\n this.baseAudioTimestamp = input.frame?.timestamp;\n }\n\n const { elapsed, rotate } = this.calcElapsed(\n this.baseAudioTimestamp,\n input.frame.timestamp,\n 48000\n );\n if (rotate) {\n this.baseAudioTimestamp = input.frame?.timestamp;\n }\n\n const index = int(elapsed / this.interval) % this.bufferLength;\n this.audioBuffer[index].push({ ...input, elapsed, kind: \"audio\" });\n\n this.start();\n };\n\n processVideoInput = (input: AVBufferInput) => {\n if (!input.frame) {\n this.stopped = true;\n this.videoOutput(input);\n return;\n }\n if (this.stopped) {\n return;\n }\n\n if (this.baseVideoTimestamp == undefined) {\n this.baseVideoTimestamp = input.frame?.timestamp;\n }\n\n const { elapsed, rotate } = this.calcElapsed(\n this.baseVideoTimestamp,\n input.frame.timestamp,\n 90000\n );\n if (rotate) {\n this.baseVideoTimestamp = input.frame?.timestamp;\n }\n\n const index = int(elapsed / this.interval) % this.bufferLength;\n this.videoBuffer[index].push({ ...input, elapsed, kind: \"video\" });\n\n this.start();\n };\n\n private calcElapsed(base: number, timestamp: number, clockRate: number) {\n const rotate = Math.abs(timestamp - base) > (Max32Uint / 4) * 3;\n if (rotate) {\n console.log(rotate);\n }\n\n const diff = rotate ? timestamp + Max32Uint - base : timestamp - base;\n /**ms */\n const elapsed = int((diff / clockRate) * 1000);\n return { elapsed, rotate };\n }\n}\n\nexport interface AvBufferOptions {\n interval: number;\n bufferLength: number;\n}\n"]}
@@ -40,6 +40,9 @@ class DepacketizeBase {
40
40
  return [];
41
41
  }
42
42
  }
43
+ if (isKeyframe) {
44
+ // console.log("isKeyframe", this.codec);
45
+ }
43
46
  output.push({
44
47
  frame: {
45
48
  data,
@@ -1 +1 @@
1
- {"version":3,"file":"depacketizer.js","sourceRoot":"","sources":["../../../../../rtp/src/processor/depacketizer.ts"],"names":[],"mappings":"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","sourcesContent":["import debug from \"debug\";\n\nimport { RtpHeader, RtpPacket, uint16Add } from \"..\";\nimport { dePacketizeRtpPackets } from \"../codec\";\nimport { enumerate } from \"../helper\";\nimport { Processor } from \"./interface\";\nimport { RtpOutput } from \"./source\";\n\nconst srcPath = `werift-rtp : packages/rtp/src/processor_v2/depacketizer.ts`;\nconst log = debug(srcPath);\n\nexport type DepacketizerInput = RtpOutput;\n\nexport interface DepacketizerOutput {\n frame?: { data: Buffer; isKeyframe: boolean; timestamp: number };\n eol?: boolean;\n}\n\nexport class DepacketizeBase\n implements Processor<DepacketizerInput, DepacketizerOutput>\n{\n private buffering: RtpPacket[] = [];\n private lastSeqNum?: number;\n private packetLostHappened = false;\n\n constructor(\n private codec: string,\n private options: {\n waitForKeyframe?: boolean;\n isFinalPacketInSequence?: (header: RtpHeader) => boolean;\n } = {}\n ) {}\n\n processInput(input: DepacketizerInput): DepacketizerOutput[] {\n const output: DepacketizerOutput[] = [];\n if (!input.rtp) {\n if (input.eol) {\n output.push({ eol: true });\n }\n return output;\n }\n\n if (this.options.isFinalPacketInSequence) {\n const isFinal = this.checkFinalPacket(input.rtp);\n if (isFinal) {\n try {\n const { timestamp } = this.buffering[0].header;\n const { data, isKeyframe } = dePacketizeRtpPackets(\n this.codec,\n this.buffering\n );\n this.clearBuffer();\n\n if (this.packetLostHappened) {\n if (isKeyframe) {\n this.packetLostHappened = false;\n } else if (this.options.waitForKeyframe) {\n return [];\n }\n }\n\n output.push({\n frame: {\n data,\n isKeyframe,\n timestamp,\n },\n });\n return output;\n } catch (error) {\n log(\"error\", error, input);\n this.clearBuffer();\n }\n }\n } else {\n try {\n const { data, isKeyframe } = dePacketizeRtpPackets(this.codec, [\n input.rtp,\n ]);\n output.push({\n frame: {\n data,\n isKeyframe,\n timestamp: input.rtp.header.timestamp,\n },\n });\n return output;\n } catch (error) {\n log(\"error\", error, input);\n }\n }\n return [];\n }\n\n private clearBuffer() {\n this.buffering.forEach((b) => b.clear());\n this.buffering = [];\n }\n\n private checkFinalPacket(rtp: RtpPacket): boolean {\n if (!this.options.isFinalPacketInSequence) {\n throw new Error(\"isFinalPacketInSequence not exist\");\n }\n\n const { sequenceNumber } = rtp.header;\n if (this.lastSeqNum != undefined) {\n const expect = uint16Add(this.lastSeqNum, 1);\n if (sequenceNumber < expect) {\n return false;\n }\n if (sequenceNumber > expect) {\n log(\"packet lost happened\", { expect, sequenceNumber });\n this.packetLostHappened = true;\n this.clearBuffer();\n }\n }\n\n this.buffering.push(rtp);\n this.lastSeqNum = sequenceNumber;\n\n let finalPacket: number | undefined;\n for (const [i, p] of enumerate(this.buffering)) {\n if (this.options.isFinalPacketInSequence(p.header)) {\n finalPacket = i;\n break;\n }\n }\n if (finalPacket == undefined) {\n return false;\n }\n\n return true;\n }\n}\n"]}
1
+ {"version":3,"file":"depacketizer.js","sourceRoot":"","sources":["../../../../../rtp/src/processor/depacketizer.ts"],"names":[],"mappings":"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","sourcesContent":["import debug from \"debug\";\n\nimport { RtpHeader, RtpPacket, uint16Add } from \"..\";\nimport { dePacketizeRtpPackets } from \"../codec\";\nimport { enumerate } from \"../helper\";\nimport { Processor } from \"./interface\";\nimport { RtpOutput } from \"./source\";\n\nconst srcPath = `werift-rtp : packages/rtp/src/processor_v2/depacketizer.ts`;\nconst log = debug(srcPath);\n\nexport type DepacketizerInput = RtpOutput;\n\nexport interface DepacketizerOutput {\n frame?: { data: Buffer; isKeyframe: boolean; timestamp: number };\n eol?: boolean;\n}\n\nexport class DepacketizeBase\n implements Processor<DepacketizerInput, DepacketizerOutput>\n{\n private buffering: RtpPacket[] = [];\n private lastSeqNum?: number;\n private packetLostHappened = false;\n\n constructor(\n private codec: string,\n private options: {\n waitForKeyframe?: boolean;\n isFinalPacketInSequence?: (header: RtpHeader) => boolean;\n } = {}\n ) {}\n\n processInput(input: DepacketizerInput): DepacketizerOutput[] {\n const output: DepacketizerOutput[] = [];\n if (!input.rtp) {\n if (input.eol) {\n output.push({ eol: true });\n }\n return output;\n }\n\n if (this.options.isFinalPacketInSequence) {\n const isFinal = this.checkFinalPacket(input.rtp);\n if (isFinal) {\n try {\n const { timestamp } = this.buffering[0].header;\n const { data, isKeyframe } = dePacketizeRtpPackets(\n this.codec,\n this.buffering\n );\n this.clearBuffer();\n\n if (this.packetLostHappened) {\n if (isKeyframe) {\n this.packetLostHappened = false;\n } else if (this.options.waitForKeyframe) {\n return [];\n }\n }\n\n if (isKeyframe) {\n // console.log(\"isKeyframe\", this.codec);\n }\n\n output.push({\n frame: {\n data,\n isKeyframe,\n timestamp,\n },\n });\n return output;\n } catch (error) {\n log(\"error\", error, input);\n this.clearBuffer();\n }\n }\n } else {\n try {\n const { data, isKeyframe } = dePacketizeRtpPackets(this.codec, [\n input.rtp,\n ]);\n output.push({\n frame: {\n data,\n isKeyframe,\n timestamp: input.rtp.header.timestamp,\n },\n });\n return output;\n } catch (error) {\n log(\"error\", error, input);\n }\n }\n return [];\n }\n\n private clearBuffer() {\n this.buffering.forEach((b) => b.clear());\n this.buffering = [];\n }\n\n private checkFinalPacket(rtp: RtpPacket): boolean {\n if (!this.options.isFinalPacketInSequence) {\n throw new Error(\"isFinalPacketInSequence not exist\");\n }\n\n const { sequenceNumber } = rtp.header;\n if (this.lastSeqNum != undefined) {\n const expect = uint16Add(this.lastSeqNum, 1);\n if (sequenceNumber < expect) {\n return false;\n }\n if (sequenceNumber > expect) {\n log(\"packet lost happened\", { expect, sequenceNumber });\n this.packetLostHappened = true;\n this.clearBuffer();\n }\n }\n\n this.buffering.push(rtp);\n this.lastSeqNum = sequenceNumber;\n\n let finalPacket: number | undefined;\n for (const [i, p] of enumerate(this.buffering)) {\n if (this.options.isFinalPacketInSequence(p.header)) {\n finalPacket = i;\n break;\n }\n }\n if (finalPacket == undefined) {\n return false;\n }\n\n return true;\n }\n}\n"]}
@@ -89,6 +89,8 @@ class MediaPlayerWebm {
89
89
  this.stopped = false;
90
90
  this.setupTrack = (port, track) => {
91
91
  let payloadType = 0;
92
+ let latestTimestamp = 0;
93
+ let timestampDiff = 0;
92
94
  const socket = (0, dgram_1.createSocket)("udp4");
93
95
  socket.bind(port);
94
96
  socket.on("message", async (buf) => {
@@ -100,8 +102,12 @@ class MediaPlayerWebm {
100
102
  if (payloadType !== rtp.header.payloadType) {
101
103
  payloadType = rtp.header.payloadType;
102
104
  track.onSourceChanged.execute(rtp.header);
105
+ timestampDiff = (0, src_1.uint32Add)(rtp.header.timestamp, -latestTimestamp);
106
+ console.log({ timestampDiff });
103
107
  }
104
- track.writeRtp(buf);
108
+ latestTimestamp = rtp.header.timestamp;
109
+ rtp.header.timestamp = (0, src_1.uint32Add)(rtp.header.timestamp, -timestampDiff);
110
+ track.writeRtp(rtp.serialize());
105
111
  });
106
112
  };
107
113
  this.setupTrack(audioPort, this.audio);
@@ -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 } 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\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 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=${\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, 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "werift",
3
- "version": "0.17.2",
3
+ "version": "0.17.3",
4
4
  "description": "WebRTC Implementation for TypeScript (Node.js)",
5
5
  "keywords": [
6
6
  "WebRTC",
@@ -3,7 +3,7 @@ import { createSocket } from "dgram";
3
3
  import { setImmediate } from "timers/promises";
4
4
  import { v4 } from "uuid";
5
5
 
6
- import { randomPort } from "../../../common/src";
6
+ import { randomPort, uint32Add } from "../../../common/src";
7
7
  import { RtpPacket } from "../../../rtp/src";
8
8
  import { MediaStreamTrack } from "../media/track";
9
9
 
@@ -105,6 +105,8 @@ export class MediaPlayerWebm {
105
105
 
106
106
  private setupTrack = (port: number, track: MediaStreamTrack) => {
107
107
  let payloadType = 0;
108
+ let latestTimestamp = 0;
109
+ let timestampDiff = 0;
108
110
 
109
111
  const socket = createSocket("udp4");
110
112
  socket.bind(port);
@@ -118,8 +120,12 @@ export class MediaPlayerWebm {
118
120
  if (payloadType !== rtp.header.payloadType) {
119
121
  payloadType = rtp.header.payloadType;
120
122
  track.onSourceChanged.execute(rtp.header);
123
+ timestampDiff = uint32Add(rtp.header.timestamp, -latestTimestamp);
124
+ console.log({ timestampDiff });
121
125
  }
122
- track.writeRtp(buf);
126
+ latestTimestamp = rtp.header.timestamp;
127
+ rtp.header.timestamp = uint32Add(rtp.header.timestamp, -timestampDiff);
128
+ track.writeRtp(rtp.serialize());
123
129
  });
124
130
  };
125
131