aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-06-06 11:12:50 +0200
committerChocobozzz <me@florianbigard.com>2023-06-29 10:18:21 +0200
commit1c9dc98c273075d92161c0572fea5c4103926467 (patch)
tree3bd5d3fa371c7feb2d7af0f0854d0241c59a241d
parentd299afeb2ca94eb7e44e056607cf7f840dd6a60b (diff)
downloadPeerTube-1c9dc98c273075d92161c0572fea5c4103926467.tar.gz
PeerTube-1c9dc98c273075d92161c0572fea5c4103926467.tar.zst
PeerTube-1c9dc98c273075d92161c0572fea5c4103926467.zip
Lock video files when generating storyboard
-rw-r--r--server/lib/job-queue/handlers/generate-storyboard.ts118
1 files changed, 62 insertions, 56 deletions
diff --git a/server/lib/job-queue/handlers/generate-storyboard.ts b/server/lib/job-queue/handlers/generate-storyboard.ts
index 09b746a3e..ec07c568c 100644
--- a/server/lib/job-queue/handlers/generate-storyboard.ts
+++ b/server/lib/job-queue/handlers/generate-storyboard.ts
@@ -21,75 +21,81 @@ async function processGenerateStoryboard (job: Job): Promise<void> {
21 21
22 logger.info('Processing generate storyboard of %s in job %s.', payload.videoUUID, job.id, lTags) 22 logger.info('Processing generate storyboard of %s in job %s.', payload.videoUUID, job.id, lTags)
23 23
24 const video = await VideoModel.loadFull(payload.videoUUID) 24 const inputFileMutexReleaser = await VideoPathManager.Instance.lockFiles(payload.videoUUID)
25 if (!video) {
26 logger.info('Video %s does not exist anymore, skipping storyboard generation.', payload.videoUUID, lTags)
27 return
28 }
29
30 const inputFile = video.getMaxQualityFile()
31
32 await VideoPathManager.Instance.makeAvailableVideoFile(inputFile, async videoPath => {
33 const isAudio = await isAudioFile(videoPath)
34 25
35 if (isAudio) { 26 try {
36 logger.info('Do not generate a storyboard of %s since the video does not have a video stream', payload.videoUUID, lTags) 27 const video = await VideoModel.loadFull(payload.videoUUID)
28 if (!video) {
29 logger.info('Video %s does not exist anymore, skipping storyboard generation.', payload.videoUUID, lTags)
37 return 30 return
38 } 31 }
39 32
40 const ffmpeg = new FFmpegImage(getFFmpegCommandWrapperOptions('thumbnail')) 33 const inputFile = video.getMaxQualityFile()
41 34
42 const filename = generateImageFilename() 35 await VideoPathManager.Instance.makeAvailableVideoFile(inputFile, async videoPath => {
43 const destination = join(CONFIG.STORAGE.STORYBOARDS_DIR, filename) 36 const isAudio = await isAudioFile(videoPath)
44 37
45 const totalSprites = buildTotalSprites(video) 38 if (isAudio) {
46 if (totalSprites === 0) { 39 logger.info('Do not generate a storyboard of %s since the video does not have a video stream', payload.videoUUID, lTags)
47 logger.info('Do not generate a storyboard of %s because the video is not long enough', payload.videoUUID, lTags) 40 return
48 return 41 }
49 }
50 42
51 const spriteDuration = Math.round(video.duration / totalSprites) 43 const ffmpeg = new FFmpegImage(getFFmpegCommandWrapperOptions('thumbnail'))
52 44
53 const spritesCount = findGridSize({ 45 const filename = generateImageFilename()
54 toFind: totalSprites, 46 const destination = join(CONFIG.STORAGE.STORYBOARDS_DIR, filename)
55 maxEdgeCount: STORYBOARD.SPRITES_MAX_EDGE_COUNT
56 })
57 47
58 logger.debug( 48 const totalSprites = buildTotalSprites(video)
59 'Generating storyboard from video of %s to %s', video.uuid, destination, 49 if (totalSprites === 0) {
60 { ...lTags, spritesCount, spriteDuration, videoDuration: video.duration } 50 logger.info('Do not generate a storyboard of %s because the video is not long enough', payload.videoUUID, lTags)
61 ) 51 return
62
63 await ffmpeg.generateStoryboardFromVideo({
64 destination,
65 path: videoPath,
66 sprites: {
67 size: STORYBOARD.SPRITE_SIZE,
68 count: spritesCount,
69 duration: spriteDuration
70 } 52 }
71 })
72
73 const imageSize = await getImageSize(destination)
74 53
75 const existing = await StoryboardModel.loadByVideo(video.id) 54 const spriteDuration = Math.round(video.duration / totalSprites)
76 if (existing) await existing.destroy() 55
77 56 const spritesCount = findGridSize({
78 await StoryboardModel.create({ 57 toFind: totalSprites,
79 filename, 58 maxEdgeCount: STORYBOARD.SPRITES_MAX_EDGE_COUNT
80 totalHeight: imageSize.height, 59 })
81 totalWidth: imageSize.width, 60
82 spriteHeight: STORYBOARD.SPRITE_SIZE.height, 61 logger.debug(
83 spriteWidth: STORYBOARD.SPRITE_SIZE.width, 62 'Generating storyboard from video of %s to %s', video.uuid, destination,
84 spriteDuration, 63 { ...lTags, spritesCount, spriteDuration, videoDuration: video.duration }
85 videoId: video.id 64 )
65
66 await ffmpeg.generateStoryboardFromVideo({
67 destination,
68 path: videoPath,
69 sprites: {
70 size: STORYBOARD.SPRITE_SIZE,
71 count: spritesCount,
72 duration: spriteDuration
73 }
74 })
75
76 const imageSize = await getImageSize(destination)
77
78 const existing = await StoryboardModel.loadByVideo(video.id)
79 if (existing) await existing.destroy()
80
81 await StoryboardModel.create({
82 filename,
83 totalHeight: imageSize.height,
84 totalWidth: imageSize.width,
85 spriteHeight: STORYBOARD.SPRITE_SIZE.height,
86 spriteWidth: STORYBOARD.SPRITE_SIZE.width,
87 spriteDuration,
88 videoId: video.id
89 })
90
91 logger.info('Storyboard generation %s ended for video %s.', destination, video.uuid, lTags)
86 }) 92 })
87 93
88 logger.info('Storyboard generation %s ended for video %s.', destination, video.uuid, lTags) 94 if (payload.federate) {
89 }) 95 await federateVideoIfNeeded(video, false)
90 96 }
91 if (payload.federate) { 97 } finally {
92 await federateVideoIfNeeded(video, false) 98 inputFileMutexReleaser()
93 } 99 }
94} 100}
95 101