@ahmedrowaihi/mediabunny-server 1.65.2-beta.539 → 1.65.2-beta.544
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/dist/bundles/mediabunny-server.cjs +60 -76
- package/dist/bundles/mediabunny-server.min.cjs +3 -3
- package/dist/bundles/mediabunny-server.min.mjs +3 -3
- package/dist/bundles/mediabunny-server.mjs +60 -76
- package/dist/mediabunny-server.d.ts +3 -8
- package/dist/modules/src/misc.d.ts.map +1 -1
- package/dist/modules/src/misc.js +22 -1
- package/dist/modules/src/network-source.d.ts.map +1 -1
- package/dist/modules/src/network-source.js +1 -6
- package/dist/modules/src/rist-source.d.ts.map +1 -1
- package/dist/modules/src/rist-source.js +5 -14
- package/dist/modules/src/rtmp-source.d.ts.map +1 -1
- package/dist/modules/src/rtmp-source.js +4 -14
- package/dist/modules/src/srt-target.d.ts +3 -8
- package/dist/modules/src/srt-target.d.ts.map +1 -1
- package/dist/modules/src/srt-target.js +43 -55
- package/dist/modules/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/misc.ts +21 -0
- package/src/network-source.ts +2 -7
- package/src/rist-source.ts +2 -12
- package/src/rtmp-source.ts +2 -13
- package/src/srt-target.ts +53 -60
|
@@ -80,6 +80,19 @@ var MediabunnyServer = (() => {
|
|
|
80
80
|
await peer.closep().catch(() => {
|
|
81
81
|
});
|
|
82
82
|
};
|
|
83
|
+
var checkUrlAndOptions = (url, options) => {
|
|
84
|
+
if (typeof url !== "string") {
|
|
85
|
+
throw new TypeError("url must be a string.");
|
|
86
|
+
}
|
|
87
|
+
if (!options || typeof options !== "object") {
|
|
88
|
+
throw new TypeError("options must be an object.");
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
var positive = (value, name) => {
|
|
92
|
+
if (value !== void 0 && (!Number.isFinite(value) || value <= 0)) {
|
|
93
|
+
throw new TypeError(`options.${name}, when provided, must be a positive number.`);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
83
96
|
var CODEC_TO_CODEC_ID = {
|
|
84
97
|
avc: NodeAv.AV_CODEC_ID_H264,
|
|
85
98
|
hevc: NodeAv.AV_CODEC_ID_HEVC,
|
|
@@ -4909,12 +4922,7 @@ var MediabunnyServer = (() => {
|
|
|
4909
4922
|
};
|
|
4910
4923
|
var NetworkSource = class extends import_mediabunny8.ReadableStreamSource {
|
|
4911
4924
|
constructor(url, options = {}) {
|
|
4912
|
-
|
|
4913
|
-
throw new TypeError("url must be a string.");
|
|
4914
|
-
}
|
|
4915
|
-
if (!options || typeof options !== "object") {
|
|
4916
|
-
throw new TypeError("options must be an object.");
|
|
4917
|
-
}
|
|
4925
|
+
checkUrlAndOptions(url, options);
|
|
4918
4926
|
if (options.connectTimeout !== void 0 && (!Number.isFinite(options.connectTimeout) || options.connectTimeout <= 0)) {
|
|
4919
4927
|
throw new TypeError("options.connectTimeout, when provided, must be a positive number.");
|
|
4920
4928
|
}
|
|
@@ -4936,11 +4944,6 @@ var MediabunnyServer = (() => {
|
|
|
4936
4944
|
var import_node_stream = __require("node:stream");
|
|
4937
4945
|
var PER_SECOND = 1e6;
|
|
4938
4946
|
var MOVFLAGS = "frag_keyframe+empty_moov+default_base_moof";
|
|
4939
|
-
var positive = (value, name) => {
|
|
4940
|
-
if (value !== void 0 && (!Number.isFinite(value) || value <= 0)) {
|
|
4941
|
-
throw new TypeError(`options.${name}, when provided, must be a positive number.`);
|
|
4942
|
-
}
|
|
4943
|
-
};
|
|
4944
4947
|
var inputOptions = (options) => {
|
|
4945
4948
|
const result = {
|
|
4946
4949
|
rw_timeout: String(Math.max(1, Math.round(options.readTimeout * PER_SECOND)))
|
|
@@ -5092,12 +5095,7 @@ var MediabunnyServer = (() => {
|
|
|
5092
5095
|
};
|
|
5093
5096
|
var RtmpSource = class extends import_mediabunny9.ReadableStreamSource {
|
|
5094
5097
|
constructor(url, options = {}) {
|
|
5095
|
-
|
|
5096
|
-
throw new TypeError("url must be a string.");
|
|
5097
|
-
}
|
|
5098
|
-
if (!options || typeof options !== "object") {
|
|
5099
|
-
throw new TypeError("options must be an object.");
|
|
5100
|
-
}
|
|
5098
|
+
checkUrlAndOptions(url, options);
|
|
5101
5099
|
if (options.mode !== void 0 && options.mode !== "listener" && options.mode !== "caller") {
|
|
5102
5100
|
throw new TypeError("options.mode, when provided, must be 'listener' or 'caller'.");
|
|
5103
5101
|
}
|
|
@@ -5130,11 +5128,6 @@ var MediabunnyServer = (() => {
|
|
|
5130
5128
|
var RTCP_RTPFB = 205;
|
|
5131
5129
|
var RTPFB_GENERIC_NACK = 1;
|
|
5132
5130
|
var RIST_APP_NAME = 1380537172;
|
|
5133
|
-
var positive2 = (value, name) => {
|
|
5134
|
-
if (value !== void 0 && (!Number.isFinite(value) || value <= 0)) {
|
|
5135
|
-
throw new TypeError(`options.${name}, when provided, must be a positive number.`);
|
|
5136
|
-
}
|
|
5137
|
-
};
|
|
5138
5131
|
var seqDistance = (a, b) => (a - b & 65535 ^ 32768) - 32768;
|
|
5139
5132
|
var parseRtp = (bytes) => {
|
|
5140
5133
|
if (bytes.length < RTP_HEADER_SIZE || bytes[0] >> 6 !== RTP_VERSION) {
|
|
@@ -5499,18 +5492,13 @@ var MediabunnyServer = (() => {
|
|
|
5499
5492
|
};
|
|
5500
5493
|
var RistSource = class extends import_mediabunny10.ReadableStreamSource {
|
|
5501
5494
|
constructor(url, options = {}) {
|
|
5502
|
-
|
|
5503
|
-
throw new TypeError("url must be a string.");
|
|
5504
|
-
}
|
|
5505
|
-
if (!options || typeof options !== "object") {
|
|
5506
|
-
throw new TypeError("options must be an object.");
|
|
5507
|
-
}
|
|
5495
|
+
checkUrlAndOptions(url, options);
|
|
5508
5496
|
if (options.mode !== void 0 && options.mode !== "listener" && options.mode !== "caller") {
|
|
5509
5497
|
throw new TypeError("options.mode, when provided, must be 'listener' or 'caller'.");
|
|
5510
5498
|
}
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5499
|
+
positive(options.bufferMs, "bufferMs");
|
|
5500
|
+
positive(options.readTimeout, "readTimeout");
|
|
5501
|
+
positive(options.nackIntervalMs, "nackIntervalMs");
|
|
5514
5502
|
const scheme = url.slice(0, url.indexOf(":"));
|
|
5515
5503
|
if (scheme !== "rist") {
|
|
5516
5504
|
throw new TypeError(`RistSource: ${JSON.stringify(url)} is not a rist:// URL.`);
|
|
@@ -5532,12 +5520,13 @@ var MediabunnyServer = (() => {
|
|
|
5532
5520
|
var PAYLOAD_SIZE = 1316;
|
|
5533
5521
|
var DEFAULT_MAX_QUEUE_BYTES = 2 * 1024 * 1024;
|
|
5534
5522
|
var DEFAULT_LINGER_SECONDS = 5;
|
|
5535
|
-
var
|
|
5523
|
+
var KEY_LENGTHS = [128, 192, 256];
|
|
5536
5524
|
var SrtSink = class {
|
|
5537
|
-
constructor(url, maxQueueBytes) {
|
|
5525
|
+
constructor(url, maxQueueBytes, listening) {
|
|
5538
5526
|
this.url = url;
|
|
5539
5527
|
this.maxQueueBytes = maxQueueBytes;
|
|
5540
|
-
this.
|
|
5528
|
+
this.listening = listening;
|
|
5529
|
+
this.opening = false;
|
|
5541
5530
|
this.pumping = null;
|
|
5542
5531
|
this.failure = null;
|
|
5543
5532
|
this.closed = false;
|
|
@@ -5549,22 +5538,13 @@ var MediabunnyServer = (() => {
|
|
|
5549
5538
|
this.sentBytes = 0;
|
|
5550
5539
|
this.writable = new WritableStream({
|
|
5551
5540
|
write: (chunk) => this.enqueue(chunk),
|
|
5552
|
-
close: () => this.finish()
|
|
5553
|
-
abort: () => this.finish(true)
|
|
5541
|
+
close: () => this.finish()
|
|
5554
5542
|
});
|
|
5555
5543
|
}
|
|
5556
|
-
/** @internal */
|
|
5557
|
-
async open() {
|
|
5558
|
-
const context = new import_node_av4.IOContext();
|
|
5559
|
-
const ret = await context.open2(this.url, import_constants3.AVIO_FLAG_WRITE);
|
|
5560
|
-
if (ret < 0) {
|
|
5561
|
-
throw new Error(`SrtTarget: could not open ${this.url} (AVERROR ${ret}).`);
|
|
5562
|
-
}
|
|
5563
|
-
this.io = context;
|
|
5564
|
-
}
|
|
5565
5544
|
/**
|
|
5566
|
-
* Takes the bytes and returns
|
|
5567
|
-
*
|
|
5545
|
+
* Takes the bytes and returns rather than awaiting the socket: pushing back here would stall the
|
|
5546
|
+
* muxer for as long as the receiver was behind, which on a live feed is unbounded. Past the queue
|
|
5547
|
+
* bound the *arriving* bytes go, not the queued ones, so what is queued stays a contiguous run.
|
|
5568
5548
|
*/
|
|
5569
5549
|
enqueue(chunk) {
|
|
5570
5550
|
if (this.failure) {
|
|
@@ -5577,11 +5557,15 @@ var MediabunnyServer = (() => {
|
|
|
5577
5557
|
}
|
|
5578
5558
|
this.queue.chunks.push(chunk);
|
|
5579
5559
|
this.queue.bytes += chunk.byteLength;
|
|
5560
|
+
void this.kick();
|
|
5561
|
+
}
|
|
5562
|
+
/** Starts the pump unless one is already running, which is the only way one ever starts. */
|
|
5563
|
+
kick() {
|
|
5580
5564
|
this.pumping ??= this.pump().finally(() => {
|
|
5581
5565
|
this.pumping = null;
|
|
5582
5566
|
});
|
|
5567
|
+
return this.pumping;
|
|
5583
5568
|
}
|
|
5584
|
-
/** @internal */
|
|
5585
5569
|
async writeDatagram(bytes) {
|
|
5586
5570
|
const io = this.io;
|
|
5587
5571
|
await io.write(Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength));
|
|
@@ -5590,12 +5574,16 @@ var MediabunnyServer = (() => {
|
|
|
5590
5574
|
}
|
|
5591
5575
|
this.sentBytes += bytes.byteLength;
|
|
5592
5576
|
}
|
|
5593
|
-
/** @internal */
|
|
5594
5577
|
async pump() {
|
|
5595
5578
|
try {
|
|
5596
5579
|
if (!this.io) {
|
|
5597
|
-
|
|
5598
|
-
|
|
5580
|
+
const context = new import_node_av4.IOContext();
|
|
5581
|
+
this.opening = true;
|
|
5582
|
+
const ret = await context.open2(this.url, import_constants3.AVIO_FLAG_WRITE);
|
|
5583
|
+
if (ret < 0) {
|
|
5584
|
+
throw new Error(`SrtTarget: could not open ${this.url} (AVERROR ${ret}).`);
|
|
5585
|
+
}
|
|
5586
|
+
this.io = context;
|
|
5599
5587
|
}
|
|
5600
5588
|
while (this.queue.chunks.length > 0) {
|
|
5601
5589
|
const chunk = this.queue.chunks.shift();
|
|
@@ -5607,8 +5595,8 @@ var MediabunnyServer = (() => {
|
|
|
5607
5595
|
this.partialLength += take;
|
|
5608
5596
|
offset += take;
|
|
5609
5597
|
if (this.partialLength === PAYLOAD_SIZE) {
|
|
5610
|
-
this.partialLength = 0;
|
|
5611
5598
|
await this.writeDatagram(this.partial);
|
|
5599
|
+
this.partialLength = 0;
|
|
5612
5600
|
}
|
|
5613
5601
|
}
|
|
5614
5602
|
}
|
|
@@ -5618,19 +5606,19 @@ var MediabunnyServer = (() => {
|
|
|
5618
5606
|
}
|
|
5619
5607
|
}
|
|
5620
5608
|
/** Drains what is queued, then closes. Awaited by the output's `finalize()`. */
|
|
5621
|
-
async finish(
|
|
5609
|
+
async finish() {
|
|
5622
5610
|
if (this.closed) {
|
|
5623
5611
|
return;
|
|
5624
5612
|
}
|
|
5625
5613
|
this.closed = true;
|
|
5614
|
+
if (this.listening && this.io === void 0 && this.opening) {
|
|
5615
|
+
await wakePendingAccept(this.url);
|
|
5616
|
+
}
|
|
5626
5617
|
while (this.pumping !== null || this.queue.chunks.length > 0) {
|
|
5627
|
-
|
|
5628
|
-
this.pumping = null;
|
|
5629
|
-
});
|
|
5630
|
-
await this.pumping.catch(() => {
|
|
5618
|
+
await this.kick().catch(() => {
|
|
5631
5619
|
});
|
|
5632
5620
|
}
|
|
5633
|
-
if (!
|
|
5621
|
+
if (!this.failure && this.io && this.partialLength > 0) {
|
|
5634
5622
|
await this.writeDatagram(this.partial.subarray(0, this.partialLength)).catch((error) => {
|
|
5635
5623
|
this.failure ??= error instanceof Error ? error : new Error(String(error));
|
|
5636
5624
|
});
|
|
@@ -5641,7 +5629,7 @@ var MediabunnyServer = (() => {
|
|
|
5641
5629
|
await this.io.closep().catch(() => {
|
|
5642
5630
|
});
|
|
5643
5631
|
}
|
|
5644
|
-
if (this.failure
|
|
5632
|
+
if (this.failure) {
|
|
5645
5633
|
throw this.failure;
|
|
5646
5634
|
}
|
|
5647
5635
|
}
|
|
@@ -5672,43 +5660,39 @@ var MediabunnyServer = (() => {
|
|
|
5672
5660
|
}
|
|
5673
5661
|
if (options.passphrase !== void 0) {
|
|
5674
5662
|
url.searchParams.set("passphrase", options.passphrase);
|
|
5675
|
-
url.searchParams.set("pbkeylen", String(
|
|
5663
|
+
url.searchParams.set("pbkeylen", String((options.keyLength ?? 128) / 8));
|
|
5676
5664
|
}
|
|
5677
5665
|
if (options.latency !== void 0) {
|
|
5678
|
-
url.searchParams.set("latency",
|
|
5666
|
+
url.searchParams.set("latency", String(Math.max(1, Math.round(options.latency * 1e3))));
|
|
5679
5667
|
}
|
|
5680
5668
|
if (url.searchParams.get("mode") === "listener") {
|
|
5681
5669
|
url.searchParams.set("listen_timeout", micros(connectTimeout));
|
|
5682
5670
|
}
|
|
5683
5671
|
url.searchParams.set("timeout", micros(connectTimeout));
|
|
5684
|
-
return url.toString();
|
|
5672
|
+
return { url: url.toString(), listening: url.searchParams.get("mode") === "listener" };
|
|
5685
5673
|
};
|
|
5686
5674
|
var SrtTarget = class extends import_mediabunny11.AppendOnlyStreamTarget {
|
|
5687
5675
|
constructor(url, options = {}) {
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
}
|
|
5691
|
-
if (!options || typeof options !== "object") {
|
|
5692
|
-
throw new TypeError("options must be an object.");
|
|
5693
|
-
}
|
|
5694
|
-
if (options.connectTimeout !== void 0 && (!Number.isFinite(options.connectTimeout) || options.connectTimeout <= 0)) {
|
|
5695
|
-
throw new TypeError("options.connectTimeout, when provided, must be a positive number.");
|
|
5696
|
-
}
|
|
5676
|
+
checkUrlAndOptions(url, options);
|
|
5677
|
+
positive(options.connectTimeout, "connectTimeout");
|
|
5697
5678
|
if (options.passphrase !== void 0 && (typeof options.passphrase !== "string" || options.passphrase.length < 10 || options.passphrase.length > 79)) {
|
|
5698
5679
|
throw new TypeError("options.passphrase, when provided, must be a string of 10 to 79 characters.");
|
|
5699
5680
|
}
|
|
5700
|
-
if (options.keyLength !== void 0 &&
|
|
5681
|
+
if (options.keyLength !== void 0 && !KEY_LENGTHS.includes(options.keyLength)) {
|
|
5701
5682
|
throw new TypeError("options.keyLength, when provided, must be 128, 192 or 256.");
|
|
5702
5683
|
}
|
|
5703
|
-
|
|
5704
|
-
throw new TypeError("options.latency, when provided, must be a positive number of milliseconds.");
|
|
5705
|
-
}
|
|
5684
|
+
positive(options.latency, "latency");
|
|
5706
5685
|
if (options.maxQueueBytes !== void 0 && (!Number.isInteger(options.maxQueueBytes) || options.maxQueueBytes < PAYLOAD_SIZE)) {
|
|
5707
5686
|
throw new TypeError(
|
|
5708
5687
|
`options.maxQueueBytes, when provided, must be an integer of at least ${PAYLOAD_SIZE}.`
|
|
5709
5688
|
);
|
|
5710
5689
|
}
|
|
5711
|
-
const
|
|
5690
|
+
const resolved = srtUrl(url, options);
|
|
5691
|
+
const sink = new SrtSink(
|
|
5692
|
+
resolved.url,
|
|
5693
|
+
options.maxQueueBytes ?? DEFAULT_MAX_QUEUE_BYTES,
|
|
5694
|
+
resolved.listening
|
|
5695
|
+
);
|
|
5712
5696
|
super(sink.writable);
|
|
5713
5697
|
this.sink = sink;
|
|
5714
5698
|
}
|