Add video transcoding to H264/MP4, use high quality CRF 18

This commit is contained in:
CallMeVerity
2026-06-03 04:32:01 +01:00
parent e99aaea193
commit 8138f4e36a
5 changed files with 204 additions and 46 deletions
+69 -44
View File
@@ -259,57 +259,82 @@ export default function UploadForm() {
const { parts, uploadId } = initRes.presignedUrls;
const totalSize = videoFile.size;
const CHUNK_SIZE = 80 * 1024 * 1024;
const CONCURRENT_UPLOADS = 3;
const uploadedParts: { partNumber: number; eTag: string }[] = [];
const progressPerChunk: number[] = new Array(parts.length).fill(0);
for (let i = 0; i < parts.length; i++) {
const part = parts[i]!;
const start = i * CHUNK_SIZE;
const uploadChunk = (index: number) => {
const part = parts[index]!;
const start = index * CHUNK_SIZE;
const end = Math.min(start + CHUNK_SIZE, totalSize);
const chunk = videoFile.slice(start, end);
const eTag = await new Promise<string>((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", (e) => {
if (e.lengthComputable) {
const chunkProgress = e.loaded / e.total;
const overallUploaded = start + e.loaded;
setProgress(
5 +
Math.round(
(overallUploaded / totalSize) * 90,
),
);
}
});
xhr.addEventListener("load", () => {
if (xhr.status >= 200 && xhr.status < 300) {
const etag = xhr.getResponseHeader("ETag");
if (etag) resolve(etag);
else
reject(
new Error("No ETag returned from upload"),
return new Promise<{ partNumber: number; eTag: string }>(
(resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", (e) => {
if (e.lengthComputable) {
progressPerChunk[index] = e.loaded;
const total = progressPerChunk.reduce(
(a, b) => a + b,
0,
);
} else {
reject(
new Error(
`Upload failed with status ${xhr.status}`,
),
);
}
});
xhr.addEventListener("error", () =>
reject(new Error("Upload failed")),
);
xhr.open("PUT", part.url);
xhr.setRequestHeader(
"Content-Type",
videoFile.type || "video/webm",
);
xhr.send(chunk);
});
setProgress(
5 + Math.round((total / totalSize) * 90),
);
}
});
xhr.addEventListener("load", () => {
if (xhr.status >= 200 && xhr.status < 300) {
const etag = xhr.getResponseHeader("ETag");
if (etag)
resolve({
partNumber: part.partNumber,
eTag: etag,
});
else
reject(
new Error(
"No ETag returned from upload",
),
);
} else {
reject(
new Error(
`Upload failed with status ${xhr.status}`,
),
);
}
});
xhr.addEventListener("error", () =>
reject(new Error("Upload failed")),
);
xhr.open("PUT", part.url);
xhr.setRequestHeader(
"Content-Type",
videoFile.type || "video/webm",
);
xhr.send(chunk);
},
);
};
uploadedParts.push({ partNumber: part.partNumber, eTag });
}
let nextIndex = 0;
const uploadNext = async (): Promise<void> => {
if (nextIndex >= parts.length) return;
const index = nextIndex++;
const result = await uploadChunk(index);
uploadedParts.push(result);
await uploadNext();
};
await Promise.all(
Array.from(
{ length: Math.min(CONCURRENT_UPLOADS, parts.length) },
() => uploadNext(),
),
);
uploadedParts.sort((a, b) => a.partNumber - b.partNumber);
setProgress(98);
await uploadVideoComplete(initRes.id, uploadedParts, uploadId);