From e5c4ba906edf13261968e6c4bcdfb59546e79d48 Mon Sep 17 00:00:00 2001 From: Yemeni Date: Mon, 24 Aug 2020 01:47:18 +0300 Subject: [PATCH 01/17] added Resolution model --- controllers/backend/resolutionChange.js | 1 + models/Resolution.js | 17 +++++++++++++++++ models/Upload.js | 5 +++++ package.json | 2 +- 4 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 controllers/backend/resolutionChange.js create mode 100644 models/Resolution.js diff --git a/controllers/backend/resolutionChange.js b/controllers/backend/resolutionChange.js new file mode 100644 index 00000000..24801195 --- /dev/null +++ b/controllers/backend/resolutionChange.js @@ -0,0 +1 @@ +// this controller is still empty \ No newline at end of file diff --git a/models/Resolution.js b/models/Resolution.js new file mode 100644 index 00000000..b3ae1066 --- /dev/null +++ b/models/Resolution.js @@ -0,0 +1,17 @@ +const mongoose = require('mongoose'); +const _ = require('lodash'); +const javascriptTimeAgo = require('javascript-time-ago'); +javascriptTimeAgo.locale(require('javascript-time-ago/locales/en')); +require('javascript-time-ago/intl-messageformat-global'); +require('intl-messageformat/dist/locale-data/en'); + +const resolutionSchema = new mongoose.Schema({ + + fileSize: Number, + resolution: { type: String, enum: ['240', '360', '480', '720', '1080'] }, + originalUpload: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Upload' + } + +}); \ No newline at end of file diff --git a/models/Upload.js b/models/Upload.js index 943944d4..054f3521 100644 --- a/models/Upload.js +++ b/models/Upload.js @@ -33,6 +33,11 @@ const uploadSchema = new mongoose.Schema({ originalFileSizeInMb: Number, processedFileSizeInMb: Number, fileSize: Number, // TODO: should support highQualityFileSize as well for compressions + fileQuality: Array, + fileResolutions: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Resolution' + }, views: { type: Number, default: 0 diff --git a/package.json b/package.json index 3d1eeb89..b9e9f605 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "NodeTube", - "version": "1.0.0", + "version": "1.0.1", "description": "Video, audio and image hosting", "repository": { "type": "git", From db1cc566b9035c4f829a3a054cf1a66ea764b411 Mon Sep 17 00:00:00 2001 From: Yemeni Date: Thu, 27 Aug 2020 19:51:09 +0300 Subject: [PATCH 02/17] Revert "added Resolution model" This reverts commit e5c4ba90 --- controllers/backend/resolutionChange.js | 1 - models/Resolution.js | 17 ----------------- models/Upload.js | 5 ----- package.json | 2 +- 4 files changed, 1 insertion(+), 24 deletions(-) delete mode 100644 controllers/backend/resolutionChange.js delete mode 100644 models/Resolution.js diff --git a/controllers/backend/resolutionChange.js b/controllers/backend/resolutionChange.js deleted file mode 100644 index 24801195..00000000 --- a/controllers/backend/resolutionChange.js +++ /dev/null @@ -1 +0,0 @@ -// this controller is still empty \ No newline at end of file diff --git a/models/Resolution.js b/models/Resolution.js deleted file mode 100644 index b3ae1066..00000000 --- a/models/Resolution.js +++ /dev/null @@ -1,17 +0,0 @@ -const mongoose = require('mongoose'); -const _ = require('lodash'); -const javascriptTimeAgo = require('javascript-time-ago'); -javascriptTimeAgo.locale(require('javascript-time-ago/locales/en')); -require('javascript-time-ago/intl-messageformat-global'); -require('intl-messageformat/dist/locale-data/en'); - -const resolutionSchema = new mongoose.Schema({ - - fileSize: Number, - resolution: { type: String, enum: ['240', '360', '480', '720', '1080'] }, - originalUpload: { - type: mongoose.Schema.Types.ObjectId, - ref: 'Upload' - } - -}); \ No newline at end of file diff --git a/models/Upload.js b/models/Upload.js index 054f3521..943944d4 100644 --- a/models/Upload.js +++ b/models/Upload.js @@ -33,11 +33,6 @@ const uploadSchema = new mongoose.Schema({ originalFileSizeInMb: Number, processedFileSizeInMb: Number, fileSize: Number, // TODO: should support highQualityFileSize as well for compressions - fileQuality: Array, - fileResolutions: { - type: mongoose.Schema.Types.ObjectId, - ref: 'Resolution' - }, views: { type: Number, default: 0 diff --git a/package.json b/package.json index b9e9f605..3d1eeb89 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "NodeTube", - "version": "1.0.1", + "version": "1.0.0", "description": "Video, audio and image hosting", "repository": { "type": "git", From 6ee186a5b0a877e162b6355f63d2a6a96ed75528 Mon Sep 17 00:00:00 2001 From: Yemeni Date: Fri, 28 Aug 2020 02:42:59 +0300 Subject: [PATCH 03/17] added ffmpeg quality conversion to videos --- controllers/backend/uploading.js | 37 +++++++++++++++++++++++++++++++- lib/uploading/ffmpeg.js | 7 ++++-- lib/uploading/helpers.js | 16 ++++++++++++++ models/Upload.js | 11 ++++++++++ package.json | 2 +- 5 files changed, 69 insertions(+), 4 deletions(-) diff --git a/controllers/backend/uploading.js b/controllers/backend/uploading.js index 89443ea4..7ba57d27 100644 --- a/controllers/backend/uploading.js +++ b/controllers/backend/uploading.js @@ -31,6 +31,7 @@ const { b2, bucket, hostUrl } = require('../../lib/uploading/backblaze'); const ffmpegHelper = require('../../lib/uploading/ffmpeg'); const { markUploadAsComplete, + markConvertAsComplete, updateUsersUnreadSubscriptions, runTimeoutFunction, userCanUploadContentOfThisRating @@ -520,7 +521,6 @@ exports.postFileUpload = async(req, res) => { } upload.fileType = 'video'; - upload = await upload.save(); } @@ -548,6 +548,41 @@ exports.postFileUpload = async(req, res) => { responseSent = true; aboutToProcess(res, channelUrl, uniqueTag); } + // TODO: put qualities somewhere else + const qualities = [ + { name: '256 x 144p', quality: 144, bitrate: 80 }, + { name: '426 x 240p', quality: 240, bitrate: 300 }, + { name: '640 x 360p', quality: 360, bitrate: 400 }, + { name: '854 x 480p', quality: 480, bitrate: 500 }, + { name: '1280 x 720p', quality: 720, bitrate: 2250 } + ]; + // TODO: Do quality stuff + // TODO: loop quality stuff + // video will be available in original quality while this is happening in the background + // TODO: make a quality conversion counter + for(var i = 0; i < qualities.length; i = i + 1){ + // TODO: this is kind of ugly lmao + qualitySavePath = `${channelUrlFolder}/${uniqueTag}-${qualities[i].quality}.mp4`; + await ffmpegHelper.convertVideo({ + uploadedPath: fileInDirectory, + title, + bitrate: qualities[i].bitrate, + savePath: qualitySavePath, + uniqueTag: uniqueTag + '-' + qualities[i].quality, + quality: qualities[i].quality + }); + + // Save file size after compression. + const response = await ffmpegHelper.ffprobePromise(qualitySavePath); + // upload.processedFileSizeInMb = bytesToMb(response.format.size); + + // await upload.save(); + } + + await markConvertAsComplete(uniqueTag, channelUrl, user); + + uploadLogger.info('Quality all qualities are converted', logObject); + }); // }); diff --git a/lib/uploading/ffmpeg.js b/lib/uploading/ffmpeg.js index e5b9b4db..af651c5c 100644 --- a/lib/uploading/ffmpeg.js +++ b/lib/uploading/ffmpeg.js @@ -79,7 +79,7 @@ function setRedisClient({ currentSeconds, uniqueTag, progress, force }){ // setRedisClient(); -function convertVideo({ uploadedPath, title, bitrate, savePath, uniqueTag }){ +function convertVideo({ uploadedPath, title, quality, bitrate, savePath, uniqueTag }){ return new Promise(function(resolve, reject) { let command; @@ -88,9 +88,12 @@ function convertVideo({ uploadedPath, title, bitrate, savePath, uniqueTag }){ command = ffmpeg(uploadedPath).videoCodec('libx264').audioCodec('aac').format('mp4') .outputOptions([ '-preset faster', '-b:v 2500k' ]); - } else { + } else if(!quality){ command = ffmpeg(uploadedPath).videoCodec('libx264').audioCodec('aac').format('mp4') + } else{ + command = ffmpeg(uploadedPath).videoCodec('libx264').audioCodec('aac').format('mp4') + .outputOptions([ '-preset faster', '-b:v ' + bitrate + 'k', '-vf scale=-2:' + quality ]); } let secondCounter = 0; diff --git a/lib/uploading/helpers.js b/lib/uploading/helpers.js index 801b6721..2b5cb6cc 100644 --- a/lib/uploading/helpers.js +++ b/lib/uploading/helpers.js @@ -18,6 +18,21 @@ async function markUploadAsComplete(uniqueTag, channelUrl, user, res){ return 'success' } +async function markConvertAsComplete(uniqueTag, channelUrl, user, res){ + // upload = await Upload.findOne({ uniqueTag }); + // upload.status = 'completed'; + + // upload.processingCompletedAt = new Date(); + + // await upload.save(); + console.log("quality converted") + + // user.uploads.push(upload._id); + // await user.save(); + + return 'success' +} + async function updateUsersUnreadSubscriptions(user){ const subscriptions = await Subscription.find({ subscribedToUser: user._id, active: true }); @@ -84,6 +99,7 @@ const bytesToGb = (bytes, decimalPlaces = 4) => { module.exports = { markUploadAsComplete, + markConvertAsComplete, updateUsersUnreadSubscriptions, runTimeoutFunction, userCanUploadContentOfThisRating, diff --git a/models/Upload.js b/models/Upload.js index 943944d4..da55d428 100644 --- a/models/Upload.js +++ b/models/Upload.js @@ -33,6 +33,17 @@ const uploadSchema = new mongoose.Schema({ originalFileSizeInMb: Number, processedFileSizeInMb: Number, fileSize: Number, // TODO: should support highQualityFileSize as well for compressions + videoQuality: { + quality: String, enum: ['240p', '360p', '480p', '720p', '1080p'], + fileSizeInMb: Number, + bitrate: Number + }, + // videoQualities: [ + // { quality: 'String', + // fileSizeInMb : Number , + // bitrate: Number, + // status: String, enum: ['pending', 'converting', 'complete'], default: 'pending' } + // ], views: { type: Number, default: 0 diff --git a/package.json b/package.json index 3d1eeb89..064bf09a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "NodeTube", - "version": "1.0.0", + "version": "1.0.2", "description": "Video, audio and image hosting", "repository": { "type": "git", From 91819ef9502fe3f624e5e99836fa7a5548f1ae83 Mon Sep 17 00:00:00 2001 From: Yemeni Date: Fri, 28 Aug 2020 19:56:43 +0300 Subject: [PATCH 04/17] added quality in upload model and made uploading push to mongodb --- controllers/backend/uploading.js | 49 +++++++++++++++++++++++++------- models/Upload.js | 24 +++++++++------- 2 files changed, 51 insertions(+), 22 deletions(-) diff --git a/controllers/backend/uploading.js b/controllers/backend/uploading.js index 7ba57d27..c4e84b59 100644 --- a/controllers/backend/uploading.js +++ b/controllers/backend/uploading.js @@ -559,24 +559,51 @@ exports.postFileUpload = async(req, res) => { // TODO: Do quality stuff // TODO: loop quality stuff // video will be available in original quality while this is happening in the background - // TODO: make a quality conversion counter + // TODO: make a quality conversion counter/progress bar for(var i = 0; i < qualities.length; i = i + 1){ // TODO: this is kind of ugly lmao qualitySavePath = `${channelUrlFolder}/${uniqueTag}-${qualities[i].quality}.mp4`; - await ffmpegHelper.convertVideo({ - uploadedPath: fileInDirectory, - title, - bitrate: qualities[i].bitrate, - savePath: qualitySavePath, - uniqueTag: uniqueTag + '-' + qualities[i].quality, - quality: qualities[i].quality - }); + + let qualityExists = upload.videoQualities.find(o => o.quality === qualities[i].quality); + if(!qualityExists){ + // TODO: add if it exists but still pending in case server was shut down or something else + // qualityExists.status !== 'complete' + await ffmpegHelper.convertVideo({ + uploadedPath: fileInDirectory, + title, + bitrate: qualities[i].bitrate, + savePath: qualitySavePath, + uniqueTag: uniqueTag + '-' + qualities[i].quality, + quality: qualities[i].quality + }); + + // const response = await ffmpegHelper.ffprobePromise(qualitySavePath); + + upload.videoQualities.push({ + quality: qualities[i].quality, + bitrate: qualities[i].bitrate, + fileSizeInMb: 1, + status: 'complete' // TODO: use enum here not string + }); + + await upload.save(); + + } + // await ffmpegHelper.convertVideo({ + // uploadedPath: fileInDirectory, + // title, + // bitrate: qualities[i].bitrate, + // savePath: qualitySavePath, + // uniqueTag: uniqueTag + '-' + qualities[i].quality, + // quality: qualities[i].quality + // }); // Save file size after compression. - const response = await ffmpegHelper.ffprobePromise(qualitySavePath); + // const response = await ffmpegHelper.ffprobePromise(qualitySavePath); // upload.processedFileSizeInMb = bytesToMb(response.format.size); - // await upload.save(); + upload.videoQualities + await upload.save(); } await markConvertAsComplete(uniqueTag, channelUrl, user); diff --git a/models/Upload.js b/models/Upload.js index da55d428..6839385e 100644 --- a/models/Upload.js +++ b/models/Upload.js @@ -33,17 +33,19 @@ const uploadSchema = new mongoose.Schema({ originalFileSizeInMb: Number, processedFileSizeInMb: Number, fileSize: Number, // TODO: should support highQualityFileSize as well for compressions - videoQuality: { - quality: String, enum: ['240p', '360p', '480p', '720p', '1080p'], - fileSizeInMb: Number, - bitrate: Number - }, - // videoQualities: [ - // { quality: 'String', - // fileSizeInMb : Number , - // bitrate: Number, - // status: String, enum: ['pending', 'converting', 'complete'], default: 'pending' } - // ], + // videoQuality: { + // quality: String, enum: ['240p', '360p', '480p', '720p', '1080p'], + // fileSizeInMb: Number, + // bitrate: Number + // }, + videoQualities: [ + { + quality: 'String', + fileSizeInMb: Number, + bitrate: Number, + status: {type: String, enum: ['pending', 'converting', 'complete'], default: 'pending'} + } + ], views: { type: Number, default: 0 From 753adb372aba1a45a613fa1a5bae351526c6fc61 Mon Sep 17 00:00:00 2001 From: Yemeni Date: Fri, 28 Aug 2020 22:21:03 +0300 Subject: [PATCH 05/17] nasty stuff that are not checked yet --- views/media.pug | 10 ++++++---- .../plyrAndAutoplayFunctionalityJs.pug | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/views/media.pug b/views/media.pug index 9ce5698a..cd71054a 100644 --- a/views/media.pug +++ b/views/media.pug @@ -66,7 +66,9 @@ block content video#media_player.display-element(playsinline poster=`${serverToUse}/${upload.uploader.channelUrl}/${upload.thumbnails.generated || upload.thumbnails.medium}` controls='', style="max-width:100%;background-color:black;") // to - source.video-source(src=`${serverToUse}/${upload.uploader.channelUrl}/${upload.uniqueTag}.mp4`, type='video/mp4') + source(src=`${serverToUse}/${upload.uploader.channelUrl}/${upload.uniqueTag}.mp4`, size='original', type='video/mp4') + source(src=`${serverToUse}/${upload.uploader.channelUrl}/${upload.uniqueTag}-144.mp4`, size='144', type='video/mp4') + //source.video-source(src=`${serverToUse}/${upload.uploader.channelUrl}/${upload.uniqueTag}.mp4`, type='video/mp4') //source(src=upload.uploadUrl, type='video/mp4') // if it's an audio @@ -569,9 +571,9 @@ block extra_footer_js include ./mediaPlayerPartials/reportUploadFunctionalityJs - include ./mediaPlayerPartials/changeQualityJs - - include ./mediaPlayerPartials/changeUserDefaultQualityJs + //include ./mediaPlayerPartials/changeQualityJs + // + //include ./mediaPlayerPartials/changeUserDefaultQualityJs include mediaPlayerPartials/creditFunctionalityJs diff --git a/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug b/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug index 46258d66..07bfa022 100644 --- a/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug +++ b/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug @@ -65,6 +65,7 @@ script. autoplay: autoplay, clickToPlay: true, speed: {selected: 1, options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]}, + quality: { default: 144, options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240] }, controls: ['play-large', 'play','progress', 'current-time', 'duration', 'rewind', 'fast-forward', 'mute', 'volume', 'settings', 'fullscreen'], settings: ['speed', 'captions', 'quality', 'loop'] }; From e06f0fbb547d1a5e6cdc931f46e1002784a7050a Mon Sep 17 00:00:00 2001 From: Anthony Date: Fri, 28 Aug 2020 13:54:57 -0600 Subject: [PATCH 06/17] working example --- views/media.pug | 3 ++- views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/views/media.pug b/views/media.pug index cd71054a..c923537e 100644 --- a/views/media.pug +++ b/views/media.pug @@ -66,8 +66,9 @@ block content video#media_player.display-element(playsinline poster=`${serverToUse}/${upload.uploader.channelUrl}/${upload.thumbnails.generated || upload.thumbnails.medium}` controls='', style="max-width:100%;background-color:black;") // to - source(src=`${serverToUse}/${upload.uploader.channelUrl}/${upload.uniqueTag}.mp4`, size='original', type='video/mp4') + source(src=`${serverToUse}/${upload.uploader.channelUrl}/${upload.uniqueTag}-144.mp4`, size='144', type='video/mp4') + source(src=`${serverToUse}/${upload.uploader.channelUrl}/${upload.uniqueTag}-360.mp4`, size='360', type='video/mp4') //source.video-source(src=`${serverToUse}/${upload.uploader.channelUrl}/${upload.uniqueTag}.mp4`, type='video/mp4') //source(src=upload.uploadUrl, type='video/mp4') diff --git a/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug b/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug index 07bfa022..5b3569d7 100644 --- a/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug +++ b/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug @@ -65,7 +65,7 @@ script. autoplay: autoplay, clickToPlay: true, speed: {selected: 1, options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]}, - quality: { default: 144, options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240] }, + quality: { default: 144, options: [360, 144] }, controls: ['play-large', 'play','progress', 'current-time', 'duration', 'rewind', 'fast-forward', 'mute', 'volume', 'settings', 'fullscreen'], settings: ['speed', 'captions', 'quality', 'loop'] }; From 81991251e0491026b46b3c5af04cf9eabe0c6ef5 Mon Sep 17 00:00:00 2001 From: Yemeni Date: Sat, 29 Aug 2020 20:40:42 +0300 Subject: [PATCH 07/17] added loop over available video qualities --- package.json | 2 +- views/media.pug | 10 +++++----- .../plyrAndAutoplayFunctionalityJs.pug | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 064bf09a..25c0b528 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "NodeTube", - "version": "1.0.2", + "version": "1.0.3", "description": "Video, audio and image hosting", "repository": { "type": "git", diff --git a/views/media.pug b/views/media.pug index c923537e..8b25d23a 100644 --- a/views/media.pug +++ b/views/media.pug @@ -66,11 +66,11 @@ block content video#media_player.display-element(playsinline poster=`${serverToUse}/${upload.uploader.channelUrl}/${upload.thumbnails.generated || upload.thumbnails.medium}` controls='', style="max-width:100%;background-color:black;") // to - - source(src=`${serverToUse}/${upload.uploader.channelUrl}/${upload.uniqueTag}-144.mp4`, size='144', type='video/mp4') - source(src=`${serverToUse}/${upload.uploader.channelUrl}/${upload.uniqueTag}-360.mp4`, size='360', type='video/mp4') - //source.video-source(src=`${serverToUse}/${upload.uploader.channelUrl}/${upload.uniqueTag}.mp4`, type='video/mp4') - //source(src=upload.uploadUrl, type='video/mp4') + each val in upload.videoQualities + if val.status === 'complete' + source(src=`${serverToUse}/${upload.uploader.channelUrl}/${upload.uniqueTag}-${val.quality}.mp4`, size=`${val.quality}`, type='video/mp4') + //source.video-source(src=`${serverToUse}/${upload.uploader.channelUrl}/${upload.uniqueTag}.mp4`, type='video/mp4') + //source(src=upload.uploadUrl, type='video/mp4') // if it's an audio else if upload.fileType === 'audio' diff --git a/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug b/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug index 5b3569d7..e06ebaa0 100644 --- a/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug +++ b/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug @@ -65,7 +65,7 @@ script. autoplay: autoplay, clickToPlay: true, speed: {selected: 1, options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]}, - quality: { default: 144, options: [360, 144] }, + quality: { default: 144, options: [1080, 720 ,360, 240, 144] }, controls: ['play-large', 'play','progress', 'current-time', 'duration', 'rewind', 'fast-forward', 'mute', 'volume', 'settings', 'fullscreen'], settings: ['speed', 'captions', 'quality', 'loop'] }; From 892dc11db080a0d98e57a7d639572e22881132c0 Mon Sep 17 00:00:00 2001 From: Yemeni Date: Mon, 31 Aug 2020 22:46:24 +0300 Subject: [PATCH 08/17] Added condition before converting qualities in upload --- controllers/backend/uploading.js | 95 +++++++++++++++++++------------- 1 file changed, 58 insertions(+), 37 deletions(-) diff --git a/controllers/backend/uploading.js b/controllers/backend/uploading.js index c4e84b59..a785a90d 100644 --- a/controllers/backend/uploading.js +++ b/controllers/backend/uploading.js @@ -548,6 +548,20 @@ exports.postFileUpload = async(req, res) => { responseSent = true; aboutToProcess(res, channelUrl, uniqueTag); } + /* + all values in Kbps (kilobits per seconds) + 2160p (4k) -> 13000 + 1440p 6000 + 1080p 3000 + 720p 2250 + 480p 500 + 360p 400 + 240p 300 + 144p 80 + + 0-80 144p + 81-299 360p + */ // TODO: put qualities somewhere else const qualities = [ { name: '256 x 144p', quality: 144, bitrate: 80 }, @@ -561,49 +575,56 @@ exports.postFileUpload = async(req, res) => { // video will be available in original quality while this is happening in the background // TODO: make a quality conversion counter/progress bar for(var i = 0; i < qualities.length; i = i + 1){ - // TODO: this is kind of ugly lmao - qualitySavePath = `${channelUrlFolder}/${uniqueTag}-${qualities[i].quality}.mp4`; + if(bitrate >= qualities[i].bitrate){ + // TODO: this is kind of ugly lmao + qualitySavePath = `${channelUrlFolder}/${uniqueTag}-${qualities[i].quality}.mp4`; + + let qualityExists = upload.videoQualities.find(o => o.quality === qualities[i].quality); + if(!qualityExists){ + // TODO: add if it exists but still pending in case server was shut down or something else + // qualityExists.status !== 'complete' + await ffmpegHelper.convertVideo({ + uploadedPath: fileInDirectory, + title, + bitrate: qualities[i].bitrate, + savePath: qualitySavePath, + uniqueTag: uniqueTag + '-' + qualities[i].quality, + quality: qualities[i].quality + }); + + // const response = await ffmpegHelper.ffprobePromise(qualitySavePath); + + upload.videoQualities.push({ + quality: qualities[i].quality, + bitrate: qualities[i].bitrate, + fileSizeInMb: 1, + status: 'complete' // TODO: use enum here not string + }); + + await upload.save(); - let qualityExists = upload.videoQualities.find(o => o.quality === qualities[i].quality); - if(!qualityExists){ - // TODO: add if it exists but still pending in case server was shut down or something else - // qualityExists.status !== 'complete' - await ffmpegHelper.convertVideo({ - uploadedPath: fileInDirectory, - title, - bitrate: qualities[i].bitrate, - savePath: qualitySavePath, - uniqueTag: uniqueTag + '-' + qualities[i].quality, - quality: qualities[i].quality - }); + } + // await ffmpegHelper.convertVideo({ + // uploadedPath: fileInDirectory, + // title, + // bitrate: qualities[i].bitrate, + // savePath: qualitySavePath, + // uniqueTag: uniqueTag + '-' + qualities[i].quality, + // quality: qualities[i].quality + // }); + // Save file size after compression. // const response = await ffmpegHelper.ffprobePromise(qualitySavePath); + // upload.processedFileSizeInMb = bytesToMb(response.format.size); - upload.videoQualities.push({ - quality: qualities[i].quality, - bitrate: qualities[i].bitrate, - fileSizeInMb: 1, - status: 'complete' // TODO: use enum here not string - }); - + upload.videoQualities await upload.save(); - } - // await ffmpegHelper.convertVideo({ - // uploadedPath: fileInDirectory, - // title, - // bitrate: qualities[i].bitrate, - // savePath: qualitySavePath, - // uniqueTag: uniqueTag + '-' + qualities[i].quality, - // quality: qualities[i].quality - // }); - - // Save file size after compression. - // const response = await ffmpegHelper.ffprobePromise(qualitySavePath); - // upload.processedFileSizeInMb = bytesToMb(response.format.size); - - upload.videoQualities - await upload.save(); + else { + // do max possible conversion with the biggest bitrate left? then break; + break; + } + } await markConvertAsComplete(uniqueTag, channelUrl, user); From 5a3d80d7aa3ca18967eb8ad06e7fa3d8fb74da65 Mon Sep 17 00:00:00 2001 From: Yemeni Date: Thu, 17 Sep 2020 02:32:31 +0300 Subject: [PATCH 09/17] refactored coverting code + pending converts shows in media --- controllers/backend/uploading.js | 70 ++++++++++++++++---------------- views/media.pug | 15 ++++++- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/controllers/backend/uploading.js b/controllers/backend/uploading.js index cad63ba9..9203bcb4 100644 --- a/controllers/backend/uploading.js +++ b/controllers/backend/uploading.js @@ -554,10 +554,6 @@ exports.postFileUpload = async(req, res) => { uploadLogger.info('Upload marked as complete', logObject); - updateUsersUnreadSubscriptions(user); - - uploadLogger.info('Updated subscribed users subscriptions', logObject); - if(!responseSent){ responseSent = true; aboutToProcess(res, channelUrl, uniqueTag); @@ -590,54 +586,52 @@ exports.postFileUpload = async(req, res) => { // TODO: make a quality conversion counter/progress bar for(var i = 0; i < qualities.length; i = i + 1){ if(bitrate >= qualities[i].bitrate){ - // TODO: this is kind of ugly lmao - qualitySavePath = `${channelUrlFolder}/${uniqueTag}-${qualities[i].quality}.mp4`; + // qualitySavePath = `${channelUrlFolder}/${uniqueTag}-${qualities[i].quality}.mp4`; let qualityExists = upload.videoQualities.find(o => o.quality === qualities[i].quality); if(!qualityExists){ - // TODO: add if it exists but still pending in case server was shut down or something else - // qualityExists.status !== 'complete' - await ffmpegHelper.convertVideo({ - uploadedPath: fileInDirectory, - title, - bitrate: qualities[i].bitrate, - savePath: qualitySavePath, - uniqueTag: uniqueTag + '-' + qualities[i].quality, - quality: qualities[i].quality - }); - - // const response = await ffmpegHelper.ffprobePromise(qualitySavePath); upload.videoQualities.push({ quality: qualities[i].quality, bitrate: qualities[i].bitrate, fileSizeInMb: 1, - status: 'complete' // TODO: use enum here not string + status: 'pending' // TODO: use enum here not string }); + } + + } + } + await upload.save(); + + for(var i = 0; i < upload.videoQualities.length; i = i + 1){ + if(bitrate >= upload.videoQualities[i].bitrate){ + if(upload.videoQualities[i].status != 'complete'){ + // TODO: this is kind of ugly lmao + qualitySavePath = `${channelUrlFolder}/${uniqueTag}-${upload.videoQualities[i].quality}.mp4`; + + upload.videoQualities[i].status = 'converting'; + // upload.videoQualities await upload.save(); + // await upload.save(); + await ffmpegHelper.convertVideo({ + uploadedPath: fileInDirectory, + title, + bitrate: upload.videoQualities[i].bitrate, + savePath: qualitySavePath, + uniqueTag: uniqueTag + '-' + upload.videoQualities[i].quality, + quality: upload.videoQualities[i].quality + }); + upload.videoQualities[i].status = 'complete'; } - // await ffmpegHelper.convertVideo({ - // uploadedPath: fileInDirectory, - // title, - // bitrate: qualities[i].bitrate, - // savePath: qualitySavePath, - // uniqueTag: uniqueTag + '-' + qualities[i].quality, - // quality: qualities[i].quality - // }); - // Save file size after compression. - // const response = await ffmpegHelper.ffprobePromise(qualitySavePath); - // upload.processedFileSizeInMb = bytesToMb(response.format.size); - - upload.videoQualities await upload.save(); } - else { - // do max possible conversion with the biggest bitrate left? then break; - break; - } + // else { + // // do max possible conversion with the biggest bitrate left? then break; + // break; + // } } @@ -645,6 +639,10 @@ exports.postFileUpload = async(req, res) => { uploadLogger.info('Quality all qualities are converted', logObject); + updateUsersUnreadSubscriptions(user); + + uploadLogger.info('Updated subscribed users subscriptions', logObject); + }); // }); diff --git a/views/media.pug b/views/media.pug index 41cb57bc..507e7f0c 100644 --- a/views/media.pug +++ b/views/media.pug @@ -283,6 +283,17 @@ block content h4.fw(style="font-size:22px;margin-top:30px;") If your upload is stuck on processing, let an admin know via the social links at the bottom of the page and we'll take a look. + if upload.status !== 'processing' + + div(style="max-width:443px;margin:0 auto;") + //if(upload.videoQualities.includes({status: 'pending'})) + // h2.fw wtf + each val in upload.videoQualities + if val.status !== 'complete' + h4.fw(style="font-size:22px;margin-top:30px;") Video #{val.quality} convert is #{val.status} + + + br br @@ -291,7 +302,7 @@ block content div.display-div.magnetic(style="min-width:50%;min-height:50%;margin:0 auto;margin-top: -25px;") // margin-top:46px; - video#media_player.display-element(playsinline poster=`${uploadServer}/${upload.uploader.channelUrl}/${upload.thumbnails.generated || upload.thumbnails.medium}` controls='', style="max-width:100%;background-color:black;") + video#media_player.display-element(playsfinline poster=`${uploadServer}/${upload.uploader.channelUrl}/${upload.thumbnails.generated || upload.thumbnails.medium}` controls='', style="max-width:100%;background-color:black;") // to each val in upload.videoQualities if val.status === 'complete' @@ -901,7 +912,7 @@ block extra_footer_js if upload.status == 'processing' include ./mediaPlayerPartials/progressTrackerJs - + // include the stuff of media to calculate converstion percentage script(src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.0/clipboard.min.js") script(src="https://cdnjs.cloudflare.com/ajax/libs/plyr/3.5.10/plyr.min.js") From 359359d84912f05b65c705ba050353cd0f0a7dd0 Mon Sep 17 00:00:00 2001 From: Yemeni Date: Thu, 17 Sep 2020 02:52:53 +0300 Subject: [PATCH 10/17] Removed extra spaces for eslint --- controllers/frontend/public.js | 3 --- routes.js | 1 - 2 files changed, 4 deletions(-) diff --git a/controllers/frontend/public.js b/controllers/frontend/public.js index 5ca88d23..b9033e37 100644 --- a/controllers/frontend/public.js +++ b/controllers/frontend/public.js @@ -71,7 +71,6 @@ exports.index = async(req, res) => { } }; - /** * GET /landing * Landing page @@ -117,7 +116,6 @@ exports.getLandingPage = async(req, res) => { } }; - /** * GET /globe * Globe page. @@ -232,7 +230,6 @@ exports.getDocs = async(req, res) => { }); }; - /** * GET /donate * Donation page diff --git a/routes.js b/routes.js index 1b450eb8..4f27fb2b 100644 --- a/routes.js +++ b/routes.js @@ -133,7 +133,6 @@ function frontendRoutes(app){ app.get('/about', publicController.about); app.get('/docs', publicController.getDocs); - app.get('/donate', publicController.getDonate); app.get('/landing', publicController.getLandingPage); From 90adcd54cef90d93770467a0fe5f340a11d67e3b Mon Sep 17 00:00:00 2001 From: Yousef Al-Hadhrami Date: Thu, 17 Sep 2020 03:44:14 +0300 Subject: [PATCH 11/17] Update media.pug --- views/media.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/media.pug b/views/media.pug index 507e7f0c..86d7d02a 100644 --- a/views/media.pug +++ b/views/media.pug @@ -302,7 +302,7 @@ block content div.display-div.magnetic(style="min-width:50%;min-height:50%;margin:0 auto;margin-top: -25px;") // margin-top:46px; - video#media_player.display-element(playsfinline poster=`${uploadServer}/${upload.uploader.channelUrl}/${upload.thumbnails.generated || upload.thumbnails.medium}` controls='', style="max-width:100%;background-color:black;") + video#media_player.display-element(playsinline poster=`${uploadServer}/${upload.uploader.channelUrl}/${upload.thumbnails.generated || upload.thumbnails.medium}` controls='', style="max-width:100%;background-color:black;") // to each val in upload.videoQualities if val.status === 'complete' From a557926909e0bd379f46e73719f68bc1b6b6a3ab Mon Sep 17 00:00:00 2001 From: Yemeni Date: Sun, 20 Sep 2020 01:15:01 +0300 Subject: [PATCH 12/17] Added bull and bull-board package --- app.js | 7 + package-lock.json | 333 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 2 + 3 files changed, 337 insertions(+), 5 deletions(-) diff --git a/app.js b/app.js index c95e909c..ca192fdd 100644 --- a/app.js +++ b/app.js @@ -26,6 +26,7 @@ const ngrok = require('ngrok'); const commandExists = require('command-exists'); const errorHandler = require('errorhandler'); const jsHelpers = require('./lib/helpers/js-helpers'); +const { UI } = require('bull-board'); /** FOR FINDING ERRANT LOGS **/ if(process.env.SHOW_LOG_LOCATION == 'true' || 2 == 1){ @@ -161,6 +162,12 @@ if(cluster.isMaster){ path: '/hiddenStatus' })); + // TODO: put this behind auth + /** bull-board queue monitor **/ + if(process.env.NODE_ENV === 'development'){ + app.use('/admin/queues', UI); + }; + app.use(compression()); app.use(sass({ src: path.join(__dirname, 'public'), diff --git a/package-lock.json b/package-lock.json index 3860d081..5759535a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "NodeTube", - "version": "1.0.0", + "version": "1.0.3", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -107,6 +107,11 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-13.5.2.tgz", "integrity": "sha512-Fr6a47c84PRLfd7M7u3/hEknyUdQrrBA6VoPmkze0tcflhU5UnpWEX2kn12ktA/lb+MNHSqFlSiPHIHsaErTPA==" }, + "@types/qs": { + "version": "6.9.5", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz", + "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==" + }, "@types/range-parser": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", @@ -1070,6 +1075,94 @@ "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" }, + "bull": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/bull/-/bull-3.18.0.tgz", + "integrity": "sha512-nE/BKlg1dnJ/AcOy5D1nzthcmpAKqpUVXzQ43mJfnVC8ZM7mi4ZzP3spN7745UuikzmGGsbTe9px2TbEKhR+DQ==", + "requires": { + "cron-parser": "^2.13.0", + "debuglog": "^1.0.0", + "get-port": "^5.1.1", + "ioredis": "^4.14.1", + "lodash": "^4.17.19", + "p-timeout": "^3.2.0", + "promise.prototype.finally": "^3.1.2", + "semver": "^7.3.2", + "util.promisify": "^1.0.1", + "uuid": "^8.3.0" + }, + "dependencies": { + "p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "requires": { + "p-finally": "^1.0.0" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + }, + "uuid": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", + "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==" + } + } + }, + "bull-board": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/bull-board/-/bull-board-0.9.0.tgz", + "integrity": "sha512-Ek6zNREJSPWT+j7GyZRMHDXprrFfeLYzJNV0EIUqhiUkCd8NV3F9qGa/0vThxB0OxcoMp/mDVdhQYz7OTlmrlw==", + "requires": { + "body-parser": "^1.17.2", + "bull": "3.11.0", + "date-fns": "2.4.1", + "ejs": "^2.6.1", + "express": "^4.15.2", + "express-async-router": "^0.1.15", + "pretty-bytes": "^5.1.0", + "ramda": "^0.26.1", + "react": "16.10.2", + "react-dom": "16.10.2", + "react-highlight": "^0.12.0", + "redis-info": "^3.0.8" + }, + "dependencies": { + "bull": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/bull/-/bull-3.11.0.tgz", + "integrity": "sha512-QQOn63RkL6CfnmZcacPVg1EF42SwQcYxNSn9OGlM5S2JW+Gah/dwCcXxZQ3h2nYnhsNfBsherJ7EpLzIsi2kSQ==", + "requires": { + "cron-parser": "^2.13.0", + "debuglog": "^1.0.0", + "get-port": "^5.0.0", + "ioredis": "^4.14.1", + "lodash": "^4.17.15", + "p-timeout": "^3.1.0", + "promise.prototype.finally": "^3.1.1", + "semver": "^6.3.0", + "util.promisify": "^1.0.0", + "uuid": "^3.3.3" + } + }, + "p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "requires": { + "p-finally": "^1.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, "busboy": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", @@ -1415,6 +1508,11 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" }, + "cluster-key-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", + "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -1487,7 +1585,7 @@ "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "integrity": "sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=", "requires": { "delayed-stream": "~1.0.0" } @@ -1834,6 +1932,15 @@ "capture-stack-trace": "^1.0.0" } }, + "cron-parser": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-2.16.3.tgz", + "integrity": "sha512-XNJBD1QLFeAMUkZtZQuncAAOgJFWNhBdIbwgD22hZxrcWOImBFMKgPC66GzaXpyoJs7UvYLLgPH/8BRk/7gbZg==", + "requires": { + "is-nan": "^1.3.0", + "moment-timezone": "^0.5.31" + } + }, "cross-spawn": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", @@ -1890,6 +1997,11 @@ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==" }, + "date-fns": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.4.1.tgz", + "integrity": "sha512-2RhmH/sjDSCYW2F3ZQxOUx/I7PvzXpi89aQL2d3OAxSTwLx6NilATeUbe0menFE3Lu5lFkOFci36ivimwYHHxw==" + }, "dayjs": { "version": "1.8.19", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.19.tgz", @@ -1908,6 +2020,11 @@ "ms": "2.0.0" } }, + "debuglog": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", + "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=" + }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -2265,6 +2382,11 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, + "ejs": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", + "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==" + }, "email-validator": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz", @@ -3041,6 +3163,34 @@ } } }, + "express-async-router": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/express-async-router/-/express-async-router-0.1.15.tgz", + "integrity": "sha512-fV4AwVHOCtYyECvfSqUcWoKC4leRSjkP+OTv8TLNUByZDk40lfE2Ptky77ZVUctTVnel1nwdAaGTrUuzVWz+Fw==", + "requires": { + "@types/express": "^4.16.0", + "@types/node": "^8.10.36", + "express": "^4.16.4" + }, + "dependencies": { + "@types/express": { + "version": "4.17.8", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.8.tgz", + "integrity": "sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "*", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/node": { + "version": "8.10.64", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.64.tgz", + "integrity": "sha512-/EwBIb+imu8Qi/A3NF9sJ9iuKo7yV+pryqjmeRqaU0C4wBAOhas5mdvoYeJ5PCKrh6thRSJHdoasFqh3BQGILA==" + } + } + }, "express-flash": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/express-flash/-/express-flash-0.0.2.tgz", @@ -4256,6 +4406,11 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=" }, + "get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==" + }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", @@ -4624,6 +4779,11 @@ "zero-fill": "^2.2.3" } }, + "highlight.js": { + "version": "9.18.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.3.tgz", + "integrity": "sha512-zBZAmhSupHIl5sITeMqIJnYCDfAEc3Gdkqj65wC1lpI468MMQeeQkhcIAvk+RylAkxrCcI9xy9piHiXeQ1BdzQ==" + }, "hosted-git-info": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", @@ -4909,6 +5069,45 @@ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, + "ioredis": { + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.17.3.tgz", + "integrity": "sha512-iRvq4BOYzNFkDnSyhx7cmJNOi1x/HWYe+A4VXHBu4qpwJaGT1Mp+D2bVGJntH9K/Z/GeOM/Nprb8gB3bmitz1Q==", + "requires": { + "cluster-key-slot": "^1.1.0", + "debug": "^4.1.1", + "denque": "^1.1.0", + "lodash.defaults": "^4.2.0", + "lodash.flatten": "^4.4.0", + "redis-commands": "1.5.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.0.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", + "requires": { + "redis-errors": "^1.0.0" + } + } + } + }, "ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", @@ -5107,6 +5306,14 @@ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==" }, + "is-nan": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.0.tgz", + "integrity": "sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ==", + "requires": { + "define-properties": "^1.1.3" + } + }, "is-npm": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", @@ -5284,8 +5491,7 @@ "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" }, "js-yaml": { "version": "3.13.1", @@ -5704,6 +5910,14 @@ "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", @@ -6335,6 +6549,14 @@ "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", "integrity": "sha1-DQVdU/UFKqZTyfbraLtdEr9cK1s=" }, + "moment-timezone": { + "version": "0.5.31", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", + "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", + "requires": { + "moment": ">= 2.9.0" + } + }, "mongodb": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.5.2.tgz", @@ -7115,7 +7337,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.0-next.1" @@ -7685,6 +7906,11 @@ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" }, + "pretty-bytes": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.4.1.tgz", + "integrity": "sha512-s1Iam6Gwz3JI5Hweaz4GoCD1WUNUIyzePFy5+Js2hjwGVt2Z79wNN+ZKOZ2vB6C+Xs6njyB84Z1IthQg8d9LxA==" + }, "prettyjson": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prettyjson/-/prettyjson-1.2.1.tgz", @@ -7725,6 +7951,16 @@ "asap": "~2.0.3" } }, + "promise.prototype.finally": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/promise.prototype.finally/-/promise.prototype.finally-3.1.2.tgz", + "integrity": "sha512-A2HuJWl2opDH0EafgdjwEw7HysI8ff/n4lW4QEVBCUXFk9QeGecBWv0Deph0UmLe3tTNYegz8MOjsVuE6SMoJA==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.0", + "function-bind": "^1.1.1" + } + }, "promisify-call": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz", @@ -7774,6 +8010,16 @@ } } }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, "proxy-addr": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", @@ -8031,6 +8277,11 @@ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=" }, + "ramda": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz", + "integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==" + }, "random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", @@ -8106,6 +8357,40 @@ } } }, + "react": { + "version": "16.10.2", + "resolved": "https://registry.npmjs.org/react/-/react-16.10.2.tgz", + "integrity": "sha512-MFVIq0DpIhrHFyqLU0S3+4dIcBhhOvBE8bJ/5kHPVOVaGdo0KuiQzpcjCPsf585WvhypqtrMILyoE2th6dT+Lw==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "react-dom": { + "version": "16.10.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.10.2.tgz", + "integrity": "sha512-kWGDcH3ItJK4+6Pl9DZB16BXYAZyrYQItU4OMy0jAkv5aNqc+mAKb4TpFtAteI6TJZu+9ZlNhaeNQSVQDHJzkw==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.16.2" + } + }, + "react-highlight": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/react-highlight/-/react-highlight-0.12.0.tgz", + "integrity": "sha512-j04EWbYOFM0PryhF5Vvl0FDa/dD3M6q0Sl+nFN9kTvWQ9hFkfISNNs85+ssL4TSkDM+4pQTpMdxlDRi8yfIxjw==", + "requires": { + "highlight.js": "^9.11.0" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", @@ -8222,6 +8507,19 @@ "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.5.0.tgz", "integrity": "sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg==" }, + "redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=" + }, + "redis-info": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/redis-info/-/redis-info-3.0.8.tgz", + "integrity": "sha512-L7yPuGzRq+gu+ZYl/aO0TDgc4nNcMpDTaTN4P3bBi8ZENp1fk8gvtZQpidrYL5uAJYMIcMN81fgUz28qUpTeVA==", + "requires": { + "lodash": "^4.17.11" + } + }, "redis-parser": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", @@ -8713,6 +9011,15 @@ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=" }, + "scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-BqYVWqwz6s1wZMhjFvLfVR5WXP7ZY32M/wYPo04CcuPM7XZEbV2TBNW7Z0UkguPTl0dWMA59VbNXxK6q+pHItg==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, "scmp": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz", @@ -9382,6 +9689,11 @@ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" }, + "standard-as-callback": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.0.1.tgz", + "integrity": "sha512-NQOxSeB8gOI5WjSaxjBgog2QFw55FV8TkS6Y07BiB3VJ8xNTvUYm0wl0s8ObgQ5NhdpnNfigMIKjgPESzgr4tg==" + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -10267,6 +10579,17 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, "utile": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/utile/-/utile-0.3.0.tgz", diff --git a/package.json b/package.json index 25c0b528..1e0e0cb4 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,8 @@ "bcrypt-nodejs": "^0.0.3", "bluebird": "^3.5.4", "body-parser": "^1.19.0", + "bull": "^3.18.0", + "bull-board": "^0.9.0", "captchapng": "0.0.1", "chalk": "^1.1.3", "cheerio": "^0.22.0", From 711c50ebbba4ddd087fc6978feaf88bbc65d528b Mon Sep 17 00:00:00 2001 From: Yemeni Date: Sun, 20 Sep 2020 01:15:25 +0300 Subject: [PATCH 13/17] Added queue logic to converting --- controllers/backend/uploading.js | 66 ++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/controllers/backend/uploading.js b/controllers/backend/uploading.js index 9203bcb4..5faae773 100644 --- a/controllers/backend/uploading.js +++ b/controllers/backend/uploading.js @@ -41,6 +41,8 @@ const backblaze = require('../../lib/uploading/backblaze'); // console.log(`SAVE AND SERVE FILES DIRECTORY: ${saveAndServeFilesDirectory}`); var resumable = require('../../lib/uploading/resumable.js')(__dirname + '/upload'); +var Queue = require('bull'); +const { setQueues } = require('bull-board'); const moderationUpdatesToDiscord = process.env.MODERATION_UPDATES_TO_DISCORD == 'true'; @@ -558,6 +560,57 @@ exports.postFileUpload = async(req, res) => { responseSent = true; aboutToProcess(res, channelUrl, uniqueTag); } + + var videoQualityQueue = new Queue('Video Quality is going to convert'); + setQueues([videoQualityQueue]); + + videoQualityQueue.process(async function(job, done){ + + Upload.update({'videoQualities._id': job.data.videoQualitiesId}, {'$set': { + 'videoQualities.$.status': 'converting', + 'videoQualities.$.fileSizeInMb': 2 + }}, function(err, result){ + + if(err){ + res.send(err); + } + else { + res.send(result); + } + + }); + + job.progress(5); + + await ffmpegHelper.convertVideo({ + uploadedPath: job.data.uploadedPath, + title: job.data.title, + bitrate: job.data.bitrate, + savePath: job.data.savePath, + uniqueTag: job.data.uniqueTag, + quality: job.data.quality + }); + + job.progress(42); // TODO: set progress based on convert percentage + + Upload.update({'videoQualities._id': job.data.videoQualitiesId}, {'$set': { + 'videoQualities.$.status': 'complete', + 'videoQualities.$.fileSizeInMb': 3 + }}, function(err, result){ + + if(err){ + res.send(err); + } + else { + res.send(result); + } + + }); + + job.progress(100); + done(); + + }); /* all values in Kbps (kilobits per seconds) 2160p (4k) -> 13000 @@ -610,20 +663,17 @@ exports.postFileUpload = async(req, res) => { // TODO: this is kind of ugly lmao qualitySavePath = `${channelUrlFolder}/${uniqueTag}-${upload.videoQualities[i].quality}.mp4`; - upload.videoQualities[i].status = 'converting'; - // upload.videoQualities - await upload.save(); - // await upload.save(); - await ffmpegHelper.convertVideo({ + videoQualityQueue.add({ + uploadId: upload._id, + videoQualitiesId: upload.videoQualities[i]._id, uploadedPath: fileInDirectory, - title, + title: title, bitrate: upload.videoQualities[i].bitrate, savePath: qualitySavePath, uniqueTag: uniqueTag + '-' + upload.videoQualities[i].quality, quality: upload.videoQualities[i].quality + // uploadSave: upload.save() }); - - upload.videoQualities[i].status = 'complete'; } await upload.save(); From c815416f148d209edf1f795526ae247bf584ca32 Mon Sep 17 00:00:00 2001 From: Yemeni Date: Sun, 20 Sep 2020 02:09:36 +0300 Subject: [PATCH 14/17] added 480p video quality --- views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug b/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug index edc32d29..9f09174f 100644 --- a/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug +++ b/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug @@ -69,7 +69,7 @@ script. autoplay, clickToPlay: true, speed: {selected: 1, options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]}, - quality: { default: 144, options: [1080, 720 ,360, 240, 144] }, + quality: { default: 144, options: [1080, 720, 360, 480, 240, 144] }, controls: ['play-large', 'play','progress', 'current-time', 'duration', 'rewind', 'fast-forward', 'mute', 'volume', 'settings', 'fullscreen', 'captions'], settings: ['speed', 'captions', 'quality', 'loop'] }; From 0a3b35a933ef8fe6463197c0f313578753e54405 Mon Sep 17 00:00:00 2001 From: Yemeni Date: Sun, 20 Sep 2020 02:11:20 +0300 Subject: [PATCH 15/17] added 480p video quality --- views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug b/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug index 9f09174f..698c1861 100644 --- a/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug +++ b/views/mediaPlayerPartials/plyrAndAutoplayFunctionalityJs.pug @@ -69,7 +69,7 @@ script. autoplay, clickToPlay: true, speed: {selected: 1, options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]}, - quality: { default: 144, options: [1080, 720, 360, 480, 240, 144] }, + quality: { default: 144, options: [1080, 720, 480, 360, 240, 144] }, controls: ['play-large', 'play','progress', 'current-time', 'duration', 'rewind', 'fast-forward', 'mute', 'volume', 'settings', 'fullscreen', 'captions'], settings: ['speed', 'captions', 'quality', 'loop'] }; From 5d85a552fcaec3b06682ca375c3de05a7c041cff Mon Sep 17 00:00:00 2001 From: Yemeni Date: Sun, 20 Sep 2020 02:15:11 +0300 Subject: [PATCH 16/17] eslint removed unnecessary semi colon --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index a32f4f14..d6ec6b93 100644 --- a/app.js +++ b/app.js @@ -166,7 +166,7 @@ if(cluster.isMaster){ /** bull-board queue monitor **/ if(process.env.NODE_ENV === 'development'){ app.use('/admin/queues', UI); - }; + } app.use(compression()); app.use(sass({ From 35113532f1a9ed068fc36fd10f72fe6a54eceab0 Mon Sep 17 00:00:00 2001 From: Yemeni Date: Sat, 26 Sep 2020 21:16:53 +0300 Subject: [PATCH 17/17] mark as complete and inform users that all video qualities are complete --- controllers/backend/uploading.js | 36 +++++++++++++++++--------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/controllers/backend/uploading.js b/controllers/backend/uploading.js index ff549388..52190718 100644 --- a/controllers/backend/uploading.js +++ b/controllers/backend/uploading.js @@ -604,12 +604,27 @@ exports.postFileUpload = async(req, res) => { if(err){ res.send(err); } - else { - res.send(result); - } + // else { + // res.send(result); + // } }); + // Update if all qualities are converted + // TODO: needs some cleanup + // db.uploads.findOne({}).videoQualities.every(arr=> arr.status == 'complete'); + await Upload.findOne({uniqueTag : job.data.uploadUniqueTag }) + .select('videoQualities') + .exec(async function(err, txs){ + if(txs.videoQualities.every(arr=> arr.status === 'complete')){ + await markConvertAsComplete(uniqueTag, channelUrl, user); + uploadLogger.info('Quality all qualities are converted', logObject); + updateUsersUnreadSubscriptions(user); + uploadLogger.info('Updated subscribed users subscriptions', logObject); + } + + }); + job.progress(100); done(); @@ -673,32 +688,19 @@ exports.postFileUpload = async(req, res) => { title: title, bitrate: upload.videoQualities[i].bitrate, savePath: qualitySavePath, + uploadUniqueTag: uniqueTag, uniqueTag: uniqueTag + '-' + upload.videoQualities[i].quality, quality: upload.videoQualities[i].quality - // uploadSave: upload.save() }); } await upload.save(); } - // else { - // // do max possible conversion with the biggest bitrate left? then break; - // break; - // } } - await markConvertAsComplete(uniqueTag, channelUrl, user); - - uploadLogger.info('Quality all qualities are converted', logObject); - - updateUsersUnreadSubscriptions(user); - - uploadLogger.info('Updated subscribed users subscriptions', logObject); - }); - // }); } }); } catch(err){