X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Flib%2Fjob-queue%2Fhandlers%2Fvideo-import.ts;h=93a3e9d901cc0f2819738f4b75728a33f60b3d03;hb=00aab0666c6f772548c160fdfa871a8843b88f37;hp=51a0b5faf5a2bc347a515addbec764491839963a;hpb=2a8c5d0af13f3ccb9a505e1fbc9d324b9d33ba1f;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/lib/job-queue/handlers/video-import.ts b/server/lib/job-queue/handlers/video-import.ts index 51a0b5faf..93a3e9d90 100644 --- a/server/lib/job-queue/handlers/video-import.ts +++ b/server/lib/job-queue/handlers/video-import.ts @@ -6,15 +6,22 @@ import { VideoImportState } from '../../../../shared/models/videos' import { getDurationFromVideoFile, getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffmpeg-utils' import { extname, join } from 'path' import { VideoFileModel } from '../../../models/video/video-file' -import { CONFIG, PREVIEWS_SIZE, sequelizeTypescript, THUMBNAILS_SIZE, VIDEO_IMPORT_TIMEOUT } from '../../../initializers' -import { downloadImage } from '../../../helpers/requests' +import { VIDEO_IMPORT_TIMEOUT } from '../../../initializers/constants' import { VideoState } from '../../../../shared' import { JobQueue } from '../index' import { federateVideoIfNeeded } from '../../activitypub' import { VideoModel } from '../../../models/video/video' import { downloadWebTorrentVideo } from '../../../helpers/webtorrent' import { getSecureTorrentName } from '../../../helpers/utils' -import { remove, rename, stat } from 'fs-extra' +import { move, remove, stat } from 'fs-extra' +import { Notifier } from '../../notifier' +import { CONFIG } from '../../../initializers/config' +import { sequelizeTypescript } from '../../../initializers/database' +import { createVideoMiniatureFromUrl, generateVideoMiniature } from '../../thumbnail' +import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type' +import { MThumbnail } from '../../../typings/models/video/thumbnail' +import { MVideoImportDefault, MVideoImportDefaultFiles, MVideoImportVideo } from '@server/typings/models/video/video-import' +import { MVideoBlacklistVideo, MVideoBlacklist } from '@server/typings/models' type VideoImportYoutubeDLPayload = { type: 'youtube-dl' @@ -105,7 +112,7 @@ type ProcessFileOptions = { generateThumbnail: boolean generatePreview: boolean } -async function processFile (downloader: () => Promise, videoImport: VideoImportModel, options: ProcessFileOptions) { +async function processFile (downloader: () => Promise, videoImport: MVideoImportDefault, options: ProcessFileOptions) { let tempVideoPath: string let videoDestFile: string let videoFile: VideoFileModel @@ -134,76 +141,87 @@ async function processFile (downloader: () => Promise, videoImport: Vide videoId: videoImport.videoId } videoFile = new VideoFileModel(videoFileData) + + const videoWithFiles = Object.assign(videoImport.Video, { VideoFiles: [ videoFile ] }) // To clean files if the import fails - videoImport.Video.VideoFiles = [ videoFile ] + const videoImportWithFiles: MVideoImportDefaultFiles = Object.assign(videoImport, { Video: videoWithFiles }) // Move file - videoDestFile = join(CONFIG.STORAGE.VIDEOS_DIR, videoImport.Video.getVideoFilename(videoFile)) - await rename(tempVideoPath, videoDestFile) + videoDestFile = join(CONFIG.STORAGE.VIDEOS_DIR, videoImportWithFiles.Video.getVideoFilename(videoFile)) + await move(tempVideoPath, videoDestFile) tempVideoPath = null // This path is not used anymore // Process thumbnail - if (options.downloadThumbnail) { - if (options.thumbnailUrl) { - await downloadImage(options.thumbnailUrl, CONFIG.STORAGE.THUMBNAILS_DIR, videoImport.Video.getThumbnailName(), THUMBNAILS_SIZE) - } else { - await videoImport.Video.createThumbnail(videoFile) - } - } else if (options.generateThumbnail) { - await videoImport.Video.createThumbnail(videoFile) + let thumbnailModel: MThumbnail + if (options.downloadThumbnail && options.thumbnailUrl) { + thumbnailModel = await createVideoMiniatureFromUrl(options.thumbnailUrl, videoImportWithFiles.Video, ThumbnailType.MINIATURE) + } else if (options.generateThumbnail || options.downloadThumbnail) { + thumbnailModel = await generateVideoMiniature(videoImportWithFiles.Video, videoFile, ThumbnailType.MINIATURE) } // Process preview - if (options.downloadPreview) { - if (options.thumbnailUrl) { - await downloadImage(options.thumbnailUrl, CONFIG.STORAGE.PREVIEWS_DIR, videoImport.Video.getPreviewName(), PREVIEWS_SIZE) - } else { - await videoImport.Video.createPreview(videoFile) - } - } else if (options.generatePreview) { - await videoImport.Video.createPreview(videoFile) + let previewModel: MThumbnail + if (options.downloadPreview && options.thumbnailUrl) { + previewModel = await createVideoMiniatureFromUrl(options.thumbnailUrl, videoImportWithFiles.Video, ThumbnailType.PREVIEW) + } else if (options.generatePreview || options.downloadPreview) { + previewModel = await generateVideoMiniature(videoImportWithFiles.Video, videoFile, ThumbnailType.PREVIEW) } // Create torrent - await videoImport.Video.createTorrentAndSetInfoHash(videoFile) + await videoImportWithFiles.Video.createTorrentAndSetInfoHash(videoFile) + + const { videoImportUpdated, video } = await sequelizeTypescript.transaction(async t => { + const videoImportToUpdate = videoImportWithFiles as MVideoImportVideo - const videoImportUpdated: VideoImportModel = await sequelizeTypescript.transaction(async t => { // Refresh video - const video = await VideoModel.load(videoImport.videoId, t) - if (!video) throw new Error('Video linked to import ' + videoImport.videoId + ' does not exist anymore.') - videoImport.Video = video + const video = await VideoModel.load(videoImportToUpdate.videoId, t) + if (!video) throw new Error('Video linked to import ' + videoImportToUpdate.videoId + ' does not exist anymore.') const videoFileCreated = await videoFile.save({ transaction: t }) - video.VideoFiles = [ videoFileCreated ] + videoImportToUpdate.Video = Object.assign(video, { VideoFiles: [ videoFileCreated ] }) // Update video DB object video.duration = duration video.state = CONFIG.TRANSCODING.ENABLED ? VideoState.TO_TRANSCODE : VideoState.PUBLISHED - const videoUpdated = await video.save({ transaction: t }) + await video.save({ transaction: t }) + + if (thumbnailModel) await video.addAndSaveThumbnail(thumbnailModel, t) + if (previewModel) await video.addAndSaveThumbnail(previewModel, t) // Now we can federate the video (reload from database, we need more attributes) const videoForFederation = await VideoModel.loadAndPopulateAccountAndServerAndTags(video.uuid, t) await federateVideoIfNeeded(videoForFederation, true, t) // Update video import object - videoImport.state = VideoImportState.SUCCESS - const videoImportUpdated = await videoImport.save({ transaction: t }) + videoImportToUpdate.state = VideoImportState.SUCCESS + const videoImportUpdated = await videoImportToUpdate.save({ transaction: t }) as MVideoImportVideo + videoImportUpdated.Video = video logger.info('Video %s imported.', video.uuid) - videoImportUpdated.Video = videoUpdated - return videoImportUpdated + return { videoImportUpdated, video: videoForFederation } }) + Notifier.Instance.notifyOnFinishedVideoImport(videoImportUpdated, true) + + if (video.isBlacklisted()) { + const videoBlacklist = Object.assign(video.VideoBlacklist, { Video: video }) + + Notifier.Instance.notifyOnVideoAutoBlacklist(videoBlacklist) + } else { + Notifier.Instance.notifyOnNewVideoIfNeeded(video) + } + // Create transcoding jobs? - if (videoImportUpdated.Video.state === VideoState.TO_TRANSCODE) { + if (video.state === VideoState.TO_TRANSCODE) { // Put uuid because we don't have id auto incremented for now const dataInput = { + type: 'optimize' as 'optimize', videoUUID: videoImportUpdated.Video.uuid, isNewVideo: true } - await JobQueue.Instance.createJob({ type: 'video-file', payload: dataInput }) + await JobQueue.Instance.createJob({ type: 'video-transcoding', payload: dataInput }) } } catch (err) { @@ -217,6 +235,8 @@ async function processFile (downloader: () => Promise, videoImport: Vide videoImport.state = VideoImportState.FAILED await videoImport.save() + Notifier.Instance.notifyOnFinishedVideoImport(videoImport, false) + throw err } }