feat: make video upload speed down to 5min for <500mb (#209)

* feat: make video upload down to 5min for <500mb

* update to 15 minutes timeout
This commit is contained in:
Rotimi Best
2024-03-16 17:35:23 +01:00
committed by GitHub
parent af909d1dd2
commit 62a32a6204
5 changed files with 295 additions and 25 deletions
+1
View File
@@ -20,6 +20,7 @@
"homepage": "https://github.com/rotimi-best/classroomio#readme",
"dependencies": {
"@aws-sdk/client-s3": "^3.388.0",
"@aws-sdk/lib-storage": "^3.535.0",
"@supabase/supabase-js": "^2.32.0",
"axios": "^1.4.0",
"body-parser": "^1.20.2",
+34 -10
View File
@@ -1,11 +1,12 @@
const express = require('express');
const FormData = require('form-data');
const axios = require('axios');
const { promisify } = require('util');
const fs = require('fs');
const unlinkAsync = promisify(fs.unlink);
const { Upload } = require('@aws-sdk/lib-storage');
const {
S3Client,
PutObjectCommand
@@ -42,6 +43,9 @@ const S3 = new S3Client({
// });
router.post('/', upload.single('videoFile'), async (req, res) => {
// Set timeout for this request to 15 minutes
req.setTimeout(900000);
const {
file,
query: { lessonId }
@@ -56,7 +60,10 @@ router.post('/', upload.single('videoFile'), async (req, res) => {
});
}
if (file?.size > 1000 * 1024 * 1024) {
// File upload limit is 500MB
const fileSizeInMegabytes = file?.size / (1024 * 1024);
if (fileSizeInMegabytes > 500) {
return res.status(400).json({
success: false,
type: 'FILE_TOO_LARGE',
@@ -66,19 +73,36 @@ router.post('/', upload.single('videoFile'), async (req, res) => {
const fileData = fs.readFileSync(file.path);
const fileName = `${genUniqueId()}-${file.originalname.split(' ').join('-')}`;
const params = {
Bucket: 'videos',
Key: fileName,
Body: fileData
};
const fileUrl = `https://pub-${CLOUDFLARE_PUBLIC_ACCOUNT_ID}.r2.dev/${fileName}`;
let metadata = {};
let metadata = {
sizeInMb: fileSizeInMegabytes
};
try {
console.log('Upload starting');
const s3UploadRes = await S3.send(new PutObjectCommand(params));
console.log('s3UploadRes', s3UploadRes);
console.time('upload');
const parallelUploads3 = new Upload({
client: S3,
queueSize: 5,
partSize: 1024 * 1024 * 20,
leavePartsOnError: false, // optional manually handle dropped parts
params: {
Bucket: 'videos',
Key: fileName,
Body: fileData
}
});
parallelUploads3.on('httpUploadProgress', (progress) => {
console.log(progress);
});
await parallelUploads3.done();
console.log('Upload to done');
console.timeEnd('upload');
unlinkAsync(file.path);
@@ -21,8 +21,9 @@
const uploadingTexts = [
'Sending your video to our server...',
'Breaking video into chunks',
'Compressing the video...',
'Generating a link to your video...',
'Generating transcription for your video...',
'Wrapping things up'
];
let uploadingLoadingText = uploadingTexts[0];
@@ -36,7 +37,10 @@
if (!fileInput) return;
const formData = new FormData();
formData.append('videoFile', fileInput.files[0]);
const videoFile = fileInput.files[0];
formData.append('videoFile', videoFile);
console.log({ size: videoFile?.size });
try {
const response = await axios({
@@ -97,7 +101,7 @@
console.log('uploadingLoadingText', next);
uploadingLoadingText = next;
}
}, 5000);
}, 30000);
} else if (timeoutkey) {
console.log('clearTimeout');
clearTimeout(timeoutkey);
@@ -112,11 +116,11 @@
<button
type="button"
on:click={() => (fileInput && !isLoading ? fileInput.click() : null)}
class="w-full h-full"
class="h-full w-full"
disabled={isLoading || !PUBLIC_SERVER_URL}
>
<form
class="h-full w-full flex flex-col items-center justify-center border border-primary-300 border-dashed rounded-xl"
class="border-primary-300 flex h-full w-full flex-col items-center justify-center rounded-xl border border-dashed"
on:submit|preventDefault={onUpload}
>
{#if isLoading}
@@ -129,7 +133,7 @@
<p class=" text-center text-sm font-normal">
Select file( Mp4, MOV, AVI) to upload to your lesson.
</p>
<p>(Max 80 MB)</p>
<p>(Max 500 MB)</p>
</span>
{/if}
<input
@@ -145,9 +149,9 @@
</form>
</button>
{:else if formRes?.type === 'FILE_TOO_LARGE'}
<div class="h-full w-full flex flex-col items-center justify-center rounded-xl">
<div class="flex h-full w-full flex-col items-center justify-center rounded-xl">
<img src="/video-upload-error.svg" alt="upload error" />
<span class="pt-3 pb-2">
<span class="pb-2 pt-3">
<h3 class="text-center text-base font-normal dark:text-white">
Oops 😬, couldn’t upload video
</h3>
@@ -158,9 +162,9 @@
<PrimaryButton label="Try another file" onClick={tryAgain} />
</div>
{:else if !formRes?.success}
<div class="h-full w-full flex flex-col items-center justify-center rounded-xl">
<div class="flex h-full w-full flex-col items-center justify-center rounded-xl">
<img src="/video-upload-error.svg" alt="upload error" />
<span class="pt-3 pb-2">
<span class="pb-2 pt-3">
<h3 class="text-center text-base font-normal dark:text-white">
Oops 😬, couldn’t upload video
</h3>
@@ -172,11 +176,11 @@
<PrimaryButton label="Please try again" onClick={tryAgain} />
</div>
{:else}
<div class="flex flex-col w-full h-full items-start justify-between">
<div class="h-auto w-full border rounded-md px-8 py-3">
<div class="flex h-full w-full flex-col items-start justify-between">
<div class="h-auto w-full rounded-md border px-8 py-3">
<div class="flex items-center justify-between">
<span class="flex items-center gap-2">
<div class="rounded-sm overflow-hidden">
<div class="overflow-hidden rounded-sm">
<video class="w-[200px]">
<source src={uploadedFileUrl} type="video/mp4" />
<!-- <source src="/path/to/video.webm" type="video/webm" /> -->