diff options
author | Chocobozzz <me@florianbigard.com> | 2023-06-06 11:12:50 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2023-06-29 10:18:21 +0200 |
commit | 1c9dc98c273075d92161c0572fea5c4103926467 (patch) | |
tree | 3bd5d3fa371c7feb2d7af0f0854d0241c59a241d | |
parent | d299afeb2ca94eb7e44e056607cf7f840dd6a60b (diff) | |
download | PeerTube-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.ts | 118 |
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 | ||