Fix video streaming: parse total size from S3 Content-Range header
This commit is contained in:
@@ -7,7 +7,6 @@ import {
|
||||
CompleteMultipartUploadCommand,
|
||||
AbortMultipartUploadCommand,
|
||||
GetObjectCommand,
|
||||
HeadObjectCommand,
|
||||
} from "@aws-sdk/client-s3";
|
||||
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
||||
|
||||
@@ -169,58 +168,44 @@ export async function getVideoStream(
|
||||
): Promise<VideoStreamResult> {
|
||||
const s3 = getRustFsClient();
|
||||
|
||||
const headResult = await s3.send(
|
||||
new HeadObjectCommand({
|
||||
Bucket: RUSTFS_BUCKET,
|
||||
Key: key,
|
||||
}),
|
||||
);
|
||||
const totalSize = headResult.ContentLength ?? 0;
|
||||
const contentType = headResult.ContentType || "video/webm";
|
||||
|
||||
let range: { start: number; end: number } | undefined;
|
||||
let command: GetObjectCommand;
|
||||
|
||||
if (rangeHeader) {
|
||||
const match = rangeHeader.match(/bytes=(\d*)-(\d*)/);
|
||||
if (match) {
|
||||
const start = match[1] ? parseInt(match[1], 10) : 0;
|
||||
const end = match[2] ? parseInt(match[2], 10) : totalSize - 1;
|
||||
range = { start, end: Math.min(end, totalSize - 1) };
|
||||
|
||||
command = new GetObjectCommand({
|
||||
Bucket: RUSTFS_BUCKET,
|
||||
Key: key,
|
||||
Range: `bytes=${range.start}-${range.end}`,
|
||||
});
|
||||
} else {
|
||||
command = new GetObjectCommand({
|
||||
Bucket: RUSTFS_BUCKET,
|
||||
Key: key,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
command = new GetObjectCommand({
|
||||
Bucket: RUSTFS_BUCKET,
|
||||
Key: key,
|
||||
});
|
||||
}
|
||||
const command = new GetObjectCommand({
|
||||
Bucket: RUSTFS_BUCKET,
|
||||
Key: key,
|
||||
...(rangeHeader ? { Range: rangeHeader } : {}),
|
||||
});
|
||||
|
||||
const result = await s3.send(command);
|
||||
if (!result.Body) {
|
||||
throw new Error("Empty response body from RustFS");
|
||||
}
|
||||
|
||||
const contentType = result.ContentType || "video/webm";
|
||||
|
||||
const sdkStream = result.Body as any;
|
||||
const webStream: ReadableStream<Uint8Array> = sdkStream.transformToWebStream
|
||||
? sdkStream.transformToWebStream()
|
||||
: sdkStream;
|
||||
|
||||
if (rangeHeader && result.ContentRange) {
|
||||
const match = result.ContentRange.match(/bytes (\d+)-(\d+)\/(\d+)/);
|
||||
if (match) {
|
||||
const start = parseInt(match[1], 10);
|
||||
const end = parseInt(match[2], 10);
|
||||
const totalSize = parseInt(match[3], 10);
|
||||
return {
|
||||
stream: webStream,
|
||||
contentType,
|
||||
contentLength: totalSize,
|
||||
range: { start, end },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
stream: webStream,
|
||||
contentType,
|
||||
contentLength: totalSize,
|
||||
range,
|
||||
contentLength: result.ContentLength ?? 0,
|
||||
range: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user