diff options
Diffstat (limited to 'server/lib')
-rw-r--r-- | server/lib/activitypub/playlist.ts | 2 | ||||
-rw-r--r-- | server/lib/activitypub/videos.ts | 154 | ||||
-rw-r--r-- | server/lib/files-cache/videos-preview-cache.ts | 2 | ||||
-rw-r--r-- | server/lib/job-queue/handlers/video-import.ts | 12 | ||||
-rw-r--r-- | server/lib/job-queue/handlers/video-live-ending.ts | 12 | ||||
-rw-r--r-- | server/lib/thumbnail.ts | 110 |
6 files changed, 196 insertions, 96 deletions
diff --git a/server/lib/activitypub/playlist.ts b/server/lib/activitypub/playlist.ts index 53298e968..d5a3ef7c8 100644 --- a/server/lib/activitypub/playlist.ts +++ b/server/lib/activitypub/playlist.ts | |||
@@ -103,7 +103,7 @@ async function createOrUpdateVideoPlaylist (playlistObject: PlaylistObject, byAc | |||
103 | 103 | ||
104 | if (playlistObject.icon) { | 104 | if (playlistObject.icon) { |
105 | try { | 105 | try { |
106 | const thumbnailModel = await createPlaylistMiniatureFromUrl(playlistObject.icon.url, refreshedPlaylist) | 106 | const thumbnailModel = await createPlaylistMiniatureFromUrl({ downloadUrl: playlistObject.icon.url, playlist: refreshedPlaylist }) |
107 | await refreshedPlaylist.setAndSaveThumbnail(thumbnailModel, undefined) | 107 | await refreshedPlaylist.setAndSaveThumbnail(thumbnailModel, undefined) |
108 | } catch (err) { | 108 | } catch (err) { |
109 | logger.warn('Cannot generate thumbnail of %s.', playlistObject.id, { err }) | 109 | logger.warn('Cannot generate thumbnail of %s.', playlistObject.id, { err }) |
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts index 201ef0302..66981f43f 100644 --- a/server/lib/activitypub/videos.ts +++ b/server/lib/activitypub/videos.ts | |||
@@ -313,7 +313,11 @@ async function updateVideoFromAP (options: { | |||
313 | let thumbnailModel: MThumbnail | 313 | let thumbnailModel: MThumbnail |
314 | 314 | ||
315 | try { | 315 | try { |
316 | thumbnailModel = await createVideoMiniatureFromUrl(getThumbnailFromIcons(videoObject).url, video, ThumbnailType.MINIATURE) | 316 | thumbnailModel = await createVideoMiniatureFromUrl({ |
317 | downloadUrl: getThumbnailFromIcons(videoObject).url, | ||
318 | video, | ||
319 | type: ThumbnailType.MINIATURE | ||
320 | }) | ||
317 | } catch (err) { | 321 | } catch (err) { |
318 | logger.warn('Cannot generate thumbnail of %s.', videoObject.id, { err }) | 322 | logger.warn('Cannot generate thumbnail of %s.', videoObject.id, { err }) |
319 | } | 323 | } |
@@ -362,7 +366,12 @@ async function updateVideoFromAP (options: { | |||
362 | 366 | ||
363 | if (videoUpdated.getPreview()) { | 367 | if (videoUpdated.getPreview()) { |
364 | const previewUrl = getPreviewUrl(getPreviewFromIcons(videoObject), video) | 368 | const previewUrl = getPreviewUrl(getPreviewFromIcons(videoObject), video) |
365 | const previewModel = createPlaceholderThumbnail(previewUrl, video, ThumbnailType.PREVIEW, PREVIEWS_SIZE) | 369 | const previewModel = createPlaceholderThumbnail({ |
370 | fileUrl: previewUrl, | ||
371 | video, | ||
372 | type: ThumbnailType.PREVIEW, | ||
373 | size: PREVIEWS_SIZE | ||
374 | }) | ||
366 | await videoUpdated.addAndSaveThumbnail(previewModel, t) | 375 | await videoUpdated.addAndSaveThumbnail(previewModel, t) |
367 | } | 376 | } |
368 | 377 | ||
@@ -585,11 +594,14 @@ async function createVideo (videoObject: VideoObject, channel: MChannelAccountLi | |||
585 | const videoData = await videoActivityObjectToDBAttributes(channel, videoObject, videoObject.to) | 594 | const videoData = await videoActivityObjectToDBAttributes(channel, videoObject, videoObject.to) |
586 | const video = VideoModel.build(videoData) as MVideoThumbnail | 595 | const video = VideoModel.build(videoData) as MVideoThumbnail |
587 | 596 | ||
588 | const promiseThumbnail = createVideoMiniatureFromUrl(getThumbnailFromIcons(videoObject).url, video, ThumbnailType.MINIATURE) | 597 | const promiseThumbnail = createVideoMiniatureFromUrl({ |
589 | .catch(err => { | 598 | downloadUrl: getThumbnailFromIcons(videoObject).url, |
590 | logger.error('Cannot create miniature from url.', { err }) | 599 | video, |
591 | return undefined | 600 | type: ThumbnailType.MINIATURE |
592 | }) | 601 | }).catch(err => { |
602 | logger.error('Cannot create miniature from url.', { err }) | ||
603 | return undefined | ||
604 | }) | ||
593 | 605 | ||
594 | let thumbnailModel: MThumbnail | 606 | let thumbnailModel: MThumbnail |
595 | if (waitThumbnail === true) { | 607 | if (waitThumbnail === true) { |
@@ -597,81 +609,93 @@ async function createVideo (videoObject: VideoObject, channel: MChannelAccountLi | |||
597 | } | 609 | } |
598 | 610 | ||
599 | const { autoBlacklisted, videoCreated } = await sequelizeTypescript.transaction(async t => { | 611 | const { autoBlacklisted, videoCreated } = await sequelizeTypescript.transaction(async t => { |
600 | const sequelizeOptions = { transaction: t } | 612 | try { |
613 | const sequelizeOptions = { transaction: t } | ||
601 | 614 | ||
602 | const videoCreated = await video.save(sequelizeOptions) as MVideoFullLight | 615 | const videoCreated = await video.save(sequelizeOptions) as MVideoFullLight |
603 | videoCreated.VideoChannel = channel | 616 | videoCreated.VideoChannel = channel |
604 | 617 | ||
605 | if (thumbnailModel) await videoCreated.addAndSaveThumbnail(thumbnailModel, t) | 618 | if (thumbnailModel) await videoCreated.addAndSaveThumbnail(thumbnailModel, t) |
606 | 619 | ||
607 | const previewIcon = getPreviewFromIcons(videoObject) | 620 | const previewUrl = getPreviewUrl(getPreviewFromIcons(videoObject), videoCreated) |
608 | const previewUrl = getPreviewUrl(previewIcon, videoCreated) | 621 | const previewModel = createPlaceholderThumbnail({ |
609 | const previewModel = createPlaceholderThumbnail(previewUrl, videoCreated, ThumbnailType.PREVIEW, PREVIEWS_SIZE) | 622 | fileUrl: previewUrl, |
623 | video: videoCreated, | ||
624 | type: ThumbnailType.PREVIEW, | ||
625 | size: PREVIEWS_SIZE | ||
626 | }) | ||
610 | 627 | ||
611 | if (thumbnailModel) await videoCreated.addAndSaveThumbnail(previewModel, t) | 628 | if (thumbnailModel) await videoCreated.addAndSaveThumbnail(previewModel, t) |
612 | 629 | ||
613 | // Process files | 630 | // Process files |
614 | const videoFileAttributes = videoFileActivityUrlToDBAttributes(videoCreated, videoObject.url) | 631 | const videoFileAttributes = videoFileActivityUrlToDBAttributes(videoCreated, videoObject.url) |
615 | 632 | ||
616 | const videoFilePromises = videoFileAttributes.map(f => VideoFileModel.create(f, { transaction: t })) | 633 | const videoFilePromises = videoFileAttributes.map(f => VideoFileModel.create(f, { transaction: t })) |
617 | const videoFiles = await Promise.all(videoFilePromises) | 634 | const videoFiles = await Promise.all(videoFilePromises) |
618 | 635 | ||
619 | const streamingPlaylistsAttributes = streamingPlaylistActivityUrlToDBAttributes(videoCreated, videoObject, videoFiles) | 636 | const streamingPlaylistsAttributes = streamingPlaylistActivityUrlToDBAttributes(videoCreated, videoObject, videoFiles) |
620 | videoCreated.VideoStreamingPlaylists = [] | 637 | videoCreated.VideoStreamingPlaylists = [] |
621 | 638 | ||
622 | for (const playlistAttributes of streamingPlaylistsAttributes) { | 639 | for (const playlistAttributes of streamingPlaylistsAttributes) { |
623 | const playlistModel = await VideoStreamingPlaylistModel.create(playlistAttributes, { transaction: t }) | 640 | const playlistModel = await VideoStreamingPlaylistModel.create(playlistAttributes, { transaction: t }) |
624 | 641 | ||
625 | const playlistFiles = videoFileActivityUrlToDBAttributes(playlistModel, playlistAttributes.tagAPObject) | 642 | const playlistFiles = videoFileActivityUrlToDBAttributes(playlistModel, playlistAttributes.tagAPObject) |
626 | const videoFilePromises = playlistFiles.map(f => VideoFileModel.create(f, { transaction: t })) | 643 | const videoFilePromises = playlistFiles.map(f => VideoFileModel.create(f, { transaction: t })) |
627 | playlistModel.VideoFiles = await Promise.all(videoFilePromises) | 644 | playlistModel.VideoFiles = await Promise.all(videoFilePromises) |
628 | 645 | ||
629 | videoCreated.VideoStreamingPlaylists.push(playlistModel) | 646 | videoCreated.VideoStreamingPlaylists.push(playlistModel) |
630 | } | 647 | } |
631 | 648 | ||
632 | // Process tags | 649 | // Process tags |
633 | const tags = videoObject.tag | 650 | const tags = videoObject.tag |
634 | .filter(isAPHashTagObject) | 651 | .filter(isAPHashTagObject) |
635 | .map(t => t.name) | 652 | .map(t => t.name) |
636 | await setVideoTags({ video: videoCreated, tags, transaction: t }) | 653 | await setVideoTags({ video: videoCreated, tags, transaction: t }) |
637 | 654 | ||
638 | // Process captions | 655 | // Process captions |
639 | const videoCaptionsPromises = videoObject.subtitleLanguage.map(c => { | 656 | const videoCaptionsPromises = videoObject.subtitleLanguage.map(c => { |
640 | const caption = new VideoCaptionModel({ | 657 | const caption = new VideoCaptionModel({ |
641 | videoId: videoCreated.id, | 658 | videoId: videoCreated.id, |
642 | filename: VideoCaptionModel.generateCaptionName(c.identifier), | 659 | filename: VideoCaptionModel.generateCaptionName(c.identifier), |
643 | language: c.identifier, | 660 | language: c.identifier, |
644 | fileUrl: c.url | 661 | fileUrl: c.url |
645 | }) as MVideoCaption | 662 | }) as MVideoCaption |
646 | 663 | ||
647 | return VideoCaptionModel.insertOrReplaceLanguage(caption, t) | 664 | return VideoCaptionModel.insertOrReplaceLanguage(caption, t) |
648 | }) | 665 | }) |
649 | await Promise.all(videoCaptionsPromises) | 666 | await Promise.all(videoCaptionsPromises) |
650 | 667 | ||
651 | videoCreated.VideoFiles = videoFiles | 668 | videoCreated.VideoFiles = videoFiles |
652 | 669 | ||
653 | if (videoCreated.isLive) { | 670 | if (videoCreated.isLive) { |
654 | const videoLive = new VideoLiveModel({ | 671 | const videoLive = new VideoLiveModel({ |
655 | streamKey: null, | 672 | streamKey: null, |
656 | saveReplay: videoObject.liveSaveReplay, | 673 | saveReplay: videoObject.liveSaveReplay, |
657 | permanentLive: videoObject.permanentLive, | 674 | permanentLive: videoObject.permanentLive, |
658 | videoId: videoCreated.id | 675 | videoId: videoCreated.id |
659 | }) | 676 | }) |
660 | 677 | ||
661 | videoCreated.VideoLive = await videoLive.save({ transaction: t }) | 678 | videoCreated.VideoLive = await videoLive.save({ transaction: t }) |
662 | } | 679 | } |
663 | 680 | ||
664 | const autoBlacklisted = await autoBlacklistVideoIfNeeded({ | 681 | const autoBlacklisted = await autoBlacklistVideoIfNeeded({ |
665 | video: videoCreated, | 682 | video: videoCreated, |
666 | user: undefined, | 683 | user: undefined, |
667 | isRemote: true, | 684 | isRemote: true, |
668 | isNew: true, | 685 | isNew: true, |
669 | transaction: t | 686 | transaction: t |
670 | }) | 687 | }) |
671 | 688 | ||
672 | logger.info('Remote video with uuid %s inserted.', videoObject.uuid) | 689 | logger.info('Remote video with uuid %s inserted.', videoObject.uuid) |
673 | 690 | ||
674 | return { autoBlacklisted, videoCreated } | 691 | return { autoBlacklisted, videoCreated } |
692 | } catch (err) { | ||
693 | // FIXME: Use rollback hook when https://github.com/sequelize/sequelize/pull/13038 is released | ||
694 | // Remove thumbnail | ||
695 | if (thumbnailModel) await thumbnailModel.removeThumbnail() | ||
696 | |||
697 | throw err | ||
698 | } | ||
675 | }) | 699 | }) |
676 | 700 | ||
677 | if (waitThumbnail === false) { | 701 | if (waitThumbnail === false) { |
diff --git a/server/lib/files-cache/videos-preview-cache.ts b/server/lib/files-cache/videos-preview-cache.ts index 47488da74..ee72cd3f9 100644 --- a/server/lib/files-cache/videos-preview-cache.ts +++ b/server/lib/files-cache/videos-preview-cache.ts | |||
@@ -20,7 +20,7 @@ class VideosPreviewCache extends AbstractVideoStaticFileCache <string> { | |||
20 | } | 20 | } |
21 | 21 | ||
22 | async getFilePathImpl (filename: string) { | 22 | async getFilePathImpl (filename: string) { |
23 | const thumbnail = await ThumbnailModel.loadWithVideoByName(filename, ThumbnailType.PREVIEW) | 23 | const thumbnail = await ThumbnailModel.loadWithVideoByFilename(filename, ThumbnailType.PREVIEW) |
24 | if (!thumbnail) return undefined | 24 | if (!thumbnail) return undefined |
25 | 25 | ||
26 | if (thumbnail.Video.isOwned()) return { isOwned: true, path: thumbnail.getPath() } | 26 | if (thumbnail.Video.isOwned()) return { isOwned: true, path: thumbnail.getPath() } |
diff --git a/server/lib/job-queue/handlers/video-import.ts b/server/lib/job-queue/handlers/video-import.ts index 1e5e52b58..0d00c1b9d 100644 --- a/server/lib/job-queue/handlers/video-import.ts +++ b/server/lib/job-queue/handlers/video-import.ts | |||
@@ -162,7 +162,11 @@ async function processFile (downloader: () => Promise<string>, videoImport: MVid | |||
162 | let thumbnailModel: MThumbnail | 162 | let thumbnailModel: MThumbnail |
163 | let thumbnailSave: object | 163 | let thumbnailSave: object |
164 | if (!videoImportWithFiles.Video.getMiniature()) { | 164 | if (!videoImportWithFiles.Video.getMiniature()) { |
165 | thumbnailModel = await generateVideoMiniature(videoImportWithFiles.Video, videoFile, ThumbnailType.MINIATURE) | 165 | thumbnailModel = await generateVideoMiniature({ |
166 | video: videoImportWithFiles.Video, | ||
167 | videoFile, | ||
168 | type: ThumbnailType.MINIATURE | ||
169 | }) | ||
166 | thumbnailSave = thumbnailModel.toJSON() | 170 | thumbnailSave = thumbnailModel.toJSON() |
167 | } | 171 | } |
168 | 172 | ||
@@ -170,7 +174,11 @@ async function processFile (downloader: () => Promise<string>, videoImport: MVid | |||
170 | let previewModel: MThumbnail | 174 | let previewModel: MThumbnail |
171 | let previewSave: object | 175 | let previewSave: object |
172 | if (!videoImportWithFiles.Video.getPreview()) { | 176 | if (!videoImportWithFiles.Video.getPreview()) { |
173 | previewModel = await generateVideoMiniature(videoImportWithFiles.Video, videoFile, ThumbnailType.PREVIEW) | 177 | previewModel = await generateVideoMiniature({ |
178 | video: videoImportWithFiles.Video, | ||
179 | videoFile, | ||
180 | type: ThumbnailType.PREVIEW | ||
181 | }) | ||
174 | previewSave = previewModel.toJSON() | 182 | previewSave = previewModel.toJSON() |
175 | } | 183 | } |
176 | 184 | ||
diff --git a/server/lib/job-queue/handlers/video-live-ending.ts b/server/lib/job-queue/handlers/video-live-ending.ts index db6cd3682..6d50635bb 100644 --- a/server/lib/job-queue/handlers/video-live-ending.ts +++ b/server/lib/job-queue/handlers/video-live-ending.ts | |||
@@ -122,11 +122,19 @@ async function saveLive (video: MVideo, live: MVideoLive) { | |||
122 | 122 | ||
123 | // Regenerate the thumbnail & preview? | 123 | // Regenerate the thumbnail & preview? |
124 | if (videoWithFiles.getMiniature().automaticallyGenerated === true) { | 124 | if (videoWithFiles.getMiniature().automaticallyGenerated === true) { |
125 | await generateVideoMiniature(videoWithFiles, videoWithFiles.getMaxQualityFile(), ThumbnailType.MINIATURE) | 125 | await generateVideoMiniature({ |
126 | video: videoWithFiles, | ||
127 | videoFile: videoWithFiles.getMaxQualityFile(), | ||
128 | type: ThumbnailType.MINIATURE | ||
129 | }) | ||
126 | } | 130 | } |
127 | 131 | ||
128 | if (videoWithFiles.getPreview().automaticallyGenerated === true) { | 132 | if (videoWithFiles.getPreview().automaticallyGenerated === true) { |
129 | await generateVideoMiniature(videoWithFiles, videoWithFiles.getMaxQualityFile(), ThumbnailType.PREVIEW) | 133 | await generateVideoMiniature({ |
134 | video: videoWithFiles, | ||
135 | videoFile: videoWithFiles.getMaxQualityFile(), | ||
136 | type: ThumbnailType.PREVIEW | ||
137 | }) | ||
130 | } | 138 | } |
131 | 139 | ||
132 | await publishAndFederateIfNeeded(videoWithFiles, true) | 140 | await publishAndFederateIfNeeded(videoWithFiles, true) |
diff --git a/server/lib/thumbnail.ts b/server/lib/thumbnail.ts index 33aa7159c..55478299c 100644 --- a/server/lib/thumbnail.ts +++ b/server/lib/thumbnail.ts | |||
@@ -1,33 +1,48 @@ | |||
1 | import { join } from 'path' | ||
2 | |||
3 | import { ThumbnailType } from '../../shared/models/videos/thumbnail.type' | ||
1 | import { generateImageFromVideoFile } from '../helpers/ffmpeg-utils' | 4 | import { generateImageFromVideoFile } from '../helpers/ffmpeg-utils' |
5 | import { processImage } from '../helpers/image-utils' | ||
6 | import { downloadImage } from '../helpers/requests' | ||
2 | import { CONFIG } from '../initializers/config' | 7 | import { CONFIG } from '../initializers/config' |
3 | import { ASSETS_PATH, PREVIEWS_SIZE, THUMBNAILS_SIZE } from '../initializers/constants' | 8 | import { ASSETS_PATH, PREVIEWS_SIZE, THUMBNAILS_SIZE } from '../initializers/constants' |
4 | import { ThumbnailModel } from '../models/video/thumbnail' | 9 | import { ThumbnailModel } from '../models/video/thumbnail' |
5 | import { ThumbnailType } from '../../shared/models/videos/thumbnail.type' | ||
6 | import { processImage } from '../helpers/image-utils' | ||
7 | import { join } from 'path' | ||
8 | import { downloadImage } from '../helpers/requests' | ||
9 | import { MVideoPlaylistThumbnail } from '../types/models/video/video-playlist' | ||
10 | import { MVideoFile, MVideoThumbnail } from '../types/models' | 10 | import { MVideoFile, MVideoThumbnail } from '../types/models' |
11 | import { MThumbnail } from '../types/models/video/thumbnail' | 11 | import { MThumbnail } from '../types/models/video/thumbnail' |
12 | import { MVideoPlaylistThumbnail } from '../types/models/video/video-playlist' | ||
12 | import { getVideoFilePath } from './video-paths' | 13 | import { getVideoFilePath } from './video-paths' |
13 | 14 | ||
14 | type ImageSize = { height: number, width: number } | 15 | type ImageSize = { height: number, width: number } |
15 | 16 | ||
16 | function createPlaylistMiniatureFromExisting ( | 17 | function createPlaylistMiniatureFromExisting (options: { |
17 | inputPath: string, | 18 | inputPath: string |
18 | playlist: MVideoPlaylistThumbnail, | 19 | playlist: MVideoPlaylistThumbnail |
19 | automaticallyGenerated: boolean, | 20 | automaticallyGenerated: boolean |
20 | keepOriginal = false, | 21 | keepOriginal?: boolean // default to false |
21 | size?: ImageSize | 22 | size?: ImageSize |
22 | ) { | 23 | }) { |
24 | const { inputPath, playlist, automaticallyGenerated, keepOriginal = false, size } = options | ||
23 | const { filename, outputPath, height, width, existingThumbnail } = buildMetadataFromPlaylist(playlist, size) | 25 | const { filename, outputPath, height, width, existingThumbnail } = buildMetadataFromPlaylist(playlist, size) |
24 | const type = ThumbnailType.MINIATURE | 26 | const type = ThumbnailType.MINIATURE |
25 | 27 | ||
26 | const thumbnailCreator = () => processImage(inputPath, outputPath, { width, height }, keepOriginal) | 28 | const thumbnailCreator = () => processImage(inputPath, outputPath, { width, height }, keepOriginal) |
27 | return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, automaticallyGenerated, existingThumbnail }) | 29 | return createThumbnailFromFunction({ |
30 | thumbnailCreator, | ||
31 | filename, | ||
32 | height, | ||
33 | width, | ||
34 | type, | ||
35 | automaticallyGenerated, | ||
36 | existingThumbnail | ||
37 | }) | ||
28 | } | 38 | } |
29 | 39 | ||
30 | function createPlaylistMiniatureFromUrl (downloadUrl: string, playlist: MVideoPlaylistThumbnail, size?: ImageSize) { | 40 | function createPlaylistMiniatureFromUrl (options: { |
41 | downloadUrl: string | ||
42 | playlist: MVideoPlaylistThumbnail | ||
43 | size?: ImageSize | ||
44 | }) { | ||
45 | const { downloadUrl, playlist, size } = options | ||
31 | const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromPlaylist(playlist, size) | 46 | const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromPlaylist(playlist, size) |
32 | const type = ThumbnailType.MINIATURE | 47 | const type = ThumbnailType.MINIATURE |
33 | 48 | ||
@@ -40,7 +55,13 @@ function createPlaylistMiniatureFromUrl (downloadUrl: string, playlist: MVideoPl | |||
40 | return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail, fileUrl }) | 55 | return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail, fileUrl }) |
41 | } | 56 | } |
42 | 57 | ||
43 | function createVideoMiniatureFromUrl (downloadUrl: string, video: MVideoThumbnail, type: ThumbnailType, size?: ImageSize) { | 58 | function createVideoMiniatureFromUrl (options: { |
59 | downloadUrl: string | ||
60 | video: MVideoThumbnail | ||
61 | type: ThumbnailType | ||
62 | size?: ImageSize | ||
63 | }) { | ||
64 | const { downloadUrl, video, type, size } = options | ||
44 | const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size) | 65 | const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size) |
45 | 66 | ||
46 | // Only save the file URL if it is a remote video | 67 | // Only save the file URL if it is a remote video |
@@ -58,17 +79,31 @@ function createVideoMiniatureFromExisting (options: { | |||
58 | type: ThumbnailType | 79 | type: ThumbnailType |
59 | automaticallyGenerated: boolean | 80 | automaticallyGenerated: boolean |
60 | size?: ImageSize | 81 | size?: ImageSize |
61 | keepOriginal?: boolean | 82 | keepOriginal?: boolean // default to false |
62 | }) { | 83 | }) { |
63 | const { inputPath, video, type, automaticallyGenerated, size, keepOriginal } = options | 84 | const { inputPath, video, type, automaticallyGenerated, size, keepOriginal = false } = options |
64 | 85 | ||
65 | const { filename, outputPath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size) | 86 | const { filename, outputPath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size) |
66 | const thumbnailCreator = () => processImage(inputPath, outputPath, { width, height }, keepOriginal) | 87 | const thumbnailCreator = () => processImage(inputPath, outputPath, { width, height }, keepOriginal) |
67 | 88 | ||
68 | return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, automaticallyGenerated, existingThumbnail }) | 89 | return createThumbnailFromFunction({ |
90 | thumbnailCreator, | ||
91 | filename, | ||
92 | height, | ||
93 | width, | ||
94 | type, | ||
95 | automaticallyGenerated, | ||
96 | existingThumbnail | ||
97 | }) | ||
69 | } | 98 | } |
70 | 99 | ||
71 | function generateVideoMiniature (video: MVideoThumbnail, videoFile: MVideoFile, type: ThumbnailType) { | 100 | function generateVideoMiniature (options: { |
101 | video: MVideoThumbnail | ||
102 | videoFile: MVideoFile | ||
103 | type: ThumbnailType | ||
104 | }) { | ||
105 | const { video, videoFile, type } = options | ||
106 | |||
72 | const input = getVideoFilePath(video, videoFile) | 107 | const input = getVideoFilePath(video, videoFile) |
73 | 108 | ||
74 | const { filename, basePath, height, width, existingThumbnail, outputPath } = buildMetadataFromVideo(video, type) | 109 | const { filename, basePath, height, width, existingThumbnail, outputPath } = buildMetadataFromVideo(video, type) |
@@ -76,10 +111,24 @@ function generateVideoMiniature (video: MVideoThumbnail, videoFile: MVideoFile, | |||
76 | ? () => processImage(ASSETS_PATH.DEFAULT_AUDIO_BACKGROUND, outputPath, { width, height }, true) | 111 | ? () => processImage(ASSETS_PATH.DEFAULT_AUDIO_BACKGROUND, outputPath, { width, height }, true) |
77 | : () => generateImageFromVideoFile(input, basePath, filename, { height, width }) | 112 | : () => generateImageFromVideoFile(input, basePath, filename, { height, width }) |
78 | 113 | ||
79 | return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, automaticallyGenerated: true, existingThumbnail }) | 114 | return createThumbnailFromFunction({ |
115 | thumbnailCreator, | ||
116 | filename, | ||
117 | height, | ||
118 | width, | ||
119 | type, | ||
120 | automaticallyGenerated: true, | ||
121 | existingThumbnail | ||
122 | }) | ||
80 | } | 123 | } |
81 | 124 | ||
82 | function createPlaceholderThumbnail (fileUrl: string, video: MVideoThumbnail, type: ThumbnailType, size: ImageSize) { | 125 | function createPlaceholderThumbnail (options: { |
126 | fileUrl: string | ||
127 | video: MVideoThumbnail | ||
128 | type: ThumbnailType | ||
129 | size: ImageSize | ||
130 | }) { | ||
131 | const { fileUrl, video, type, size } = options | ||
83 | const { filename, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size) | 132 | const { filename, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size) |
84 | 133 | ||
85 | const thumbnail = existingThumbnail || new ThumbnailModel() | 134 | const thumbnail = existingThumbnail || new ThumbnailModel() |
@@ -164,12 +213,22 @@ async function createThumbnailFromFunction (parameters: { | |||
164 | fileUrl?: string | 213 | fileUrl?: string |
165 | existingThumbnail?: MThumbnail | 214 | existingThumbnail?: MThumbnail |
166 | }) { | 215 | }) { |
167 | const { thumbnailCreator, filename, width, height, type, existingThumbnail, automaticallyGenerated = null, fileUrl = null } = parameters | 216 | const { |
168 | 217 | thumbnailCreator, | |
169 | // Remove old file | 218 | filename, |
170 | if (existingThumbnail) await existingThumbnail.removeThumbnail() | 219 | width, |
220 | height, | ||
221 | type, | ||
222 | existingThumbnail, | ||
223 | automaticallyGenerated = null, | ||
224 | fileUrl = null | ||
225 | } = parameters | ||
226 | |||
227 | const oldFilename = existingThumbnail | ||
228 | ? existingThumbnail.filename | ||
229 | : undefined | ||
171 | 230 | ||
172 | const thumbnail = existingThumbnail || new ThumbnailModel() | 231 | const thumbnail: MThumbnail = existingThumbnail || new ThumbnailModel() |
173 | 232 | ||
174 | thumbnail.filename = filename | 233 | thumbnail.filename = filename |
175 | thumbnail.height = height | 234 | thumbnail.height = height |
@@ -177,6 +236,7 @@ async function createThumbnailFromFunction (parameters: { | |||
177 | thumbnail.type = type | 236 | thumbnail.type = type |
178 | thumbnail.fileUrl = fileUrl | 237 | thumbnail.fileUrl = fileUrl |
179 | thumbnail.automaticallyGenerated = automaticallyGenerated | 238 | thumbnail.automaticallyGenerated = automaticallyGenerated |
239 | thumbnail.previousThumbnailFilename = oldFilename | ||
180 | 240 | ||
181 | await thumbnailCreator() | 241 | await thumbnailCreator() |
182 | 242 | ||