diff --git a/.github/workflows/deploy-backend-on-push.yml b/.github/workflows/deploy-backend-on-push.yml index c7940d01..4b297ccb 100644 --- a/.github/workflows/deploy-backend-on-push.yml +++ b/.github/workflows/deploy-backend-on-push.yml @@ -1,10 +1,9 @@ -name: backend_deploy +name: Deploy Backend on: workflow_dispatch jobs: deploy: - name: Deploy backend runs-on: ubuntu-latest concurrency: deploy-group # optional: ensure only one action runs at a time steps: diff --git a/apps/backend/package.json b/apps/backend/package.json index c1cfc28b..65828b1f 100644 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -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", diff --git a/apps/backend/src/routes/uploadVideo.js b/apps/backend/src/routes/uploadVideo.js index 71e2569e..eff2d47a 100644 --- a/apps/backend/src/routes/uploadVideo.js +++ b/apps/backend/src/routes/uploadVideo.js @@ -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); diff --git a/apps/dashboard/src/lib/components/Course/components/Lesson/Materials/Video/LocalVideo.svelte b/apps/dashboard/src/lib/components/Course/components/Lesson/Materials/Video/LocalVideo.svelte index f3320c7f..29d50678 100644 --- a/apps/dashboard/src/lib/components/Course/components/Lesson/Materials/Video/LocalVideo.svelte +++ b/apps/dashboard/src/lib/components/Course/components/Lesson/Materials/Video/LocalVideo.svelte @@ -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 @@ {:else if formRes?.type === 'FILE_TOO_LARGE'} -
+
upload error - +

Oops 😬, couldn’t upload video

@@ -158,9 +162,9 @@
{:else if !formRes?.success} -
+
upload error - +

Oops 😬, couldn’t upload video

@@ -172,11 +176,11 @@
{:else} -
-
+
+
-
+