video-jobs.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. import { ManageVideoTorrentPayload, VideoPrivacy, VideoPrivacyType, VideoState, VideoStateType } from '@peertube/peertube-models'
  2. import { CONFIG } from '@server/initializers/config.js'
  3. import { VideoJobInfoModel } from '@server/models/video/video-job-info.js'
  4. import { MVideo, MVideoFile, MVideoFullLight, MVideoUUID } from '@server/types/models/index.js'
  5. import { CreateJobArgument, CreateJobOptions, JobQueue } from './job-queue/job-queue.js'
  6. import { moveFilesIfPrivacyChanged } from './video-privacy.js'
  7. export async function buildMoveJob (options: {
  8. video: MVideoUUID
  9. previousVideoState: VideoStateType
  10. type: 'move-to-object-storage' | 'move-to-file-system'
  11. isNewVideo?: boolean // Default true
  12. }) {
  13. const { video, previousVideoState, isNewVideo = true, type } = options
  14. await VideoJobInfoModel.increaseOrCreate(video.uuid, 'pendingMove')
  15. return {
  16. type,
  17. payload: {
  18. videoUUID: video.uuid,
  19. isNewVideo,
  20. previousVideoState
  21. }
  22. }
  23. }
  24. export function buildStoryboardJobIfNeeded (options: {
  25. video: MVideo
  26. federate: boolean
  27. }) {
  28. const { video, federate } = options
  29. if (CONFIG.STORYBOARDS.ENABLED) {
  30. return {
  31. type: 'generate-video-storyboard' as 'generate-video-storyboard',
  32. payload: {
  33. videoUUID: video.uuid,
  34. federate
  35. }
  36. }
  37. }
  38. if (federate === true) {
  39. return {
  40. type: 'federate-video' as 'federate-video',
  41. payload: {
  42. videoUUID: video.uuid,
  43. isNewVideoForFederation: false
  44. }
  45. }
  46. }
  47. return undefined
  48. }
  49. export async function addVideoJobsAfterCreation (options: {
  50. video: MVideo
  51. videoFile: MVideoFile
  52. }) {
  53. const { video, videoFile } = options
  54. const jobs: (CreateJobArgument & CreateJobOptions)[] = [
  55. {
  56. type: 'manage-video-torrent' as 'manage-video-torrent',
  57. payload: {
  58. videoId: video.id,
  59. videoFileId: videoFile.id,
  60. action: 'create'
  61. }
  62. },
  63. buildStoryboardJobIfNeeded({ video, federate: false }),
  64. {
  65. type: 'notify',
  66. payload: {
  67. action: 'new-video',
  68. videoUUID: video.uuid
  69. }
  70. },
  71. {
  72. type: 'federate-video' as 'federate-video',
  73. payload: {
  74. videoUUID: video.uuid,
  75. isNewVideoForFederation: true
  76. }
  77. }
  78. ]
  79. if (video.state === VideoState.TO_MOVE_TO_EXTERNAL_STORAGE) {
  80. jobs.push(await buildMoveJob({ video, previousVideoState: undefined, type: 'move-to-object-storage' }))
  81. }
  82. if (video.state === VideoState.TO_TRANSCODE) {
  83. jobs.push({
  84. type: 'transcoding-job-builder' as 'transcoding-job-builder',
  85. payload: {
  86. videoUUID: video.uuid,
  87. optimizeJob: {
  88. isNewVideo: true
  89. }
  90. }
  91. })
  92. }
  93. return JobQueue.Instance.createSequentialJobFlow(...jobs)
  94. }
  95. export async function addVideoJobsAfterUpdate (options: {
  96. video: MVideoFullLight
  97. isNewVideoForFederation: boolean
  98. nameChanged: boolean
  99. oldPrivacy: VideoPrivacyType
  100. }) {
  101. const { video, nameChanged, oldPrivacy, isNewVideoForFederation } = options
  102. const jobs: CreateJobArgument[] = []
  103. const filePathChanged = await moveFilesIfPrivacyChanged(video, oldPrivacy)
  104. if (!video.isLive && (nameChanged || filePathChanged)) {
  105. for (const file of (video.VideoFiles || [])) {
  106. const payload: ManageVideoTorrentPayload = { action: 'update-metadata', videoId: video.id, videoFileId: file.id }
  107. jobs.push({ type: 'manage-video-torrent', payload })
  108. }
  109. const hls = video.getHLSPlaylist()
  110. for (const file of (hls?.VideoFiles || [])) {
  111. const payload: ManageVideoTorrentPayload = { action: 'update-metadata', streamingPlaylistId: hls.id, videoFileId: file.id }
  112. jobs.push({ type: 'manage-video-torrent', payload })
  113. }
  114. }
  115. jobs.push({
  116. type: 'federate-video',
  117. payload: {
  118. videoUUID: video.uuid,
  119. isNewVideoForFederation
  120. }
  121. })
  122. const wasConfidentialVideo = new Set<VideoPrivacyType>([
  123. VideoPrivacy.PRIVATE,
  124. VideoPrivacy.UNLISTED,
  125. VideoPrivacy.INTERNAL
  126. ]).has(oldPrivacy)
  127. if (wasConfidentialVideo) {
  128. jobs.push({
  129. type: 'notify',
  130. payload: {
  131. action: 'new-video',
  132. videoUUID: video.uuid
  133. }
  134. })
  135. }
  136. return JobQueue.Instance.createSequentialJobFlow(...jobs)
  137. }