From 65af03a241aa83ab7ba71278b6c99acd26428b8a Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 1 Aug 2019 16:54:24 +0200 Subject: Automatically update playlist thumbnails --- server/controllers/api/video-playlist.ts | 67 +++++++++++++++++++++++--------- server/controllers/api/videos/import.ts | 4 +- server/controllers/api/videos/index.ts | 8 ++-- 3 files changed, 55 insertions(+), 24 deletions(-) (limited to 'server/controllers/api') diff --git a/server/controllers/api/video-playlist.ts b/server/controllers/api/video-playlist.ts index 540120cca..bd454f553 100644 --- a/server/controllers/api/video-playlist.ts +++ b/server/controllers/api/video-playlist.ts @@ -40,6 +40,7 @@ import { JobQueue } from '../../lib/job-queue' import { CONFIG } from '../../initializers/config' import { sequelizeTypescript } from '../../initializers/database' import { createPlaylistMiniatureFromExisting } from '../../lib/thumbnail' +import { VideoModel } from '../../models/video/video' const reqThumbnailFile = createReqFiles([ 'thumbnailfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT, { thumbnailfile: CONFIG.STORAGE.TMP_DIR }) @@ -171,13 +172,16 @@ async function addVideoPlaylist (req: express.Request, res: express.Response) { const thumbnailField = req.files['thumbnailfile'] const thumbnailModel = thumbnailField - ? await createPlaylistMiniatureFromExisting(thumbnailField[0].path, videoPlaylist) + ? await createPlaylistMiniatureFromExisting(thumbnailField[0].path, videoPlaylist, false) : undefined const videoPlaylistCreated: VideoPlaylistModel = await sequelizeTypescript.transaction(async t => { const videoPlaylistCreated = await videoPlaylist.save({ transaction: t }) - if (thumbnailModel) await videoPlaylistCreated.setAndSaveThumbnail(thumbnailModel, t) + if (thumbnailModel) { + thumbnailModel.automaticallyGenerated = false + await videoPlaylistCreated.setAndSaveThumbnail(thumbnailModel, t) + } // We need more attributes for the federation videoPlaylistCreated.OwnerAccount = await AccountModel.load(user.Account.id, t) @@ -206,7 +210,7 @@ async function updateVideoPlaylist (req: express.Request, res: express.Response) const thumbnailField = req.files['thumbnailfile'] const thumbnailModel = thumbnailField - ? await createPlaylistMiniatureFromExisting(thumbnailField[0].path, videoPlaylistInstance) + ? await createPlaylistMiniatureFromExisting(thumbnailField[0].path, videoPlaylistInstance, false) : undefined try { @@ -239,7 +243,10 @@ async function updateVideoPlaylist (req: express.Request, res: express.Response) const playlistUpdated = await videoPlaylistInstance.save(sequelizeOptions) - if (thumbnailModel) await playlistUpdated.setAndSaveThumbnail(thumbnailModel, t) + if (thumbnailModel) { + thumbnailModel.automaticallyGenerated = false + await playlistUpdated.setAndSaveThumbnail(thumbnailModel, t) + } const isNewPlaylist = wasPrivatePlaylist && playlistUpdated.privacy !== VideoPlaylistPrivacy.PRIVATE @@ -301,23 +308,17 @@ async function addVideoInPlaylist (req: express.Request, res: express.Response) videoPlaylist.changed('updatedAt', true) await videoPlaylist.save({ transaction: t }) - await sendUpdateVideoPlaylist(videoPlaylist, t) - return playlistElement }) // If the user did not set a thumbnail, automatically take the video thumbnail - if (videoPlaylist.hasThumbnail() === false) { - logger.info('Generating default thumbnail to playlist %s.', videoPlaylist.url) - - const inputPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, video.getMiniature().filename) - const thumbnailModel = await createPlaylistMiniatureFromExisting(inputPath, videoPlaylist, true) - - thumbnailModel.videoPlaylistId = videoPlaylist.id - - await thumbnailModel.save() + if (videoPlaylist.hasThumbnail() === false || (videoPlaylist.hasGeneratedThumbnail() && playlistElement.position === 1)) { + await generateThumbnailForPlaylist(videoPlaylist, video) } + sendUpdateVideoPlaylist(videoPlaylist, undefined) + .catch(err => logger.error('Cannot send video playlist update.', { err })) + logger.info('Video added in playlist %s at position %d.', videoPlaylist.uuid, playlistElement.position) return res.json({ @@ -365,11 +366,17 @@ async function removeVideoFromPlaylist (req: express.Request, res: express.Respo videoPlaylist.changed('updatedAt', true) await videoPlaylist.save({ transaction: t }) - await sendUpdateVideoPlaylist(videoPlaylist, t) - logger.info('Video playlist element %d of playlist %s deleted.', videoPlaylistElement.position, videoPlaylist.uuid) }) + // Do we need to regenerate the default thumbnail? + if (positionToDelete === 1 && videoPlaylist.hasGeneratedThumbnail()) { + await regeneratePlaylistThumbnail(videoPlaylist) + } + + sendUpdateVideoPlaylist(videoPlaylist, undefined) + .catch(err => logger.error('Cannot send video playlist update.', { err })) + return res.type('json').status(204).end() } @@ -413,8 +420,13 @@ async function reorderVideosPlaylist (req: express.Request, res: express.Respons await sendUpdateVideoPlaylist(videoPlaylist, t) }) + // The first element changed + if ((start === 1 || insertAfter === 0) && videoPlaylist.hasGeneratedThumbnail()) { + await regeneratePlaylistThumbnail(videoPlaylist) + } + logger.info( - 'Reordered playlist %s (inserted after %d elements %d - %d).', + 'Reordered playlist %s (inserted after position %d elements %d - %d).', videoPlaylist.uuid, insertAfter, start, start + reorderLength - 1 ) @@ -440,3 +452,22 @@ async function getVideoPlaylistVideos (req: express.Request, res: express.Respon } return res.json(getFormattedObjects(resultList.data, resultList.total, options)) } + +async function regeneratePlaylistThumbnail (videoPlaylist: VideoPlaylistModel) { + await videoPlaylist.Thumbnail.destroy() + videoPlaylist.Thumbnail = null + + const firstElement = await VideoPlaylistElementModel.loadFirstElementWithVideoThumbnail(videoPlaylist.id) + if (firstElement) await generateThumbnailForPlaylist(videoPlaylist, firstElement.Video) +} + +async function generateThumbnailForPlaylist (videoPlaylist: VideoPlaylistModel, video: VideoModel) { + logger.info('Generating default thumbnail to playlist %s.', videoPlaylist.url) + + const inputPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, video.getMiniature().filename) + const thumbnailModel = await createPlaylistMiniatureFromExisting(inputPath, videoPlaylist, true, true) + + thumbnailModel.videoPlaylistId = videoPlaylist.id + + videoPlaylist.Thumbnail = await thumbnailModel.save() +} diff --git a/server/controllers/api/videos/import.ts b/server/controllers/api/videos/import.ts index 1f08fe20a..04c9b547b 100644 --- a/server/controllers/api/videos/import.ts +++ b/server/controllers/api/videos/import.ts @@ -207,7 +207,7 @@ async function processThumbnail (req: express.Request, video: VideoModel) { if (thumbnailField) { const thumbnailPhysicalFile = thumbnailField[ 0 ] - return createVideoMiniatureFromExisting(thumbnailPhysicalFile.path, video, ThumbnailType.MINIATURE) + return createVideoMiniatureFromExisting(thumbnailPhysicalFile.path, video, ThumbnailType.MINIATURE, false) } return undefined @@ -218,7 +218,7 @@ async function processPreview (req: express.Request, video: VideoModel) { if (previewField) { const previewPhysicalFile = previewField[0] - return createVideoMiniatureFromExisting(previewPhysicalFile.path, video, ThumbnailType.PREVIEW) + return createVideoMiniatureFromExisting(previewPhysicalFile.path, video, ThumbnailType.PREVIEW, false) } return undefined diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 973bf1123..155ca4678 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts @@ -223,13 +223,13 @@ async function addVideo (req: express.Request, res: express.Response) { // Process thumbnail or create it from the video const thumbnailField = req.files['thumbnailfile'] const thumbnailModel = thumbnailField - ? await createVideoMiniatureFromExisting(thumbnailField[0].path, video, ThumbnailType.MINIATURE) + ? await createVideoMiniatureFromExisting(thumbnailField[0].path, video, ThumbnailType.MINIATURE, false) : await generateVideoMiniature(video, videoFile, ThumbnailType.MINIATURE) // Process preview or create it from the video const previewField = req.files['previewfile'] const previewModel = previewField - ? await createVideoMiniatureFromExisting(previewField[0].path, video, ThumbnailType.PREVIEW) + ? await createVideoMiniatureFromExisting(previewField[0].path, video, ThumbnailType.PREVIEW, false) : await generateVideoMiniature(video, videoFile, ThumbnailType.PREVIEW) // Create the torrent file @@ -329,11 +329,11 @@ async function updateVideo (req: express.Request, res: express.Response) { // Process thumbnail or create it from the video const thumbnailModel = req.files && req.files['thumbnailfile'] - ? await createVideoMiniatureFromExisting(req.files['thumbnailfile'][0].path, videoInstance, ThumbnailType.MINIATURE) + ? await createVideoMiniatureFromExisting(req.files['thumbnailfile'][0].path, videoInstance, ThumbnailType.MINIATURE, false) : undefined const previewModel = req.files && req.files['previewfile'] - ? await createVideoMiniatureFromExisting(req.files['previewfile'][0].path, videoInstance, ThumbnailType.PREVIEW) + ? await createVideoMiniatureFromExisting(req.files['previewfile'][0].path, videoInstance, ThumbnailType.PREVIEW, false) : undefined try { -- cgit v1.2.3