diff --git a/scripts/create-transcoding-job.ts b/scripts/create-transcoding-job.ts index ffdf55ae4..c77a5805f 100755 --- a/scripts/create-transcoding-job.ts +++ b/scripts/create-transcoding-job.ts @@ -49,11 +49,14 @@ async function run () { const dataInput: VideoTranscodingPayload[] = [] const maxResolution = video.getMaxQualityFile().resolution + // FIXME: check the file has audio + const hasAudio = true + // Generate HLS files if (options.generateHls || CONFIG.TRANSCODING.WEBTORRENT.ENABLED === false) { const resolutionsEnabled = options.resolution ? [ parseInt(options.resolution) ] - : computeResolutionsToTranscode({ input: maxResolution, type: 'vod', includeInput: true, strictLower: false }) + : computeResolutionsToTranscode({ input: maxResolution, type: 'vod', includeInput: true, strictLower: false, hasAudio }) for (const resolution of resolutionsEnabled) { dataInput.push({ @@ -61,7 +64,7 @@ async function run () { videoUUID: video.uuid, resolution, - hasAudio: true, + hasAudio, copyCodecs: false, isNewVideo: false, @@ -77,8 +80,7 @@ async function run () { createHLSIfNeeded: true, - // FIXME: check the file has audio - hasAudio: true, + hasAudio, isNewVideo: false, resolution: parseInt(options.resolution) diff --git a/server/controllers/api/videos/transcoding.ts b/server/controllers/api/videos/transcoding.ts index 9aca761c1..a39e47dfe 100644 --- a/server/controllers/api/videos/transcoding.ts +++ b/server/controllers/api/videos/transcoding.ts @@ -32,9 +32,10 @@ async function createTranscoding (req: express.Request, res: express.Response) { const body: VideoTranscodingCreate = req.body - const { resolution: maxResolution, audioStream } = await video.probeMaxQualityFile() + const { resolution: maxResolution, hasAudio } = await video.probeMaxQualityFile() + const resolutions = await Hooks.wrapObject( - computeResolutionsToTranscode({ input: maxResolution, type: 'vod', includeInput: true, strictLower: false }), + computeResolutionsToTranscode({ input: maxResolution, type: 'vod', includeInput: true, strictLower: false, hasAudio }), 'filter:transcoding.manual.resolutions-to-transcode.result', body ) @@ -46,7 +47,6 @@ async function createTranscoding (req: express.Request, res: express.Response) { video.state = VideoState.TO_TRANSCODE await video.save() - const hasAudio = !!audioStream const childrenResolutions = resolutions.filter(r => r !== maxResolution) const children = await Bluebird.mapSeries(childrenResolutions, resolution => { diff --git a/server/helpers/ffmpeg/ffprobe-utils.ts b/server/helpers/ffmpeg/ffprobe-utils.ts index 2c6253d44..8cfdba4f9 100644 --- a/server/helpers/ffmpeg/ffprobe-utils.ts +++ b/server/helpers/ffmpeg/ffprobe-utils.ts @@ -96,8 +96,9 @@ function computeResolutionsToTranscode (options: { type: 'vod' | 'live' includeInput: boolean strictLower: boolean + hasAudio: boolean }) { - const { input, type, includeInput, strictLower } = options + const { input, type, includeInput, strictLower, hasAudio } = options const configResolutions = type === 'vod' ? CONFIG.TRANSCODING.RESOLUTIONS @@ -125,6 +126,8 @@ function computeResolutionsToTranscode (options: { if (input < resolution) continue // We only want lower resolutions than input file if (strictLower && input === resolution) continue + // Audio resolutio but no audio in the video + if (resolution === VideoResolution.H_NOVIDEO && !hasAudio) continue resolutionsEnabled.add(resolution) } diff --git a/server/lib/job-queue/handlers/video-transcoding.ts b/server/lib/job-queue/handlers/video-transcoding.ts index 48c675678..3e6d23363 100644 --- a/server/lib/job-queue/handlers/video-transcoding.ts +++ b/server/lib/job-queue/handlers/video-transcoding.ts @@ -13,7 +13,6 @@ import { MergeAudioTranscodingPayload, NewWebTorrentResolutionTranscodingPayload, OptimizeTranscodingPayload, - VideoResolution, VideoTranscodingPayload } from '@shared/models' import { retryTransactionWrapper } from '../../../helpers/database-utils' @@ -281,7 +280,7 @@ async function createLowerResolutionsJobs (options: { // Create transcoding jobs if there are enabled resolutions const resolutionsEnabled = await Hooks.wrapObject( - computeResolutionsToTranscode({ input: videoFileResolution, type: 'vod', includeInput: false, strictLower: true }), + computeResolutionsToTranscode({ input: videoFileResolution, type: 'vod', includeInput: false, strictLower: true, hasAudio }), 'filter:transcoding.auto.resolutions-to-transcode.result', options ) @@ -289,8 +288,6 @@ async function createLowerResolutionsJobs (options: { const resolutionCreated: string[] = [] for (const resolution of resolutionsEnabled) { - if (resolution === VideoResolution.H_NOVIDEO && hasAudio === false) continue - let dataInput: VideoTranscodingPayload if (CONFIG.TRANSCODING.WEBTORRENT.ENABLED && type === 'webtorrent') { diff --git a/server/lib/live/live-manager.ts b/server/lib/live/live-manager.ts index 9470b530b..5e459f3c3 100644 --- a/server/lib/live/live-manager.ts +++ b/server/lib/live/live-manager.ts @@ -245,7 +245,7 @@ class LiveManager { ) const allResolutions = await Hooks.wrapObject( - this.buildAllResolutionsToTranscode(resolution), + this.buildAllResolutionsToTranscode(resolution, hasAudio), 'filter:transcoding.auto.resolutions-to-transcode.result', { video } ) @@ -460,11 +460,11 @@ class LiveManager { return join(directory, files.sort().reverse()[0]) } - private buildAllResolutionsToTranscode (originResolution: number) { + private buildAllResolutionsToTranscode (originResolution: number, hasAudio: boolean) { const includeInput = CONFIG.LIVE.TRANSCODING.ALWAYS_TRANSCODE_ORIGINAL_RESOLUTION const resolutionsEnabled = CONFIG.LIVE.TRANSCODING.ENABLED - ? computeResolutionsToTranscode({ input: originResolution, type: 'live', includeInput, strictLower: false }) + ? computeResolutionsToTranscode({ input: originResolution, type: 'live', includeInput, strictLower: false, hasAudio }) : [] if (resolutionsEnabled.length === 0) { diff --git a/server/lib/transcoding/transcoding.ts b/server/lib/transcoding/transcoding.ts index d83c5419f..e6914db87 100644 --- a/server/lib/transcoding/transcoding.ts +++ b/server/lib/transcoding/transcoding.ts @@ -446,7 +446,15 @@ async function generateHlsPlaylistCommon (options: { function buildOriginalFileResolution (inputResolution: number) { if (CONFIG.TRANSCODING.ALWAYS_TRANSCODE_ORIGINAL_RESOLUTION === true) return toEven(inputResolution) - const resolutions = computeResolutionsToTranscode({ input: inputResolution, type: 'vod', includeInput: false, strictLower: false }) + const resolutions = computeResolutionsToTranscode({ + input: inputResolution, + type: 'vod', + includeInput: false, + strictLower: false, + // We don't really care about the audio resolution in this context + hasAudio: true + }) + if (resolutions.length === 0) return toEven(inputResolution) return Math.max(...resolutions) diff --git a/server/models/video/video.ts b/server/models/video/video.ts index f3907bed4..56cc45cfe 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts @@ -34,7 +34,7 @@ import { isVideoInPrivateDirectory } from '@server/lib/video-privacy' import { getServerActor } from '@server/models/application/application' import { ModelCache } from '@server/models/model-cache' import { buildVideoEmbedPath, buildVideoWatchPath, pick } from '@shared/core-utils' -import { ffprobePromise, getAudioStream, uuidToShort } from '@shared/extra-utils' +import { ffprobePromise, getAudioStream, hasAudioStream, uuidToShort } from '@shared/extra-utils' import { ResultList, ThumbnailType, @@ -1751,9 +1751,11 @@ export class VideoModel extends Model>> { const probe = await ffprobePromise(originalFilePath) const { audioStream } = await getAudioStream(originalFilePath, probe) + const hasAudio = await hasAudioStream(originalFilePath, probe) return { audioStream, + hasAudio, ...await getVideoStreamDimensionsInfo(originalFilePath, probe) }