diff --git a/packages/server-commands/src/server/jobs.ts b/packages/server-commands/src/server/jobs.ts index 06c5e7ef9..10fee95d9 100644 --- a/packages/server-commands/src/server/jobs.ts +++ b/packages/server-commands/src/server/jobs.ts @@ -32,7 +32,6 @@ async function waitJobs ( if (process.env.DEBUG) console.log(`${new Date().toISOString()} - Checking ${server.url}`) for (const state of states) { - const jobPromise = server.jobs.list({ state, start: 0, diff --git a/packages/tests/src/api/videos/resumable-upload.ts b/packages/tests/src/api/videos/resumable-upload.ts index 03ba42bc9..cda059efb 100644 --- a/packages/tests/src/api/videos/resumable-upload.ts +++ b/packages/tests/src/api/videos/resumable-upload.ts @@ -187,6 +187,9 @@ describe('Test resumable upload', function () { }) it('Should not accept more chunks than expected with an invalid content length/content range', async function () { + // Sometimes the server answers 409, and sometimes 400 :shrug: + this.retries(3) + const uploadId = await prepareUpload({ size: 1500 }) try { diff --git a/server/core/lib/job-queue/handlers/video-transcoding.ts b/server/core/lib/job-queue/handlers/video-transcoding.ts index f8ba65105..119f064f8 100644 --- a/server/core/lib/job-queue/handlers/video-transcoding.ts +++ b/server/core/lib/job-queue/handlers/video-transcoding.ts @@ -5,6 +5,7 @@ import { OptimizeTranscodingPayload, VideoTranscodingPayload } from '@peertube/peertube-models' +import { isVideoMissHLSAudio } from '@server/lib/runners/job-handlers/shared/utils.js' import { onTranscodingEnded } from '@server/lib/transcoding/ended-transcoding.js' import { generateHlsPlaylistResolution } from '@server/lib/transcoding/hls-transcoding.js' import { mergeAudioVideofile, optimizeOriginalVideofile, transcodeNewWebVideoResolution } from '@server/lib/transcoding/web-transcoding.js' @@ -150,5 +151,12 @@ async function handleHLSJob (job: Job, payload: HLSTranscodingPayload, videoArg: await removeAllWebVideoFiles(video) } - await onTranscodingEnded({ isNewVideo: payload.isNewVideo, moveVideoToNextState: !payload.hasChildren, video }) + let moveVideoToNextState = !payload.hasChildren + + // Splitted audio, wait audio generation before moving the video in its next state + if (await isVideoMissHLSAudio({ resolution: payload.resolution, separatedAudio: payload.separatedAudio, videoId: videoArg.uuid })) { + moveVideoToNextState = false + } + + await onTranscodingEnded({ isNewVideo: payload.isNewVideo, moveVideoToNextState, video }) } diff --git a/server/core/lib/runners/job-handlers/shared/utils.ts b/server/core/lib/runners/job-handlers/shared/utils.ts index e78d05235..7b38a4d85 100644 --- a/server/core/lib/runners/job-handlers/shared/utils.ts +++ b/server/core/lib/runners/job-handlers/shared/utils.ts @@ -1,10 +1,14 @@ +import { + RunnerJobVODAudioMergeTranscodingPrivatePayload, + RunnerJobVODWebVideoTranscodingPrivatePayload, + VideoResolution +} from '@peertube/peertube-models' import { logger, LoggerTagsFn } from '@server/helpers/logger.js' import { onTranscodingEnded } from '@server/lib/transcoding/ended-transcoding.js' import { onWebVideoFileTranscoding } from '@server/lib/transcoding/web-transcoding.js' import { VideoModel } from '@server/models/video/video.js' import { MVideoFullLight } from '@server/types/models/index.js' import { MRunnerJob } from '@server/types/models/runners/index.js' -import { RunnerJobVODAudioMergeTranscodingPrivatePayload, RunnerJobVODWebVideoTranscodingPrivatePayload } from '@peertube/peertube-models' export async function onVODWebVideoOrAudioMergeTranscodingJob (options: { video: MVideoFullLight @@ -34,3 +38,20 @@ export async function loadRunnerVideo (runnerJob: MRunnerJob, lTags: LoggerTagsF return video } + +export async function isVideoMissHLSAudio (options: { + resolution: number + separatedAudio: boolean + videoId: string | number +}) { + if (!options.separatedAudio) return false + + if (options.resolution !== VideoResolution.H_NOVIDEO) { + const video = await VideoModel.loadFull(options.videoId) + + // Video doesn't have audio file yet + if (video.hasAudio() !== true) return true + } + + return false +} diff --git a/server/core/lib/runners/job-handlers/vod-hls-transcoding-job-handler.ts b/server/core/lib/runners/job-handlers/vod-hls-transcoding-job-handler.ts index 045ae82ca..b54ade623 100644 --- a/server/core/lib/runners/job-handlers/vod-hls-transcoding-job-handler.ts +++ b/server/core/lib/runners/job-handlers/vod-hls-transcoding-job-handler.ts @@ -15,7 +15,7 @@ import { MVideoWithFile } from '@server/types/models/index.js' import { MRunnerJob } from '@server/types/models/runners/index.js' import { generateRunnerTranscodingAudioInputFileUrl, generateRunnerTranscodingVideoInputFileUrl } from '../runner-urls.js' import { AbstractVODTranscodingJobHandler } from './abstract-vod-transcoding-job-handler.js' -import { loadRunnerVideo } from './shared/utils.js' +import { isVideoMissHLSAudio, loadRunnerVideo } from './shared/utils.js' type CreateOptions = { video: MVideoWithFile @@ -80,6 +80,7 @@ export class VODHLSTranscodingJobHandler extends AbstractVODTranscodingJobHandle resultPayload: VODHLSTranscodingSuccess }) { const { runnerJob, resultPayload } = options + const payload = runnerJob.payload as RunnerJobVODHLSTranscodingPayload const privatePayload = runnerJob.privatePayload as RunnerJobVODHLSTranscodingPrivatePayload const video = await loadRunnerVideo(runnerJob, this.lTags) @@ -94,7 +95,14 @@ export class VODHLSTranscodingJobHandler extends AbstractVODTranscodingJobHandle videoOutputPath: videoFilePath }) - await onTranscodingEnded({ isNewVideo: privatePayload.isNewVideo, moveVideoToNextState: true, video }) + // Splitted audio? Wait audio generation before moving the video in its next state + const moveVideoToNextState = !await isVideoMissHLSAudio({ + resolution: payload.output.resolution, + separatedAudio: payload.output.separatedAudio, + videoId: video.uuid + }) + + await onTranscodingEnded({ isNewVideo: privatePayload.isNewVideo, moveVideoToNextState, video }) if (privatePayload.deleteWebVideoFiles === true) { logger.info('Removing web video files of %s now we have a HLS version of it.', video.uuid, this.lTags(video.uuid)) diff --git a/server/core/lib/transcoding/shared/job-builders/abstract-job-builder.ts b/server/core/lib/transcoding/shared/job-builders/abstract-job-builder.ts index b9004d1d8..ba5959111 100644 --- a/server/core/lib/transcoding/shared/job-builders/abstract-job-builder.ts +++ b/server/core/lib/transcoding/shared/job-builders/abstract-job-builder.ts @@ -83,7 +83,7 @@ export abstract class AbstractJobBuilder

{ this.buildHLSJobPayload({ deleteWebVideoFiles: !CONFIG.TRANSCODING.WEB_VIDEOS.ENABLED && !hasSplitAudioTranscoding, - separatedAudio: CONFIG.TRANSCODING.HLS.SPLIT_AUDIO_AND_VIDEO, + separatedAudio: hasSplitAudioTranscoding, copyCodecs, @@ -103,7 +103,7 @@ export abstract class AbstractJobBuilder

{ ...this.buildHLSJobPayload({ deleteWebVideoFiles: !CONFIG.TRANSCODING.WEB_VIDEOS.ENABLED, - separatedAudio: CONFIG.TRANSCODING.HLS.SPLIT_AUDIO_AND_VIDEO, + separatedAudio: hasSplitAudioTranscoding, copyCodecs, resolution: 0, @@ -248,7 +248,7 @@ export abstract class AbstractJobBuilder

{ resolution, fps, isNewVideo, - separatedAudio: CONFIG.TRANSCODING.HLS.SPLIT_AUDIO_AND_VIDEO, + separatedAudio: hasAudio && CONFIG.TRANSCODING.HLS.SPLIT_AUDIO_AND_VIDEO, copyCodecs: CONFIG.TRANSCODING.WEB_VIDEOS.ENABLED }) )