From 2451916e45420fedf556913ce121f3964c4b57d6 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 17 Feb 2021 09:36:09 +0100 Subject: [PATCH] Add video files migration --- server/initializers/constants.ts | 2 +- .../migrations/0585-video-file-names.ts | 55 +++++++++++++++++++ .../job-queue/handlers/video-file-import.ts | 37 ++++++------- server/lib/video-transcoding.ts | 1 + .../tests/cli/create-import-video-file-job.ts | 2 +- 5 files changed, 74 insertions(+), 23 deletions(-) create mode 100644 server/initializers/migrations/0585-video-file-names.ts diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 6b0984186..c4c7ffdac 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts @@ -24,7 +24,7 @@ import { CONFIG, registerConfigChangedHandler } from './config' // --------------------------------------------------------------------------- -const LAST_MIGRATION_VERSION = 580 +const LAST_MIGRATION_VERSION = 585 // --------------------------------------------------------------------------- diff --git a/server/initializers/migrations/0585-video-file-names.ts b/server/initializers/migrations/0585-video-file-names.ts new file mode 100644 index 000000000..dd5fec3a1 --- /dev/null +++ b/server/initializers/migrations/0585-video-file-names.ts @@ -0,0 +1,55 @@ +import * as Sequelize from 'sequelize' + +async function up (utils: { + transaction: Sequelize.Transaction + queryInterface: Sequelize.QueryInterface + sequelize: Sequelize.Sequelize + db: any +}): Promise { + for (const column of [ 'filename', 'fileUrl', 'torrentFilename', 'torrentUrl' ]) { + const data = { + type: Sequelize.STRING, + allowNull: true, + defaultValue: null + } + + await utils.queryInterface.addColumn('videoFile', column, data) + } + + // Generate filenames for webtorrent files + { + const webtorrentQuery = `SELECT "videoFile".id, "video".uuid, "videoFile".resolution, "videoFile".extname ` + + `FROM video INNER JOIN "videoFile" ON "videoFile"."videoId" = video.id` + + const query = `UPDATE "videoFile" ` + + `SET filename = t.uuid || '-' || t.resolution || t.extname, ` + + `"torrentFilename" = t.uuid || '-' || t.resolution || '.torrent' ` + + `FROM (${webtorrentQuery}) AS t WHERE t.id = "videoFile"."id"` + + await utils.sequelize.query(query) + } + + // Generate filenames for HLS files + { + const hlsQuery = `SELECT "videoFile".id, "video".uuid, "videoFile".resolution, "videoFile".extname ` + + `FROM video ` + + `INNER JOIN "videoStreamingPlaylist" ON "videoStreamingPlaylist"."videoId" = video.id ` + + `INNER JOIN "videoFile" ON "videoFile"."videoStreamingPlaylistId" = "videoStreamingPlaylist".id` + + const query = `UPDATE "videoFile" ` + + `SET filename = t.uuid || '-' || t.resolution || '-fragmented' || t.extname, ` + + `"torrentFilename" = t.uuid || '-' || t.resolution || '-hls.torrent' ` + + `FROM (${hlsQuery}) AS t WHERE t.id = "videoFile"."id"` + + await utils.sequelize.query(query) + } +} + +function down (options) { + throw new Error('Not implemented.') +} + +export { + up, + down +} diff --git a/server/lib/job-queue/handlers/video-file-import.ts b/server/lib/job-queue/handlers/video-file-import.ts index 86c9b5c29..839916306 100644 --- a/server/lib/job-queue/handlers/video-file-import.ts +++ b/server/lib/job-queue/handlers/video-file-import.ts @@ -4,7 +4,7 @@ import { extname } from 'path' import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths' import { UserModel } from '@server/models/account/user' -import { MVideoFile, MVideoFullLight } from '@server/types/models' +import { MVideoFullLight } from '@server/types/models' import { VideoFileImportPayload } from '@shared/models' import { getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffprobe-utils' import { logger } from '../../../helpers/logger' @@ -56,16 +56,8 @@ async function updateVideoFile (video: MVideoFullLight, inputFilePath: string) { const fps = await getVideoFileFPS(inputFilePath) const fileExt = extname(inputFilePath) - let updatedVideoFile = new VideoFileModel({ - resolution: videoFileResolution, - extname: fileExt, - filename: generateVideoFilename(video, false, videoFileResolution, fileExt), - size, - fps, - videoId: video.id - }) as MVideoFile - const currentVideoFile = video.VideoFiles.find(videoFile => videoFile.resolution === updatedVideoFile.resolution) + const currentVideoFile = video.VideoFiles.find(videoFile => videoFile.resolution === videoFileResolution) if (currentVideoFile) { // Remove old file and old torrent @@ -74,20 +66,23 @@ async function updateVideoFile (video: MVideoFullLight, inputFilePath: string) { // Remove the old video file from the array video.VideoFiles = video.VideoFiles.filter(f => f !== currentVideoFile) - // Update the database - currentVideoFile.extname = updatedVideoFile.extname - currentVideoFile.size = updatedVideoFile.size - currentVideoFile.fps = updatedVideoFile.fps - - updatedVideoFile = currentVideoFile + await currentVideoFile.destroy() } - const outputPath = getVideoFilePath(video, updatedVideoFile) + const newVideoFile = new VideoFileModel({ + resolution: videoFileResolution, + extname: fileExt, + filename: generateVideoFilename(video, false, videoFileResolution, fileExt), + size, + fps, + videoId: video.id + }) + + const outputPath = getVideoFilePath(video, newVideoFile) await copy(inputFilePath, outputPath) - await createTorrentAndSetInfoHash(video, video, updatedVideoFile) + video.VideoFiles.push(newVideoFile) + await createTorrentAndSetInfoHash(video, video, newVideoFile) - await updatedVideoFile.save() - - video.VideoFiles.push(updatedVideoFile) + await newVideoFile.save() } diff --git a/server/lib/video-transcoding.ts b/server/lib/video-transcoding.ts index b366e2e44..e3cd18e25 100644 --- a/server/lib/video-transcoding.ts +++ b/server/lib/video-transcoding.ts @@ -166,6 +166,7 @@ async function mergeAudioVideofile (video: MVideoFullLight, resolution: VideoRes // Important to do this before getVideoFilename() to take in account the new file extension inputVideoFile.extname = newExtname + inputVideoFile.filename = generateVideoFilename(video, false, inputVideoFile.resolution, newExtname) const videoOutputPath = getVideoFilePath(video, inputVideoFile) // ffmpeg generated a new video file, so update the video duration diff --git a/server/tests/cli/create-import-video-file-job.ts b/server/tests/cli/create-import-video-file-job.ts index 7eaf2c19e..49758ff56 100644 --- a/server/tests/cli/create-import-video-file-job.ts +++ b/server/tests/cli/create-import-video-file-job.ts @@ -22,9 +22,9 @@ const expect = chai.expect function assertVideoProperties (video: VideoFile, resolution: number, extname: string, size?: number) { expect(video).to.have.nested.property('resolution.id', resolution) - expect(video).to.have.property('magnetUri').that.includes(`.${extname}`) expect(video).to.have.property('torrentUrl').that.includes(`-${resolution}.torrent`) expect(video).to.have.property('fileUrl').that.includes(`.${extname}`) + expect(video).to.have.property('magnetUri').that.includes(`.${extname}`) expect(video).to.have.property('size').that.is.above(0) if (size) expect(video.size).to.equal(size)