feat: stream video upload progress (#210)

* working on the streaming progress

* connected video upload progress from frontend to server to bucket

* cleanup

* cleanup

* added the progress bar

* finished the supabase upload-progress using supabse realtime

* use only progress bar

* updating the helpertext

* Merge branch 'upload-progress' of https://github.com/rotimi-best/classroomio into upload-progress

* updated the supabase import

* Update LocalVideo.svelte

* update lock file

---------

Co-authored-by: Rotimi Best <[email protected]>
This commit is contained in:
Em_Dev
2024-03-28 10:42:49 +01:00
committed by GitHub
co-authored by Rotimi Best
parent d8af3a304c
commit 23b3b5f555
7 changed files with 3476 additions and 9058 deletions
+15 -3
View File
@@ -13,7 +13,8 @@ const {
// GetObjectCommand,
} = require('@aws-sdk/client-s3');
// const { getSupabase } = require('../utils/supabase');
const { getSupabase } = require('../utils/supabase');
const genUniqueId = require('../utils/genUniqueId');
const upload = require('../utils/upload');
@@ -36,7 +37,7 @@ const S3 = new S3Client({
}
});
// const supabase = getSupabase();
const supabase = getSupabase();
// const museUploadQueue = new Queue('video', process.env.REDIS_API_KEY, {
// redis: { tls: { rejectUnauthorized: false } },
@@ -96,7 +97,18 @@ router.post('/', upload.single('videoFile'), async (req, res) => {
});
parallelUploads3.on('httpUploadProgress', (progress) => {
console.log(progress);
const uploadProgress = Math.round(((progress.loaded / progress.total) * 100) / 2);
console.log({ uploadProgress });
const channel = supabase.channel('upload-progress');
channel.subscribe((status) => {
if (status === 'SUBSCRIBED') {
channel.send({
type: 'broadcast',
event: lessonId,
payload: uploadProgress
});
}
});
});
await parallelUploads3.done();
+7 -10
View File
@@ -9,22 +9,19 @@ const getSupabase = (config) => {
config = {
supabaseConfig: {
bucketPath:
'https://koxqonvbkeakwvmdegcf.supabase.in/storage/v1/object/sign/',
bucketPath: 'https://koxqonvbkeakwvmdegcf.supabase.in/storage/v1/object/sign/',
url: PUBLIC_SUPABASE_URL || '',
anonKey: PUBLIC_SUPABASE_ANON_KEY || '',
},
anonKey: PUBLIC_SUPABASE_ANON_KEY || ''
}
};
supabase = createClient(
config.supabaseConfig.url,
config.supabaseConfig.anonKey,
{ auth: { persistSession: false } }
);
supabase = createClient(config.supabaseConfig.url, config.supabaseConfig.anonKey, {
auth: { persistSession: false }
});
return supabase;
};
module.exports = {
getSupabase,
getSupabase
};
View File
-1
View File
@@ -80,7 +80,6 @@
"postcss": "^8.4.24",
"postcss-load-config": "^4.0.1",
"sass": "^1.64.2",
"supabase": "^1.112.0",
"svelte": "^4.1.2",
"svelte-calendar": "^3.1.6",
"svelte-dnd-action": "^0.9.24",
@@ -7,7 +7,14 @@
deleteLessonVideo,
uploadCourseVideoStore
} from '$lib/components/Course/components/Lesson/store/lessons';
import { Moon } from 'svelte-loading-spinners';
import { onMount, onDestroy } from 'svelte';
import { ProgressBar } from 'carbon-components-svelte';
import { supabase } from '$lib/utils/functions/supabase';
let value = 0;
let max = 100;
let status = 'active';
let fileSize;
export let lessonId = '';
@@ -17,16 +24,8 @@
let submit;
let uploadedFileUrl = '';
let isLoading = false;
let timeoutkey;
const uploadingTexts = [
'Sending your video to our server...',
'Breaking video into chunks',
'Compressing the video...',
'Generating a link to your video...',
'Wrapping things up'
];
let uploadingLoadingText = uploadingTexts[0];
let prevProgress = 0;
let uploadChannel;
function isVideoAdded(link) {
return $lesson.materials?.videos?.find((v) => v.link === link);
@@ -42,6 +41,7 @@
console.log({ size: videoFile?.size });
fileSize = videoFile?.size / (1024 * 1024);
try {
const response = await axios({
method: 'POST',
@@ -51,6 +51,9 @@
maxBodyLength: Infinity,
headers: {
'Content-Type': 'multipart/form-data; boundary=MyBoundary'
},
onUploadProgress: (progressEvent) => {
value = Math.round((progressEvent.loaded * 100) / progressEvent?.total / 2);
}
});
@@ -90,23 +93,25 @@
isLoading = false;
}
$: {
if (isLoading) {
timeoutkey = setTimeout(() => {
console.log('timeout');
const i = uploadingTexts.findIndex((text) => text === uploadingLoadingText);
const next = uploadingTexts[i + 1];
onMount(async () => {
uploadChannel = supabase
.channel('upload-progress')
.on('broadcast', { event: lessonId }, (payload) => {
console.log('The progress of the upload', payload);
value = value + payload?.payload - prevProgress;
prevProgress = payload.payload;
})
.subscribe();
});
if (next) {
console.log('uploadingLoadingText', next);
uploadingLoadingText = next;
}
}, 30000);
} else if (timeoutkey) {
console.log('clearTimeout');
clearTimeout(timeoutkey);
uploadingLoadingText = uploadingTexts[0];
}
onDestroy(() => {
supabase.removeChannel(uploadChannel);
});
$: helperText = value + '% of ' + Math.round(fileSize) + 'MB';
$: if (value === max) {
helperText = 'Done';
status = 'finished';
}
$: isDoneUploading(formRes);
@@ -124,8 +129,11 @@
on:submit|preventDefault={onUpload}
>
{#if isLoading}
<Moon size="40" color="#1d4ed8" unit="px" duration="1s" />
<p class="mt-5">{uploadingLoadingText}</p>
<div class="flex flex-col gap-5 max-w-[500px] w-[60%] justify-center">
<p class="mt-5 text-center">Uploading...</p>
<ProgressBar class="w-full" {value} {max} {status} />
<p class="text-sm">{helperText}</p>
</div>
{:else}
<img src="/upload-video.svg" alt="upload" />
<span class="pt-3">
+1 -1
View File
@@ -18,7 +18,7 @@
"prettier-plugin-svelte": "^3.1.2",
"prettier-plugin-tailwindcss": "^0.5.7",
"standard-version": "^9.5.0",
"supabase": "^1.112.0",
"supabase": "^1.151.1",
"tsconfig": "workspace:*",
"turbo": "^1.10.16",
"typescript": "^5.1.6"
+2306 -7904
View File
File diff suppressed because it is too large Load Diff