ニジカ投稿局 https://tv.nizika.tv
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

video-jobs.ts 4.4 KiB

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