X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Flib%2Fthumbnail.ts;h=c085239880ded8dfbce700b10ce5b2b706ef0c98;hb=679c12e69c9f3a2d003ee3abe8b8da49f25b2bd3;hp=4bad8d6ca84e8a027bbf15e00a62188c4420ff35;hpb=1664bc60eb7aa3fa3792b6acff50f9bbabd3d877;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/lib/thumbnail.ts b/server/lib/thumbnail.ts index 4bad8d6ca..c08523988 100644 --- a/server/lib/thumbnail.ts +++ b/server/lib/thumbnail.ts @@ -1,20 +1,20 @@ -import { copy } from 'fs-extra' import { join } from 'path' + import { ThumbnailType } from '../../shared/models/videos/thumbnail.type' import { generateImageFromVideoFile } from '../helpers/ffmpeg-utils' -import { processImage } from '../helpers/image-utils' +import { generateImageFilename, processImage } from '../helpers/image-utils' import { downloadImage } from '../helpers/requests' import { CONFIG } from '../initializers/config' import { ASSETS_PATH, PREVIEWS_SIZE, THUMBNAILS_SIZE } from '../initializers/constants' import { ThumbnailModel } from '../models/video/thumbnail' -import { MVideoFile, MVideoThumbnail } from '../types/models' +import { MVideoFile, MVideoThumbnail, MVideoUUID } from '../types/models' import { MThumbnail } from '../types/models/video/thumbnail' import { MVideoPlaylistThumbnail } from '../types/models/video/video-playlist' import { getVideoFilePath } from './video-paths' -type ImageSize = { height: number, width: number } +type ImageSize = { height?: number, width?: number } -function createPlaylistMiniatureFromExisting (options: { +function updatePlaylistMiniatureFromExisting (options: { inputPath: string playlist: MVideoPlaylistThumbnail automaticallyGenerated: boolean @@ -26,7 +26,7 @@ function createPlaylistMiniatureFromExisting (options: { const type = ThumbnailType.MINIATURE const thumbnailCreator = () => processImage(inputPath, outputPath, { width, height }, keepOriginal) - return createThumbnailFromFunction({ + return updateThumbnailFromFunction({ thumbnailCreator, filename, height, @@ -37,7 +37,7 @@ function createPlaylistMiniatureFromExisting (options: { }) } -function createPlaylistMiniatureFromUrl (options: { +function updatePlaylistMiniatureFromUrl (options: { downloadUrl: string playlist: MVideoPlaylistThumbnail size?: ImageSize @@ -52,40 +52,40 @@ function createPlaylistMiniatureFromUrl (options: { : downloadUrl const thumbnailCreator = () => downloadImage(downloadUrl, basePath, filename, { width, height }) - return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail, fileUrl }) + return updateThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail, fileUrl }) } -function createVideoMiniatureFromUrl (options: { +function updateVideoMiniatureFromUrl (options: { downloadUrl: string video: MVideoThumbnail type: ThumbnailType size?: ImageSize }) { const { downloadUrl, video, type, size } = options - const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size) + const { filename: updatedFilename, basePath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size) // Only save the file URL if it is a remote video const fileUrl = video.isOwned() ? null : downloadUrl - // If the thumbnail URL did not change - const existingUrl = existingThumbnail - ? existingThumbnail.fileUrl - : null + const thumbnailUrlChanged = hasThumbnailUrlChanged(existingThumbnail, downloadUrl, video) + + // Do not change the thumbnail filename if the file did not change + const filename = thumbnailUrlChanged + ? updatedFilename + : existingThumbnail.filename - // If the thumbnail URL did not change and has a unique filename (introduced in 3.2), avoid thumbnail processing - const thumbnailUrlChanged = !existingUrl || existingUrl !== downloadUrl || downloadUrl.endsWith(`${video.uuid}.jpg`) const thumbnailCreator = () => { if (thumbnailUrlChanged) return downloadImage(downloadUrl, basePath, filename, { width, height }) - return copy(existingThumbnail.getPath(), ThumbnailModel.buildPath(type, filename)) + return Promise.resolve() } - return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail, fileUrl }) + return updateThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail, fileUrl }) } -function createVideoMiniatureFromExisting (options: { +function updateVideoMiniatureFromExisting (options: { inputPath: string video: MVideoThumbnail type: ThumbnailType @@ -98,7 +98,7 @@ function createVideoMiniatureFromExisting (options: { const { filename, outputPath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size) const thumbnailCreator = () => processImage(inputPath, outputPath, { width, height }, keepOriginal) - return createThumbnailFromFunction({ + return updateThumbnailFromFunction({ thumbnailCreator, filename, height, @@ -123,7 +123,7 @@ function generateVideoMiniature (options: { ? () => processImage(ASSETS_PATH.DEFAULT_AUDIO_BACKGROUND, outputPath, { width, height }, true) : () => generateImageFromVideoFile(input, basePath, filename, { height, width }) - return createThumbnailFromFunction({ + return updateThumbnailFromFunction({ thumbnailCreator, filename, height, @@ -134,17 +134,24 @@ function generateVideoMiniature (options: { }) } -function createPlaceholderThumbnail (options: { +function updatePlaceholderThumbnail (options: { fileUrl: string video: MVideoThumbnail type: ThumbnailType size: ImageSize }) { const { fileUrl, video, type, size } = options - const { filename, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size) + const { filename: updatedFilename, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size) + + const thumbnailUrlChanged = hasThumbnailUrlChanged(existingThumbnail, fileUrl, video) const thumbnail = existingThumbnail || new ThumbnailModel() + // Do not change the thumbnail filename if the file did not change + const filename = thumbnailUrlChanged + ? updatedFilename + : existingThumbnail.filename + thumbnail.filename = filename thumbnail.height = height thumbnail.width = width @@ -158,11 +165,20 @@ function createPlaceholderThumbnail (options: { export { generateVideoMiniature, - createVideoMiniatureFromUrl, - createVideoMiniatureFromExisting, - createPlaceholderThumbnail, - createPlaylistMiniatureFromUrl, - createPlaylistMiniatureFromExisting + updateVideoMiniatureFromUrl, + updateVideoMiniatureFromExisting, + updatePlaceholderThumbnail, + updatePlaylistMiniatureFromUrl, + updatePlaylistMiniatureFromExisting +} + +function hasThumbnailUrlChanged (existingThumbnail: MThumbnail, downloadUrl: string, video: MVideoUUID) { + const existingUrl = existingThumbnail + ? existingThumbnail.fileUrl + : null + + // If the thumbnail URL did not change and has a unique filename (introduced in 3.1), avoid thumbnail processing + return !existingUrl || existingUrl !== downloadUrl || downloadUrl.endsWith(`${video.uuid}.jpg`) } function buildMetadataFromPlaylist (playlist: MVideoPlaylistThumbnail, size: ImageSize) { @@ -185,7 +201,7 @@ function buildMetadataFromVideo (video: MVideoThumbnail, type: ThumbnailType, si : undefined if (type === ThumbnailType.MINIATURE) { - const filename = video.generateThumbnailName() + const filename = generateImageFilename() const basePath = CONFIG.STORAGE.THUMBNAILS_DIR return { @@ -199,7 +215,7 @@ function buildMetadataFromVideo (video: MVideoThumbnail, type: ThumbnailType, si } if (type === ThumbnailType.PREVIEW) { - const filename = video.generatePreviewName() + const filename = generateImageFilename() const basePath = CONFIG.STORAGE.PREVIEWS_DIR return { @@ -215,7 +231,7 @@ function buildMetadataFromVideo (video: MVideoThumbnail, type: ThumbnailType, si return undefined } -async function createThumbnailFromFunction (parameters: { +async function updateThumbnailFromFunction (parameters: { thumbnailCreator: () => Promise filename: string height: number @@ -236,7 +252,7 @@ async function createThumbnailFromFunction (parameters: { fileUrl = null } = parameters - const oldFilename = existingThumbnail + const oldFilename = existingThumbnail && existingThumbnail.filename !== filename ? existingThumbnail.filename : undefined @@ -248,7 +264,8 @@ async function createThumbnailFromFunction (parameters: { thumbnail.type = type thumbnail.fileUrl = fileUrl thumbnail.automaticallyGenerated = automaticallyGenerated - thumbnail.previousThumbnailFilename = oldFilename + + if (oldFilename) thumbnail.previousThumbnailFilename = oldFilename await thumbnailCreator()