diff options
author | Chocobozzz <me@florianbigard.com> | 2021-04-08 10:35:49 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-04-08 13:38:04 +0200 |
commit | a0eeb45f14bab539f505861cad8f5d42d9ba30cb (patch) | |
tree | 773eb5aa575c8ab870b9c84f686e6062aa58d9fd | |
parent | ca873292899c9a822a236556993916d98da14913 (diff) | |
download | PeerTube-a0eeb45f14bab539f505861cad8f5d42d9ba30cb.tar.gz PeerTube-a0eeb45f14bab539f505861cad8f5d42d9ba30cb.tar.zst PeerTube-a0eeb45f14bab539f505861cad8f5d42d9ba30cb.zip |
Update data in DB when regenerate thumbnails
-rw-r--r-- | scripts/regenerate-thumbnails.ts | 25 | ||||
-rw-r--r-- | server/lib/activitypub/videos.ts | 3 | ||||
-rw-r--r-- | server/lib/thumbnail.ts | 5 | ||||
-rw-r--r-- | server/models/account/actor-image.ts | 5 | ||||
-rw-r--r-- | server/models/video/video.ts | 9 | ||||
-rw-r--r-- | server/tests/cli/regenerate-thumbnails.ts | 32 |
6 files changed, 52 insertions, 27 deletions
diff --git a/scripts/regenerate-thumbnails.ts b/scripts/regenerate-thumbnails.ts index 04c6e2b74..0213b8a22 100644 --- a/scripts/regenerate-thumbnails.ts +++ b/scripts/regenerate-thumbnails.ts | |||
@@ -3,12 +3,13 @@ registerTSPaths() | |||
3 | 3 | ||
4 | import * as Bluebird from 'bluebird' | 4 | import * as Bluebird from 'bluebird' |
5 | import * as program from 'commander' | 5 | import * as program from 'commander' |
6 | import { pathExists } from 'fs-extra' | 6 | import { pathExists, remove } from 'fs-extra' |
7 | import { processImage } from '@server/helpers/image-utils' | 7 | import { processImage } from '@server/helpers/image-utils' |
8 | import { THUMBNAILS_SIZE } from '@server/initializers/constants' | 8 | import { THUMBNAILS_SIZE } from '@server/initializers/constants' |
9 | import { VideoModel } from '@server/models/video/video' | 9 | import { VideoModel } from '@server/models/video/video' |
10 | import { MVideo } from '@server/types/models' | 10 | import { MVideo } from '@server/types/models' |
11 | import { initDatabaseModels } from '@server/initializers/database' | 11 | import { initDatabaseModels } from '@server/initializers/database' |
12 | import { ActorImageModel } from '@server/models/account/actor-image' | ||
12 | 13 | ||
13 | program | 14 | program |
14 | .description('Regenerate local thumbnails using preview files') | 15 | .description('Regenerate local thumbnails using preview files') |
@@ -37,13 +38,8 @@ async function processVideo (videoArg: MVideo) { | |||
37 | const thumbnail = video.getMiniature() | 38 | const thumbnail = video.getMiniature() |
38 | const preview = video.getPreview() | 39 | const preview = video.getPreview() |
39 | 40 | ||
40 | const thumbnailPath = thumbnail.getPath() | ||
41 | const previewPath = preview.getPath() | 41 | const previewPath = preview.getPath() |
42 | 42 | ||
43 | if (!await pathExists(thumbnailPath)) { | ||
44 | throw new Error(`Thumbnail ${thumbnailPath} does not exist on disk`) | ||
45 | } | ||
46 | |||
47 | if (!await pathExists(previewPath)) { | 43 | if (!await pathExists(previewPath)) { |
48 | throw new Error(`Preview ${previewPath} does not exist on disk`) | 44 | throw new Error(`Preview ${previewPath} does not exist on disk`) |
49 | } | 45 | } |
@@ -52,5 +48,22 @@ async function processVideo (videoArg: MVideo) { | |||
52 | width: THUMBNAILS_SIZE.width, | 48 | width: THUMBNAILS_SIZE.width, |
53 | height: THUMBNAILS_SIZE.height | 49 | height: THUMBNAILS_SIZE.height |
54 | } | 50 | } |
51 | |||
52 | const oldPath = thumbnail.getPath() | ||
53 | |||
54 | // Update thumbnail | ||
55 | thumbnail.filename = ActorImageModel.generateFilename() | ||
56 | thumbnail.width = size.width | ||
57 | thumbnail.height = size.height | ||
58 | |||
59 | const thumbnailPath = thumbnail.getPath() | ||
55 | await processImage(previewPath, thumbnailPath, size, true) | 60 | await processImage(previewPath, thumbnailPath, size, true) |
61 | |||
62 | // Save new attributes | ||
63 | await thumbnail.save() | ||
64 | |||
65 | // Remove old thumbnail | ||
66 | await remove(oldPath) | ||
67 | |||
68 | // Don't federate, remote instances will refresh the thumbnails after a while | ||
56 | } | 69 | } |
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts index d484edd36..492b97b9e 100644 --- a/server/lib/activitypub/videos.ts +++ b/server/lib/activitypub/videos.ts | |||
@@ -3,6 +3,7 @@ import { maxBy, minBy } from 'lodash' | |||
3 | import * as magnetUtil from 'magnet-uri' | 3 | import * as magnetUtil from 'magnet-uri' |
4 | import { basename, join } from 'path' | 4 | import { basename, join } from 'path' |
5 | import { Transaction } from 'sequelize/types' | 5 | import { Transaction } from 'sequelize/types' |
6 | import { ActorImageModel } from '@server/models/account/actor-image' | ||
6 | import { TrackerModel } from '@server/models/server/tracker' | 7 | import { TrackerModel } from '@server/models/server/tracker' |
7 | import { VideoLiveModel } from '@server/models/video/video-live' | 8 | import { VideoLiveModel } from '@server/models/video/video-live' |
8 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | 9 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' |
@@ -899,7 +900,7 @@ function getPreviewFromIcons (videoObject: VideoObject) { | |||
899 | function getPreviewUrl (previewIcon: ActivityIconObject, video: MVideoWithHost) { | 900 | function getPreviewUrl (previewIcon: ActivityIconObject, video: MVideoWithHost) { |
900 | return previewIcon | 901 | return previewIcon |
901 | ? previewIcon.url | 902 | ? previewIcon.url |
902 | : buildRemoteVideoBaseUrl(video, join(LAZY_STATIC_PATHS.PREVIEWS, video.generatePreviewName())) | 903 | : buildRemoteVideoBaseUrl(video, join(LAZY_STATIC_PATHS.PREVIEWS, ActorImageModel.generateFilename())) |
903 | } | 904 | } |
904 | 905 | ||
905 | function getTrackerUrls (object: VideoObject, video: MVideoWithHost) { | 906 | function getTrackerUrls (object: VideoObject, video: MVideoWithHost) { |
diff --git a/server/lib/thumbnail.ts b/server/lib/thumbnail.ts index 106f5fdaa..e1176ac08 100644 --- a/server/lib/thumbnail.ts +++ b/server/lib/thumbnail.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { join } from 'path' | 1 | import { join } from 'path' |
2 | import { ActorImageModel } from '@server/models/account/actor-image' | ||
2 | import { ThumbnailType } from '../../shared/models/videos/thumbnail.type' | 3 | import { ThumbnailType } from '../../shared/models/videos/thumbnail.type' |
3 | import { generateImageFromVideoFile } from '../helpers/ffmpeg-utils' | 4 | import { generateImageFromVideoFile } from '../helpers/ffmpeg-utils' |
4 | import { processImage } from '../helpers/image-utils' | 5 | import { processImage } from '../helpers/image-utils' |
@@ -200,7 +201,7 @@ function buildMetadataFromVideo (video: MVideoThumbnail, type: ThumbnailType, si | |||
200 | : undefined | 201 | : undefined |
201 | 202 | ||
202 | if (type === ThumbnailType.MINIATURE) { | 203 | if (type === ThumbnailType.MINIATURE) { |
203 | const filename = video.generateThumbnailName() | 204 | const filename = ActorImageModel.generateFilename() |
204 | const basePath = CONFIG.STORAGE.THUMBNAILS_DIR | 205 | const basePath = CONFIG.STORAGE.THUMBNAILS_DIR |
205 | 206 | ||
206 | return { | 207 | return { |
@@ -214,7 +215,7 @@ function buildMetadataFromVideo (video: MVideoThumbnail, type: ThumbnailType, si | |||
214 | } | 215 | } |
215 | 216 | ||
216 | if (type === ThumbnailType.PREVIEW) { | 217 | if (type === ThumbnailType.PREVIEW) { |
217 | const filename = video.generatePreviewName() | 218 | const filename = ActorImageModel.generateFilename() |
218 | const basePath = CONFIG.STORAGE.PREVIEWS_DIR | 219 | const basePath = CONFIG.STORAGE.PREVIEWS_DIR |
219 | 220 | ||
220 | return { | 221 | return { |
diff --git a/server/models/account/actor-image.ts b/server/models/account/actor-image.ts index b779e3cf6..f7438991a 100644 --- a/server/models/account/actor-image.ts +++ b/server/models/account/actor-image.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { remove } from 'fs-extra' | 1 | import { remove } from 'fs-extra' |
2 | import { join } from 'path' | 2 | import { join } from 'path' |
3 | import { AfterDestroy, AllowNull, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' | 3 | import { AfterDestroy, AllowNull, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' |
4 | import { v4 as uuidv4 } from 'uuid' | ||
4 | import { MActorImageFormattable } from '@server/types/models' | 5 | import { MActorImageFormattable } from '@server/types/models' |
5 | import { ActorImageType } from '@shared/models' | 6 | import { ActorImageType } from '@shared/models' |
6 | import { ActorImage } from '../../../shared/models/actors/actor-image.model' | 7 | import { ActorImage } from '../../../shared/models/actors/actor-image.model' |
@@ -53,6 +54,10 @@ export class ActorImageModel extends Model { | |||
53 | .catch(err => logger.error('Cannot remove actor image file %s.', instance.filename, err)) | 54 | .catch(err => logger.error('Cannot remove actor image file %s.', instance.filename, err)) |
54 | } | 55 | } |
55 | 56 | ||
57 | static generateFilename () { | ||
58 | return uuidv4() + '.jpg' | ||
59 | } | ||
60 | |||
56 | static loadByName (filename: string) { | 61 | static loadByName (filename: string) { |
57 | const query = { | 62 | const query = { |
58 | where: { | 63 | where: { |
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 086269921..b10c6e38e 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -24,7 +24,6 @@ import { | |||
24 | Table, | 24 | Table, |
25 | UpdatedAt | 25 | UpdatedAt |
26 | } from 'sequelize-typescript' | 26 | } from 'sequelize-typescript' |
27 | import { v4 as uuidv4 } from 'uuid' | ||
28 | import { buildNSFWFilter } from '@server/helpers/express-utils' | 27 | import { buildNSFWFilter } from '@server/helpers/express-utils' |
29 | import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video' | 28 | import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video' |
30 | import { LiveManager } from '@server/lib/live-manager' | 29 | import { LiveManager } from '@server/lib/live-manager' |
@@ -1871,20 +1870,12 @@ export class VideoModel extends Model { | |||
1871 | this.Thumbnails.push(savedThumbnail) | 1870 | this.Thumbnails.push(savedThumbnail) |
1872 | } | 1871 | } |
1873 | 1872 | ||
1874 | generateThumbnailName () { | ||
1875 | return uuidv4() + '.jpg' | ||
1876 | } | ||
1877 | |||
1878 | getMiniature () { | 1873 | getMiniature () { |
1879 | if (Array.isArray(this.Thumbnails) === false) return undefined | 1874 | if (Array.isArray(this.Thumbnails) === false) return undefined |
1880 | 1875 | ||
1881 | return this.Thumbnails.find(t => t.type === ThumbnailType.MINIATURE) | 1876 | return this.Thumbnails.find(t => t.type === ThumbnailType.MINIATURE) |
1882 | } | 1877 | } |
1883 | 1878 | ||
1884 | generatePreviewName () { | ||
1885 | return uuidv4() + '.jpg' | ||
1886 | } | ||
1887 | |||
1888 | hasPreview () { | 1879 | hasPreview () { |
1889 | return !!this.getPreview() | 1880 | return !!this.getPreview() |
1890 | } | 1881 | } |
diff --git a/server/tests/cli/regenerate-thumbnails.ts b/server/tests/cli/regenerate-thumbnails.ts index a9c8642a5..8acb9f263 100644 --- a/server/tests/cli/regenerate-thumbnails.ts +++ b/server/tests/cli/regenerate-thumbnails.ts | |||
@@ -2,7 +2,7 @@ import 'mocha' | |||
2 | import { expect } from 'chai' | 2 | import { expect } from 'chai' |
3 | import { writeFile } from 'fs-extra' | 3 | import { writeFile } from 'fs-extra' |
4 | import { basename, join } from 'path' | 4 | import { basename, join } from 'path' |
5 | import { Video } from '@shared/models' | 5 | import { Video, VideoDetails } from '@shared/models' |
6 | import { | 6 | import { |
7 | buildServerDirectory, | 7 | buildServerDirectory, |
8 | cleanupTests, | 8 | cleanupTests, |
@@ -19,6 +19,17 @@ import { | |||
19 | } from '../../../shared/extra-utils' | 19 | } from '../../../shared/extra-utils' |
20 | import { HttpStatusCode } from '@shared/core-utils' | 20 | import { HttpStatusCode } from '@shared/core-utils' |
21 | 21 | ||
22 | async function testThumbnail (server: ServerInfo, videoId: number | string) { | ||
23 | const res = await getVideo(server.url, videoId) | ||
24 | const video: VideoDetails = res.body | ||
25 | |||
26 | const res1 = await makeRawRequest(join(server.url, video.thumbnailPath), HttpStatusCode.OK_200) | ||
27 | expect(res1.body).to.not.have.lengthOf(0) | ||
28 | |||
29 | const res2 = await makeRawRequest(join(server.url, video.thumbnailPath), HttpStatusCode.OK_200) | ||
30 | expect(res2.body).to.not.have.lengthOf(0) | ||
31 | } | ||
32 | |||
22 | describe('Test regenerate thumbnails script', function () { | 33 | describe('Test regenerate thumbnails script', function () { |
23 | let servers: ServerInfo[] | 34 | let servers: ServerInfo[] |
24 | 35 | ||
@@ -84,18 +95,21 @@ describe('Test regenerate thumbnails script', function () { | |||
84 | await execCLI(`${env} npm run regenerate-thumbnails`) | 95 | await execCLI(`${env} npm run regenerate-thumbnails`) |
85 | }) | 96 | }) |
86 | 97 | ||
87 | it('Should have regenerated local thumbnails', async function () { | 98 | it('Should have generated new thumbnail files', async function () { |
88 | { | 99 | await testThumbnail(servers[0], video1.uuid) |
89 | const res1 = await makeRawRequest(join(servers[0].url, video1.thumbnailPath), HttpStatusCode.OK_200) | 100 | await testThumbnail(servers[0], video2.uuid) |
90 | expect(res1.body).to.not.have.lengthOf(0) | ||
91 | 101 | ||
92 | const res2 = await makeRawRequest(join(servers[0].url, video1.previewPath), HttpStatusCode.OK_200) | 102 | const res = await makeRawRequest(join(servers[0].url, remoteVideo.thumbnailPath), HttpStatusCode.OK_200) |
93 | expect(res2.body).to.not.have.lengthOf(0) | 103 | expect(res.body).to.have.lengthOf(0) |
104 | }) | ||
105 | |||
106 | it('Should have deleted old thumbnail files', async function () { | ||
107 | { | ||
108 | await makeRawRequest(join(servers[0].url, video1.thumbnailPath), HttpStatusCode.NOT_FOUND_404) | ||
94 | } | 109 | } |
95 | 110 | ||
96 | { | 111 | { |
97 | const res = await makeRawRequest(join(servers[0].url, video2.thumbnailPath), HttpStatusCode.OK_200) | 112 | await makeRawRequest(join(servers[0].url, video2.thumbnailPath), HttpStatusCode.NOT_FOUND_404) |
98 | expect(res.body).to.not.have.lengthOf(0) | ||
99 | } | 113 | } |
100 | 114 | ||
101 | { | 115 | { |