werift 0.16.0 → 0.16.1
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/rtp/src/codec/index.d.ts +0 -4
- package/lib/rtp/src/codec/index.js +2 -6
- package/lib/rtp/src/codec/index.js.map +1 -1
- package/lib/rtp/src/index.d.ts +1 -6
- package/lib/rtp/src/index.js +1 -6
- package/lib/rtp/src/index.js.map +1 -1
- package/lib/rtp/src/processor/depacketizer.d.ts +26 -0
- package/lib/rtp/src/processor/depacketizer.js +114 -0
- package/lib/rtp/src/processor/depacketizer.js.map +1 -0
- package/lib/rtp/src/processor/depacketizerCallback.d.ts +13 -0
- package/lib/rtp/src/processor/depacketizerCallback.js +20 -0
- package/lib/rtp/src/processor/depacketizerCallback.js.map +1 -0
- package/lib/rtp/src/processor/depacketizerTransformer.d.ts +8 -0
- package/lib/rtp/src/processor/depacketizerTransformer.js +20 -0
- package/lib/rtp/src/processor/depacketizerTransformer.js.map +1 -0
- package/lib/rtp/src/processor/index.d.ts +9 -0
- package/lib/rtp/src/{processor_v2 → processor}/index.js +6 -1
- package/lib/rtp/src/processor/index.js.map +1 -0
- package/lib/rtp/src/processor/jitterBuffer.d.ts +26 -11
- package/lib/rtp/src/processor/jitterBuffer.js +150 -42
- package/lib/rtp/src/processor/jitterBuffer.js.map +1 -1
- package/lib/rtp/src/processor/jitterBufferCallback.d.ts +10 -0
- package/lib/rtp/src/processor/jitterBufferCallback.js +21 -0
- package/lib/rtp/src/processor/jitterBufferCallback.js.map +1 -0
- package/lib/rtp/src/processor/jitterBufferTransformer.d.ts +9 -0
- package/lib/rtp/src/processor/jitterBufferTransformer.js +22 -0
- package/lib/rtp/src/processor/jitterBufferTransformer.js.map +1 -0
- package/lib/rtp/src/{processor_v2 → processor}/source/index.d.ts +0 -0
- package/lib/rtp/src/{processor_v2 → processor}/source/index.js +0 -0
- package/lib/rtp/src/processor/source/index.js.map +1 -0
- package/lib/rtp/src/processor/source/rtp.d.ts +20 -0
- package/lib/rtp/src/processor/source/rtp.js +32 -0
- package/lib/rtp/src/processor/source/rtp.js.map +1 -0
- package/lib/rtp/src/processor/webm.d.ts +24 -24
- package/lib/rtp/src/processor/webm.js +78 -89
- package/lib/rtp/src/processor/webm.js.map +1 -1
- package/lib/rtp/src/processor/webmStream.d.ts +31 -0
- package/lib/rtp/src/processor/webmStream.js +36 -0
- package/lib/rtp/src/processor/webmStream.js.map +1 -0
- package/lib/rtp/src/rtp/rtp.d.ts +1 -0
- package/lib/rtp/src/rtp/rtp.js +3 -0
- package/lib/rtp/src/rtp/rtp.js.map +1 -1
- package/lib/webrtc/src/media/rtpReceiver.d.ts +3 -2
- package/lib/webrtc/src/media/rtpReceiver.js +14 -6
- package/lib/webrtc/src/media/rtpReceiver.js.map +1 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js +8 -6
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js.map +1 -1
- package/lib/webrtc/src/peerConnection.js +3 -1
- package/lib/webrtc/src/peerConnection.js.map +1 -1
- package/package.json +1 -1
- package/src/media/rtpReceiver.ts +23 -11
- package/src/nonstandard/recorder/writer/webm.ts +9 -7
- package/src/peerConnection.ts +3 -1
- package/lib/rtp/src/processor/base.d.ts +0 -18
- package/lib/rtp/src/processor/base.js +0 -39
- package/lib/rtp/src/processor/base.js.map +0 -1
- package/lib/rtp/src/processor/lipsync.d.ts +0 -30
- package/lib/rtp/src/processor/lipsync.js +0 -92
- package/lib/rtp/src/processor/lipsync.js.map +0 -1
- package/lib/rtp/src/processor/sampleBuilder.d.ts +0 -13
- package/lib/rtp/src/processor/sampleBuilder.js +0 -33
- package/lib/rtp/src/processor/sampleBuilder.js.map +0 -1
- package/lib/rtp/src/processor_v2/depacketizer.d.ts +0 -17
- package/lib/rtp/src/processor_v2/depacketizer.js +0 -84
- package/lib/rtp/src/processor_v2/depacketizer.js.map +0 -1
- package/lib/rtp/src/processor_v2/index.d.ts +0 -4
- package/lib/rtp/src/processor_v2/index.js.map +0 -1
- package/lib/rtp/src/processor_v2/jitterBuffer.d.ts +0 -33
- package/lib/rtp/src/processor_v2/jitterBuffer.js +0 -154
- package/lib/rtp/src/processor_v2/jitterBuffer.js.map +0 -1
- package/lib/rtp/src/processor_v2/source/base.d.ts +0 -8
- package/lib/rtp/src/processor_v2/source/base.js +0 -16
- package/lib/rtp/src/processor_v2/source/base.js.map +0 -1
- package/lib/rtp/src/processor_v2/source/index.js.map +0 -1
- package/lib/rtp/src/processor_v2/source/rtp.d.ts +0 -14
- package/lib/rtp/src/processor_v2/source/rtp.js +0 -24
- package/lib/rtp/src/processor_v2/source/rtp.js.map +0 -1
- package/lib/rtp/src/processor_v2/webmLive.d.ts +0 -51
- package/lib/rtp/src/processor_v2/webmLive.js +0 -154
- package/lib/rtp/src/processor_v2/webmLive.js.map +0 -1
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RtpSourceStream = void 0;
|
|
4
|
-
const rx_mini_1 = require("rx.mini");
|
|
5
|
-
const base_1 = require("./base");
|
|
6
|
-
class RtpSourceStream extends base_1.SourceStream {
|
|
7
|
-
constructor(ev, options = {}) {
|
|
8
|
-
super();
|
|
9
|
-
this.disposer = new rx_mini_1.EventDisposer();
|
|
10
|
-
ev.subscribe((rtp) => {
|
|
11
|
-
if (options.payloadType != undefined &&
|
|
12
|
-
options.payloadType !== rtp.header.payloadType) {
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
this.write({ rtp });
|
|
16
|
-
}).disposer(this.disposer);
|
|
17
|
-
}
|
|
18
|
-
async stop() {
|
|
19
|
-
this.controller.enqueue({ eol: true });
|
|
20
|
-
this.disposer.dispose();
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
exports.RtpSourceStream = RtpSourceStream;
|
|
24
|
-
//# sourceMappingURL=rtp.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rtp.js","sourceRoot":"","sources":["../../../../../../rtp/src/processor_v2/source/rtp.ts"],"names":[],"mappings":";;;AAAA,qCAA+C;AAG/C,iCAAsC;AAOtC,MAAa,eAAgB,SAAQ,mBAAuB;IAG1D,YAAY,EAAsB,EAAE,UAAoC,EAAE;QACxE,KAAK,EAAE,CAAC;QAHO,aAAQ,GAAG,IAAI,uBAAa,EAAE,CAAC;QAK9C,EAAE,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE;YACnB,IACE,OAAO,CAAC,WAAW,IAAI,SAAS;gBAChC,OAAO,CAAC,WAAW,KAAK,GAAG,CAAC,MAAM,CAAC,WAAW,EAC9C;gBACA,OAAO;aACR;YAED,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;IAC1B,CAAC;CACF;AAtBD,0CAsBC","sourcesContent":["import Event, { EventDisposer } from \"rx.mini\";\n\nimport { RtpPacket } from \"../../rtp/rtp\";\nimport { SourceStream } from \"./base\";\n\nexport interface RtpOutput {\n rtp?: RtpPacket;\n eol?: boolean;\n}\n\nexport class RtpSourceStream extends SourceStream<RtpOutput> {\n private readonly disposer = new EventDisposer();\n\n constructor(ev: Event<[RtpPacket]>, options: { payloadType?: number } = {}) {\n super();\n\n ev.subscribe((rtp) => {\n if (\n options.payloadType != undefined &&\n options.payloadType !== rtp.header.payloadType\n ) {\n return;\n }\n\n this.write({ rtp });\n }).disposer(this.disposer);\n }\n\n async stop() {\n this.controller.enqueue({ eol: true });\n this.disposer.dispose();\n }\n}\n"]}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
/// <reference types="node" />
|
|
3
|
-
import { ReadableStream, WritableStream } from "stream/web";
|
|
4
|
-
import { SupportedCodec } from "../container/webm";
|
|
5
|
-
import { DepacketizerOutput } from "./depacketizer";
|
|
6
|
-
export declare type WebmLiveInput = DepacketizerOutput;
|
|
7
|
-
export declare type WebmLiveOutput = {
|
|
8
|
-
packet?: Buffer;
|
|
9
|
-
eol?: {
|
|
10
|
-
/**ms */
|
|
11
|
-
duration: number;
|
|
12
|
-
durationElement: Uint8Array;
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
export interface WebmLiveOption {
|
|
16
|
-
/**ms */
|
|
17
|
-
duration?: number;
|
|
18
|
-
}
|
|
19
|
-
export declare class WebmLiveSink {
|
|
20
|
-
tracks: {
|
|
21
|
-
width?: number;
|
|
22
|
-
height?: number;
|
|
23
|
-
kind: "audio" | "video";
|
|
24
|
-
codec: SupportedCodec;
|
|
25
|
-
clockRate: number;
|
|
26
|
-
trackNumber: number;
|
|
27
|
-
}[];
|
|
28
|
-
private options;
|
|
29
|
-
private builder;
|
|
30
|
-
private queue;
|
|
31
|
-
private relativeTimestamp;
|
|
32
|
-
private timestamps;
|
|
33
|
-
private cuePoints;
|
|
34
|
-
private position;
|
|
35
|
-
stopped: boolean;
|
|
36
|
-
audioStream: WritableStream<WebmLiveInput>;
|
|
37
|
-
videoStream: WritableStream<WebmLiveInput>;
|
|
38
|
-
webmStream: ReadableStream<WebmLiveOutput>;
|
|
39
|
-
private controller;
|
|
40
|
-
constructor(tracks: {
|
|
41
|
-
width?: number;
|
|
42
|
-
height?: number;
|
|
43
|
-
kind: "audio" | "video";
|
|
44
|
-
codec: SupportedCodec;
|
|
45
|
-
clockRate: number;
|
|
46
|
-
trackNumber: number;
|
|
47
|
-
}[], options?: WebmLiveOption);
|
|
48
|
-
private init;
|
|
49
|
-
private onFrameReceived;
|
|
50
|
-
private stop;
|
|
51
|
-
}
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.WebmLiveSink = void 0;
|
|
7
|
-
const debug_1 = __importDefault(require("debug"));
|
|
8
|
-
const web_1 = require("stream/web");
|
|
9
|
-
const __1 = require("..");
|
|
10
|
-
const webm_1 = require("../container/webm");
|
|
11
|
-
const sourcePath = `werift-rtp : packages/rtp/src/processor_v2/webmLive.ts`;
|
|
12
|
-
const log = (0, debug_1.default)(sourcePath);
|
|
13
|
-
class WebmLiveSink {
|
|
14
|
-
constructor(tracks, options = {}) {
|
|
15
|
-
this.tracks = tracks;
|
|
16
|
-
this.options = options;
|
|
17
|
-
this.queue = new __1.PromiseQueue();
|
|
18
|
-
this.relativeTimestamp = 0;
|
|
19
|
-
this.timestamps = {};
|
|
20
|
-
this.cuePoints = [];
|
|
21
|
-
this.position = 0;
|
|
22
|
-
this.stopped = false;
|
|
23
|
-
this.builder = new webm_1.WEBMBuilder(tracks);
|
|
24
|
-
tracks.forEach((t) => {
|
|
25
|
-
this.timestamps[t.trackNumber] = new ClusterTimestamp(t.clockRate);
|
|
26
|
-
});
|
|
27
|
-
const createStream = (trackNumber) => new web_1.WritableStream({
|
|
28
|
-
write: ({ frame, eol }) => {
|
|
29
|
-
if (this.stopped)
|
|
30
|
-
return;
|
|
31
|
-
if (!frame) {
|
|
32
|
-
if (eol) {
|
|
33
|
-
this.stop();
|
|
34
|
-
}
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
this.queue.push(() => this.onFrameReceived({ ...frame, trackNumber }));
|
|
38
|
-
},
|
|
39
|
-
});
|
|
40
|
-
const audioTrack = tracks.find((t) => t.kind === "audio");
|
|
41
|
-
if (audioTrack) {
|
|
42
|
-
this.audioStream = createStream(audioTrack.trackNumber);
|
|
43
|
-
}
|
|
44
|
-
const videoTrack = tracks.find((t) => t.kind === "video");
|
|
45
|
-
if (videoTrack) {
|
|
46
|
-
this.videoStream = createStream(videoTrack.trackNumber);
|
|
47
|
-
}
|
|
48
|
-
this.webmStream = new web_1.ReadableStream({
|
|
49
|
-
start: (controller) => {
|
|
50
|
-
this.controller = controller;
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
this.queue.push(() => this.init());
|
|
54
|
-
}
|
|
55
|
-
async init() {
|
|
56
|
-
const staticPart = Buffer.concat([
|
|
57
|
-
this.builder.ebmlHeader,
|
|
58
|
-
this.builder.createSegment(this.options.duration),
|
|
59
|
-
]);
|
|
60
|
-
this.controller.enqueue({ packet: staticPart });
|
|
61
|
-
this.position += staticPart.length;
|
|
62
|
-
const video = this.tracks.find((t) => t.kind === "video");
|
|
63
|
-
if (video) {
|
|
64
|
-
this.cuePoints.push(new CuePoint(this.builder, video.trackNumber, 0.0, this.position));
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
async onFrameReceived(frame) {
|
|
68
|
-
const track = this.tracks.find((t) => t.trackNumber === frame.trackNumber);
|
|
69
|
-
if (!track) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
const timestampManager = this.timestamps[track.trackNumber];
|
|
73
|
-
let elapsed = timestampManager.update(frame.timestamp);
|
|
74
|
-
if ((track.kind === "video" && frame.isKeyframe) ||
|
|
75
|
-
elapsed > MaxSinged16Int) {
|
|
76
|
-
this.relativeTimestamp += elapsed;
|
|
77
|
-
const cluster = this.builder.createCluster(this.relativeTimestamp);
|
|
78
|
-
this.controller.enqueue({ packet: Buffer.from(cluster) });
|
|
79
|
-
if (elapsed !== 0) {
|
|
80
|
-
this.cuePoints.push(new CuePoint(this.builder, track.trackNumber, this.relativeTimestamp, this.position));
|
|
81
|
-
}
|
|
82
|
-
this.position += cluster.length;
|
|
83
|
-
Object.values(this.timestamps).forEach((t) => t.reset());
|
|
84
|
-
elapsed = timestampManager.update(frame.timestamp);
|
|
85
|
-
}
|
|
86
|
-
const block = this.builder.createSimpleBlock(frame.data, frame.isKeyframe, track.trackNumber, elapsed);
|
|
87
|
-
this.controller.enqueue({ packet: block });
|
|
88
|
-
this.position += block.length;
|
|
89
|
-
const [cuePoint] = this.cuePoints.slice(-1);
|
|
90
|
-
if (cuePoint) {
|
|
91
|
-
cuePoint.blockNumber++;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
async stop() {
|
|
95
|
-
if (this.stopped) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
this.stopped = true;
|
|
99
|
-
log("stop");
|
|
100
|
-
const cues = this.builder.createCues(this.cuePoints.map((c) => c.build()));
|
|
101
|
-
this.controller.enqueue({ packet: Buffer.from(cues) });
|
|
102
|
-
const latestTimestamp = Object.values(this.timestamps).sort((a, b) => a.elapsed - b.elapsed)[0].elapsed;
|
|
103
|
-
const duration = this.relativeTimestamp + latestTimestamp;
|
|
104
|
-
const durationElement = this.builder.createDuration(duration);
|
|
105
|
-
this.controller.enqueue({ eol: { duration, durationElement } });
|
|
106
|
-
this.controller.close();
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
exports.WebmLiveSink = WebmLiveSink;
|
|
110
|
-
class ClusterTimestamp {
|
|
111
|
-
constructor(clockRate) {
|
|
112
|
-
this.clockRate = clockRate;
|
|
113
|
-
this.elapsed = 0;
|
|
114
|
-
}
|
|
115
|
-
reset() {
|
|
116
|
-
this.baseTimestamp = undefined;
|
|
117
|
-
}
|
|
118
|
-
update(timestamp) {
|
|
119
|
-
if (this.baseTimestamp == undefined) {
|
|
120
|
-
this.baseTimestamp = timestamp;
|
|
121
|
-
}
|
|
122
|
-
const rotate = Math.abs(timestamp - this.baseTimestamp) > (Max32Uint / 4) * 3;
|
|
123
|
-
if (rotate) {
|
|
124
|
-
log("rotate", { baseTimestamp: this.baseTimestamp, timestamp });
|
|
125
|
-
}
|
|
126
|
-
const elapsed = rotate
|
|
127
|
-
? timestamp + Max32Uint - this.baseTimestamp
|
|
128
|
-
: timestamp - this.baseTimestamp;
|
|
129
|
-
this.elapsed = (0, __1.int)((elapsed / this.clockRate) * 1000);
|
|
130
|
-
return this.elapsed;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
class CuePoint {
|
|
134
|
-
constructor(builder, trackNumber, relativeTimestamp, position) {
|
|
135
|
-
this.builder = builder;
|
|
136
|
-
this.trackNumber = trackNumber;
|
|
137
|
-
this.relativeTimestamp = relativeTimestamp;
|
|
138
|
-
this.position = position;
|
|
139
|
-
/**
|
|
140
|
-
* cuesの後のclusterのあるべき位置
|
|
141
|
-
* cuesはclusterの前に挿入される
|
|
142
|
-
*/
|
|
143
|
-
this.cuesLength = 0;
|
|
144
|
-
this.blockNumber = 0;
|
|
145
|
-
}
|
|
146
|
-
build() {
|
|
147
|
-
return this.builder.createCuePoint(this.relativeTimestamp, this.trackNumber, this.position - 48 + this.cuesLength, this.blockNumber);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
/**4294967295 */
|
|
151
|
-
const Max32Uint = Number(0x01n << 32n) - 1;
|
|
152
|
-
/**32767 */
|
|
153
|
-
const MaxSinged16Int = (0x01 << 16) / 2 - 1;
|
|
154
|
-
//# sourceMappingURL=webmLive.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webmLive.js","sourceRoot":"","sources":["../../../../../rtp/src/processor_v2/webmLive.ts"],"names":[],"mappings":"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","sourcesContent":["import debug from \"debug\";\nimport {\n ReadableStream,\n ReadableStreamController,\n WritableStream,\n} from \"stream/web\";\n\nimport { int, PromiseQueue } from \"..\";\nimport { SupportedCodec, WEBMBuilder } from \"../container/webm\";\nimport { DepacketizerOutput } from \"./depacketizer\";\n\nconst sourcePath = `werift-rtp : packages/rtp/src/processor_v2/webmLive.ts`;\nconst log = debug(sourcePath);\n\nexport type WebmLiveInput = DepacketizerOutput;\n\nexport type WebmLiveOutput = {\n packet?: Buffer;\n eol?: {\n /**ms */\n duration: number;\n durationElement: Uint8Array;\n };\n};\n\nexport interface WebmLiveOption {\n /**ms */\n duration?: number;\n}\n\nexport class WebmLiveSink {\n private builder: WEBMBuilder;\n private queue = new PromiseQueue();\n private relativeTimestamp = 0;\n private timestamps: { [pt: number]: ClusterTimestamp } = {};\n private cuePoints: CuePoint[] = [];\n private position = 0;\n stopped = false;\n audioStream!: WritableStream<WebmLiveInput>;\n videoStream!: WritableStream<WebmLiveInput>;\n webmStream: ReadableStream<WebmLiveOutput>;\n private controller!: ReadableStreamController<WebmLiveOutput>;\n\n constructor(\n public tracks: {\n width?: number;\n height?: number;\n kind: \"audio\" | \"video\";\n codec: SupportedCodec;\n clockRate: number;\n trackNumber: number;\n }[],\n private options: WebmLiveOption = {}\n ) {\n this.builder = new WEBMBuilder(tracks);\n\n tracks.forEach((t) => {\n this.timestamps[t.trackNumber] = new ClusterTimestamp(t.clockRate);\n });\n\n const createStream = (trackNumber: number) =>\n new WritableStream({\n write: ({ frame, eol }: WebmLiveInput) => {\n if (this.stopped) return;\n if (!frame) {\n if (eol) {\n this.stop();\n }\n return;\n }\n\n this.queue.push(() =>\n this.onFrameReceived({ ...frame, trackNumber })\n );\n },\n });\n\n const audioTrack = tracks.find((t) => t.kind === \"audio\");\n if (audioTrack) {\n this.audioStream = createStream(audioTrack.trackNumber);\n }\n\n const videoTrack = tracks.find((t) => t.kind === \"video\");\n if (videoTrack) {\n this.videoStream = createStream(videoTrack.trackNumber);\n }\n\n this.webmStream = new ReadableStream<WebmLiveOutput>({\n start: (controller) => {\n this.controller = controller;\n },\n });\n\n this.queue.push(() => this.init());\n }\n\n private async init() {\n const staticPart = Buffer.concat([\n this.builder.ebmlHeader,\n this.builder.createSegment(this.options.duration),\n ]);\n this.controller.enqueue({ packet: staticPart });\n this.position += staticPart.length;\n\n const video = this.tracks.find((t) => t.kind === \"video\");\n if (video) {\n this.cuePoints.push(\n new CuePoint(this.builder, video.trackNumber, 0.0, this.position)\n );\n }\n }\n\n private async onFrameReceived(\n frame: WebmLiveInput[\"frame\"] & { trackNumber: number }\n ) {\n const track = this.tracks.find((t) => t.trackNumber === frame.trackNumber);\n if (!track) {\n return;\n }\n\n const timestampManager = this.timestamps[track.trackNumber];\n let elapsed = timestampManager.update(frame.timestamp);\n\n if (\n (track.kind === \"video\" && frame.isKeyframe) ||\n elapsed > MaxSinged16Int\n ) {\n this.relativeTimestamp += elapsed;\n\n const cluster = this.builder.createCluster(this.relativeTimestamp);\n this.controller.enqueue({ packet: Buffer.from(cluster) });\n\n if (elapsed !== 0) {\n this.cuePoints.push(\n new CuePoint(\n this.builder,\n track.trackNumber,\n this.relativeTimestamp,\n this.position\n )\n );\n }\n this.position += cluster.length;\n Object.values(this.timestamps).forEach((t) => t.reset());\n elapsed = timestampManager.update(frame.timestamp);\n }\n\n const block = this.builder.createSimpleBlock(\n frame.data,\n frame.isKeyframe,\n track.trackNumber,\n elapsed\n );\n this.controller.enqueue({ packet: block });\n this.position += block.length;\n const [cuePoint] = this.cuePoints.slice(-1);\n if (cuePoint) {\n cuePoint.blockNumber++;\n }\n }\n\n private async stop() {\n if (this.stopped) {\n return;\n }\n this.stopped = true;\n\n log(\"stop\");\n\n const cues = this.builder.createCues(this.cuePoints.map((c) => c.build()));\n this.controller.enqueue({ packet: Buffer.from(cues) });\n\n const latestTimestamp = Object.values(this.timestamps).sort(\n (a, b) => a.elapsed - b.elapsed\n )[0].elapsed;\n const duration = this.relativeTimestamp + latestTimestamp;\n const durationElement = this.builder.createDuration(duration);\n this.controller.enqueue({ eol: { duration, durationElement } });\n\n this.controller.close();\n }\n}\n\nclass ClusterTimestamp {\n baseTimestamp?: number;\n elapsed = 0;\n\n constructor(public clockRate: number) {}\n\n reset() {\n this.baseTimestamp = undefined;\n }\n\n update(timestamp: number) {\n if (this.baseTimestamp == undefined) {\n this.baseTimestamp = timestamp;\n }\n const rotate =\n Math.abs(timestamp - this.baseTimestamp) > (Max32Uint / 4) * 3;\n\n if (rotate) {\n log(\"rotate\", { baseTimestamp: this.baseTimestamp, timestamp });\n }\n\n const elapsed = rotate\n ? timestamp + Max32Uint - this.baseTimestamp\n : timestamp - this.baseTimestamp;\n\n this.elapsed = int((elapsed / this.clockRate) * 1000);\n return this.elapsed;\n }\n}\n\nclass CuePoint {\n /**\n * cuesの後のclusterのあるべき位置\n * cuesはclusterの前に挿入される\n */\n cuesLength = 0;\n blockNumber = 0;\n\n constructor(\n private readonly builder: WEBMBuilder,\n private readonly trackNumber: number,\n private readonly relativeTimestamp: number,\n public position: number\n ) {}\n\n build() {\n return this.builder.createCuePoint(\n this.relativeTimestamp,\n this.trackNumber,\n this.position - 48 + this.cuesLength,\n this.blockNumber\n );\n }\n}\n\n/**4294967295 */\nconst Max32Uint = Number(0x01n << 32n) - 1;\n/**32767 */\nconst MaxSinged16Int = (0x01 << 16) / 2 - 1;\n"]}
|