api/stream: add Estimated-Content-Length header to tunnels
present where Content-Length cannot be accurately calculated, pure proxy streams do not have this header and instead have the accurate Content-Length one.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import HLS from "hls-parser";
|
||||
import { createInternalStream } from "./manage.js";
|
||||
import { request } from "undici";
|
||||
|
||||
function getURL(url) {
|
||||
try {
|
||||
@@ -74,3 +75,59 @@ export async function handleHlsPlaylist(streamInfo, req, res) {
|
||||
|
||||
res.send(hlsPlaylist);
|
||||
}
|
||||
|
||||
async function getSegmentSize(url, config) {
|
||||
const segmentResponse = await request(url, {
|
||||
...config,
|
||||
throwOnError: true
|
||||
});
|
||||
|
||||
if (segmentResponse.headers['content-length']) {
|
||||
segmentResponse.body.dump();
|
||||
return +segmentResponse.headers['content-length'];
|
||||
}
|
||||
|
||||
// if the response does not have a content-length
|
||||
// header, we have to compute it ourselves
|
||||
let size = 0;
|
||||
|
||||
for await (const data of segmentResponse.body) {
|
||||
size += data.length;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
export async function probeInternalHLSTunnel(streamInfo) {
|
||||
const { url, headers, dispatcher, signal } = streamInfo;
|
||||
|
||||
// remove all falsy headers
|
||||
Object.keys(headers).forEach(key => {
|
||||
if (!headers[key]) delete headers[key];
|
||||
});
|
||||
|
||||
const config = { headers, dispatcher, signal, maxRedirections: 16 };
|
||||
|
||||
const manifestResponse = await fetch(url, config);
|
||||
|
||||
const manifest = HLS.parse(await manifestResponse.text());
|
||||
if (manifest.segments.length === 0)
|
||||
return -1;
|
||||
|
||||
const segmentSamples = await Promise.all(
|
||||
Array(5).fill().map(async () => {
|
||||
const manifestIdx = Math.floor(Math.random() * manifest.segments.length);
|
||||
const randomSegment = manifest.segments[manifestIdx];
|
||||
if (!randomSegment.uri)
|
||||
throw "segment is missing URI";
|
||||
|
||||
const segmentSize = await getSegmentSize(randomSegment.uri, config) / randomSegment.duration;
|
||||
return segmentSize;
|
||||
})
|
||||
);
|
||||
|
||||
const averageBitrate = segmentSamples.reduce((a, b) => a + b) / segmentSamples.length;
|
||||
const totalDuration = manifest.segments.reduce((acc, segment) => acc + segment.duration, 0);
|
||||
|
||||
return averageBitrate * totalDuration;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user