diff --git a/client/src/app/+accounts/accounts.component.ts b/client/src/app/+accounts/accounts.component.ts index a046a76c2..21e6de348 100644 --- a/client/src/app/+accounts/accounts.component.ts +++ b/client/src/app/+accounts/accounts.component.ts @@ -1,6 +1,6 @@ import { CommonModule } from '@angular/common' import { Component, OnDestroy, OnInit, inject, viewChild } from '@angular/core' -import { ActivatedRoute, Router, RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router' +import { ActivatedRoute, RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router' import { AuthService, MarkdownService, diff --git a/packages/tests/src/api/videos/video-files.ts b/packages/tests/src/api/videos/video-files.ts index b455307a3..2fc179570 100644 --- a/packages/tests/src/api/videos/video-files.ts +++ b/packages/tests/src/api/videos/video-files.ts @@ -30,8 +30,7 @@ describe('Test videos files', function () { await servers[0].config.enableTranscoding({ hls: true, webVideo: true, resolutions: 'max' }) }) - function runTests (objectStorage?: ObjectStorageCommand) { - + function runTests () { describe('When deleting all files', function () { let validId1: string let validId2: string @@ -222,7 +221,7 @@ describe('Test videos files', function () { const objectStorage = new ObjectStorageCommand() - runTests(objectStorage) + runTests() }) after(async function () { diff --git a/packages/tests/src/api/videos/video-transcription.ts b/packages/tests/src/api/videos/video-transcription.ts index f010f41d2..799c9b125 100644 --- a/packages/tests/src/api/videos/video-transcription.ts +++ b/packages/tests/src/api/videos/video-transcription.ts @@ -205,7 +205,7 @@ describe('Test video transcription', function () { tasks: [ { name: 'cut' as 'cut', - options: { start: 1 } + options: { start: 10 } } ] }) @@ -231,7 +231,7 @@ describe('Test video transcription', function () { tasks: [ { name: 'cut' as 'cut', - options: { start: 1 } + options: { start: 10 } } ] }) @@ -242,6 +242,40 @@ describe('Test video transcription', function () { expect(oldContent).to.equal(newContent) }) + it('Should run transcription after a video replacement', async function () { + this.timeout(120000) + + await servers[0].config.enableFileUpdate() + + const uuid = await uploadForTranscription(servers[0]) + await waitJobs(servers) + + await checkAutoCaption({ servers, uuid }) + const oldContent = await getCaptionContent(servers[0], uuid, 'en') + + await servers[0].videos.replaceSourceFile({ videoId: uuid, fixture: 'video_short_360p.mp4' }) + await waitJobs(servers) + + const newContent = await getCaptionContent(servers[0], uuid, 'en') + expect(oldContent).to.not.equal(newContent) + }) + + it('Should not run transcription after video replacement if the subtitle has not been auto generated', async function () { + this.timeout(120000) + + const uuid = await uploadForTranscription(servers[0], { language: 'en' }) + await waitJobs(servers) + + await servers[0].captions.add({ language: 'en', videoId: uuid, fixture: 'subtitle-good1.vtt' }) + const oldContent = await getCaptionContent(servers[0], uuid, 'en') + + await servers[0].videos.replaceSourceFile({ videoId: uuid, fixture: 'video_short_360p.mp4' }) + await waitJobs(servers) + + const newContent = await getCaptionContent(servers[0], uuid, 'en') + expect(oldContent).to.equal(newContent) + }) + it('Should run transcription with HLS only and audio splitted', async function () { this.timeout(360000) diff --git a/server/core/controllers/api/videos/source.ts b/server/core/controllers/api/videos/source.ts index f6eac1bd2..42ac582cc 100644 --- a/server/core/controllers/api/videos/source.ts +++ b/server/core/controllers/api/videos/source.ts @@ -6,6 +6,7 @@ import { Hooks } from '@server/lib/plugins/hooks.js' import { regenerateMiniaturesIfNeeded } from '@server/lib/thumbnail.js' import { setupUploadResumableRoutes } from '@server/lib/uploadx.js' import { autoBlacklistVideoIfNeeded } from '@server/lib/video-blacklist.js' +import { regenerateTranscriptionTaskIfNeeded } from '@server/lib/video-captions.js' import { buildNewFile, createVideoSource } from '@server/lib/video-file.js' import { buildMoveVideoJob, buildStoryboardJobIfNeeded } from '@server/lib/video-jobs.js' import { VideoPathManager } from '@server/lib/video-path-manager.js' @@ -198,7 +199,9 @@ async function addVideoJobsAfterUpload (video: MVideoFullLight, videoFile: MVide }) } - return JobQueue.Instance.createSequentialJobFlow(...jobs) + await JobQueue.Instance.createSequentialJobFlow(...jobs) + + await regenerateTranscriptionTaskIfNeeded(video) } async function removeOldFiles (options: { diff --git a/server/core/lib/video-captions.ts b/server/core/lib/video-captions.ts index 9baf913ac..d885dc2f5 100644 --- a/server/core/lib/video-captions.ts +++ b/server/core/lib/video-captions.ts @@ -101,6 +101,16 @@ export async function updateHLSMasterOnCaptionChange (video: MVideo, hls: MStrea // --------------------------------------------------------------------------- +export async function regenerateTranscriptionTaskIfNeeded (video: MVideo) { + if (video.language && CONFIG.VIDEO_TRANSCRIPTION.ENABLED) { + const caption = await VideoCaptionModel.loadByVideoIdAndLanguage(video.id, video.language) + + if (caption?.automaticallyGenerated) { + await createTranscriptionTaskIfNeeded(video) + } + } +} + export async function createTranscriptionTaskIfNeeded (video: MVideoUUID & MVideoUrl) { if (CONFIG.VIDEO_TRANSCRIPTION.ENABLED !== true) return diff --git a/server/core/lib/video-studio.ts b/server/core/lib/video-studio.ts index 9d53b6575..256fe8635 100644 --- a/server/core/lib/video-studio.ts +++ b/server/core/lib/video-studio.ts @@ -4,14 +4,13 @@ import { VideoStudioEditionPayload, VideoStudioTask, VideoStudioTaskPayload } fr import { logger, loggerTagsFactory } from '@server/helpers/logger.js' import { createTorrentAndSetInfoHashFromPath } from '@server/helpers/webtorrent.js' import { CONFIG } from '@server/initializers/config.js' -import { VideoCaptionModel } from '@server/models/video/video-caption.js' import { MUser, MVideoFile, MVideoFullLight, MVideoWithAllFiles, MVideoWithFile } from '@server/types/models/index.js' import { move, remove } from 'fs-extra/esm' import { join } from 'path' import { JobQueue } from './job-queue/index.js' import { VideoStudioTranscodingJobHandler } from './runners/index.js' import { getTranscodingJobPriority } from './transcoding/transcoding-priority.js' -import { createTranscriptionTaskIfNeeded } from './video-captions.js' +import { regenerateTranscriptionTaskIfNeeded } from './video-captions.js' import { buildNewFile, removeHLSPlaylist, removeWebVideoFile } from './video-file.js' import { buildStoryboardJobIfNeeded } from './video-jobs.js' import { VideoPathManager } from './video-path-manager.js' @@ -112,7 +111,6 @@ export async function onVideoStudioEnded (options: { await JobQueue.Instance.createSequentialJobFlow( buildStoryboardJobIfNeeded({ video, federate: false }), - { type: 'federate-video' as 'federate-video', payload: { @@ -120,7 +118,6 @@ export async function onVideoStudioEnded (options: { isNewVideoForFederation: false } }, - { type: 'transcoding-job-builder' as 'transcoding-job-builder', payload: { @@ -132,13 +129,7 @@ export async function onVideoStudioEnded (options: { } ) - if (video.language && CONFIG.VIDEO_TRANSCRIPTION.ENABLED) { - const caption = await VideoCaptionModel.loadByVideoIdAndLanguage(video.id, video.language) - - if (caption?.automaticallyGenerated) { - await createTranscriptionTaskIfNeeded(video) - } - } + await regenerateTranscriptionTaskIfNeeded(video) } // ---------------------------------------------------------------------------