thumbnail.ts 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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, ASSETS_PATH } 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'
  12. type ImageSize = { height: number, width: number }
  13. function createPlaylistMiniatureFromExisting (inputPath: string, playlist: VideoPlaylistModel, keepOriginal = false, size?: ImageSize) {
  14. const { filename, outputPath, height, width, existingThumbnail } = buildMetadataFromPlaylist(playlist, size)
  15. const type = ThumbnailType.MINIATURE
  16. const thumbnailCreator = () => processImage(inputPath, outputPath, { width, height }, keepOriginal)
  17. return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail })
  18. }
  19. function createPlaylistMiniatureFromUrl (fileUrl: string, playlist: VideoPlaylistModel, size?: ImageSize) {
  20. const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromPlaylist(playlist, size)
  21. const type = ThumbnailType.MINIATURE
  22. const thumbnailCreator = () => downloadImage(fileUrl, basePath, filename, { width, height })
  23. return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail, fileUrl })
  24. }
  25. function createVideoMiniatureFromUrl (fileUrl: string, video: VideoModel, type: ThumbnailType, size?: ImageSize) {
  26. const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size)
  27. const thumbnailCreator = () => downloadImage(fileUrl, basePath, filename, { width, height })
  28. return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail, fileUrl })
  29. }
  30. function createVideoMiniatureFromExisting (inputPath: string, video: VideoModel, type: ThumbnailType, size?: ImageSize) {
  31. const { filename, outputPath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size)
  32. const thumbnailCreator = () => processImage(inputPath, outputPath, { width, height })
  33. return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail })
  34. }
  35. function generateVideoMiniature (video: VideoModel, videoFile: VideoFileModel, type: ThumbnailType) {
  36. const input = video.getVideoFilePath(videoFile)
  37. const { filename, basePath, height, width, existingThumbnail, outputPath } = buildMetadataFromVideo(video, type)
  38. const thumbnailCreator = videoFile.isAudio()
  39. ? () => processImage(ASSETS_PATH.DEFAULT_AUDIO_BACKGROUND, outputPath, { width, height }, true)
  40. : () => generateImageFromVideoFile(input, basePath, filename, { height, width })
  41. return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail })
  42. }
  43. function createPlaceholderThumbnail (fileUrl: string, video: VideoModel, type: ThumbnailType, size: ImageSize) {
  44. const { filename, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size)
  45. const thumbnail = existingThumbnail ? existingThumbnail : new ThumbnailModel()
  46. thumbnail.filename = filename
  47. thumbnail.height = height
  48. thumbnail.width = width
  49. thumbnail.type = type
  50. thumbnail.fileUrl = fileUrl
  51. return thumbnail
  52. }
  53. // ---------------------------------------------------------------------------
  54. export {
  55. generateVideoMiniature,
  56. createVideoMiniatureFromUrl,
  57. createVideoMiniatureFromExisting,
  58. createPlaceholderThumbnail,
  59. createPlaylistMiniatureFromUrl,
  60. createPlaylistMiniatureFromExisting
  61. }
  62. function buildMetadataFromPlaylist (playlist: VideoPlaylistModel, size: ImageSize) {
  63. const filename = playlist.generateThumbnailName()
  64. const basePath = CONFIG.STORAGE.THUMBNAILS_DIR
  65. return {
  66. filename,
  67. basePath,
  68. existingThumbnail: playlist.Thumbnail,
  69. outputPath: join(basePath, filename),
  70. height: size ? size.height : THUMBNAILS_SIZE.height,
  71. width: size ? size.width : THUMBNAILS_SIZE.width
  72. }
  73. }
  74. function buildMetadataFromVideo (video: VideoModel, type: ThumbnailType, size?: ImageSize) {
  75. const existingThumbnail = Array.isArray(video.Thumbnails)
  76. ? video.Thumbnails.find(t => t.type === type)
  77. : undefined
  78. if (type === ThumbnailType.MINIATURE) {
  79. const filename = video.generateThumbnailName()
  80. const basePath = CONFIG.STORAGE.THUMBNAILS_DIR
  81. return {
  82. filename,
  83. basePath,
  84. existingThumbnail,
  85. outputPath: join(basePath, filename),
  86. height: size ? size.height : THUMBNAILS_SIZE.height,
  87. width: size ? size.width : THUMBNAILS_SIZE.width
  88. }
  89. }
  90. if (type === ThumbnailType.PREVIEW) {
  91. const filename = video.generatePreviewName()
  92. const basePath = CONFIG.STORAGE.PREVIEWS_DIR
  93. return {
  94. filename,
  95. basePath,
  96. existingThumbnail,
  97. outputPath: join(basePath, filename),
  98. height: size ? size.height : PREVIEWS_SIZE.height,
  99. width: size ? size.width : PREVIEWS_SIZE.width
  100. }
  101. }
  102. return undefined
  103. }
  104. async function createThumbnailFromFunction (parameters: {
  105. thumbnailCreator: () => Promise<any>,
  106. filename: string,
  107. height: number,
  108. width: number,
  109. type: ThumbnailType,
  110. fileUrl?: string,
  111. existingThumbnail?: ThumbnailModel
  112. }) {
  113. const { thumbnailCreator, filename, width, height, type, existingThumbnail, fileUrl = null } = parameters
  114. const thumbnail = existingThumbnail ? existingThumbnail : new ThumbnailModel()
  115. thumbnail.filename = filename
  116. thumbnail.height = height
  117. thumbnail.width = width
  118. thumbnail.type = type
  119. thumbnail.fileUrl = fileUrl
  120. await thumbnailCreator()
  121. return thumbnail
  122. }