1 import { VideoFileModel } from '../models/video/video-file'
2 import { generateImageFromVideoFile } from '../helpers/ffmpeg-utils'
3 import { CONFIG } from '../initializers/config'
4 import { PREVIEWS_SIZE, THUMBNAILS_SIZE } from '../initializers/constants'
5 import { VideoModel } from '../models/video/video'
6 import { ThumbnailModel } from '../models/video/thumbnail'
7 import { ThumbnailType } from '../../shared/models/videos/thumbnail.type'
8 import { processImage } from '../helpers/image-utils'
9 import { join } from 'path'
10 import { downloadImage } from '../helpers/requests'
11 import { VideoPlaylistModel } from '../models/video/video-playlist'
13 type ImageSize = { height: number, width: number }
15 function createPlaylistMiniatureFromExisting (inputPath: string, playlist: VideoPlaylistModel, keepOriginal = false, size?: ImageSize) {
16 const { filename, outputPath, height, width, existingThumbnail } = buildMetadataFromPlaylist(playlist, size)
17 const type = ThumbnailType.MINIATURE
19 const thumbnailCreator = () => processImage(inputPath, outputPath, { width, height }, keepOriginal)
20 return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail })
23 function createPlaylistMiniatureFromUrl (fileUrl: string, playlist: VideoPlaylistModel, size?: ImageSize) {
24 const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromPlaylist(playlist, size)
25 const type = ThumbnailType.MINIATURE
27 const thumbnailCreator = () => downloadImage(fileUrl, basePath, filename, { width, height })
28 return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail, fileUrl })
31 function createVideoMiniatureFromUrl (fileUrl: string, video: VideoModel, type: ThumbnailType, size?: ImageSize) {
32 const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size)
33 const thumbnailCreator = () => downloadImage(fileUrl, basePath, filename, { width, height })
35 return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail, fileUrl })
38 function createVideoMiniatureFromExisting (inputPath: string, video: VideoModel, type: ThumbnailType, size?: ImageSize) {
39 const { filename, outputPath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size)
40 const thumbnailCreator = () => processImage(inputPath, outputPath, { width, height })
42 return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail })
45 function generateVideoMiniature (video: VideoModel, videoFile: VideoFileModel, type: ThumbnailType) {
46 const input = video.getVideoFilePath(videoFile)
48 const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type)
49 const thumbnailCreator = () => generateImageFromVideoFile(input, basePath, filename, { height, width })
51 return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail })
54 function createPlaceholderThumbnail (fileUrl: string, video: VideoModel, type: ThumbnailType, size: ImageSize) {
55 const { filename, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size)
57 const thumbnail = existingThumbnail ? existingThumbnail : new ThumbnailModel()
59 thumbnail.filename = filename
60 thumbnail.height = height
61 thumbnail.width = width
63 thumbnail.fileUrl = fileUrl
68 // ---------------------------------------------------------------------------
71 generateVideoMiniature,
72 createVideoMiniatureFromUrl,
73 createVideoMiniatureFromExisting,
74 createPlaceholderThumbnail,
75 createPlaylistMiniatureFromUrl,
76 createPlaylistMiniatureFromExisting
79 function buildMetadataFromPlaylist (playlist: VideoPlaylistModel, size: ImageSize) {
80 const filename = playlist.generateThumbnailName()
81 const basePath = CONFIG.STORAGE.THUMBNAILS_DIR
86 existingThumbnail: playlist.Thumbnail,
87 outputPath: join(basePath, filename),
88 height: size ? size.height : THUMBNAILS_SIZE.height,
89 width: size ? size.width : THUMBNAILS_SIZE.width
93 function buildMetadataFromVideo (video: VideoModel, type: ThumbnailType, size?: ImageSize) {
94 const existingThumbnail = Array.isArray(video.Thumbnails)
95 ? video.Thumbnails.find(t => t.type === type)
98 if (type === ThumbnailType.MINIATURE) {
99 const filename = video.generateThumbnailName()
100 const basePath = CONFIG.STORAGE.THUMBNAILS_DIR
106 outputPath: join(basePath, filename),
107 height: size ? size.height : THUMBNAILS_SIZE.height,
108 width: size ? size.width : THUMBNAILS_SIZE.width
112 if (type === ThumbnailType.PREVIEW) {
113 const filename = video.generatePreviewName()
114 const basePath = CONFIG.STORAGE.PREVIEWS_DIR
120 outputPath: join(basePath, filename),
121 height: size ? size.height : PREVIEWS_SIZE.height,
122 width: size ? size.width : PREVIEWS_SIZE.width
129 async function createThumbnailFromFunction (parameters: {
130 thumbnailCreator: () => Promise<any>,
136 existingThumbnail?: ThumbnailModel
138 const { thumbnailCreator, filename, width, height, type, existingThumbnail, fileUrl = null } = parameters
140 const thumbnail = existingThumbnail ? existingThumbnail : new ThumbnailModel()
142 thumbnail.filename = filename
143 thumbnail.height = height
144 thumbnail.width = width
145 thumbnail.type = type
146 thumbnail.fileUrl = fileUrl
148 await thumbnailCreator()