Correctly handle RTMP streams without audio

This commit is contained in:
Chocobozzz 2022-09-28 10:23:03 +02:00
parent 690bad52e1
commit 1ce4256a65
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
3 changed files with 43 additions and 17 deletions

View File

@ -23,11 +23,24 @@ async function getLiveTranscodingCommand (options: {
fps: number
bitrate: number
ratio: number
hasAudio: boolean
availableEncoders: AvailableEncoders
profile: string
}) {
const { inputUrl, outPath, resolutions, fps, bitrate, availableEncoders, profile, masterPlaylistName, ratio, latencyMode } = options
const {
inputUrl,
outPath,
resolutions,
fps,
bitrate,
availableEncoders,
profile,
masterPlaylistName,
ratio,
latencyMode,
hasAudio
} = options
const command = getFFmpeg(inputUrl, 'live')
@ -47,6 +60,7 @@ async function getLiveTranscodingCommand (options: {
addDefaultEncoderGlobalParams(command)
for (let i = 0; i < resolutions.length; i++) {
const streamMap: string[] = []
const resolution = resolutions[i]
const resolutionFPS = computeFPS(fps, resolution)
@ -94,9 +108,11 @@ async function getLiveTranscodingCommand (options: {
options: `w=-2:h=${resolution}`,
outputs: `vout${resolution}`
})
streamMap.push(`v:${i}`)
}
{
if (hasAudio) {
const streamType: StreamType = 'audio'
const builderResult = await getEncoderBuilderResult({ ...baseEncoderBuilderParams, streamType })
if (!builderResult) {
@ -114,9 +130,11 @@ async function getLiveTranscodingCommand (options: {
command.outputOption(`${buildStreamSuffix('-c:a', i)} ${builderResult.encoder}`)
applyEncoderOptions(command, builderResult.result)
streamMap.push(`a:${i}`)
}
varStreamMap.push(`v:${i},a:${i}`)
varStreamMap.push(streamMap.join(','))
}
command.complexFilter(complexFilter)

View File

@ -1,4 +1,3 @@
import { readdir, readFile } from 'fs-extra'
import { createServer, Server } from 'net'
import { join } from 'path'
@ -9,7 +8,8 @@ import {
getLiveSegmentTime,
getVideoStreamBitrate,
getVideoStreamDimensionsInfo,
getVideoStreamFPS
getVideoStreamFPS,
hasAudioStream
} from '@server/helpers/ffmpeg'
import { logger, loggerTagsFactory } from '@server/helpers/logger'
import { CONFIG, registerConfigChangedHandler } from '@server/initializers/config'
@ -20,7 +20,7 @@ import { VideoLiveModel } from '@server/models/video/video-live'
import { VideoLiveSessionModel } from '@server/models/video/video-live-session'
import { VideoStreamingPlaylistModel } from '@server/models/video/video-streaming-playlist'
import { MStreamingPlaylistVideo, MVideo, MVideoLiveSession, MVideoLiveVideo } from '@server/types/models'
import { wait } from '@shared/core-utils'
import { pick, wait } from '@shared/core-utils'
import { LiveVideoError, VideoState, VideoStreamingPlaylistType } from '@shared/models'
import { federateVideoIfNeeded } from '../activitypub/videos'
import { JobQueue } from '../job-queue'
@ -232,10 +232,11 @@ class LiveManager {
const now = Date.now()
const probe = await ffprobePromise(inputUrl)
const [ { resolution, ratio }, fps, bitrate ] = await Promise.all([
const [ { resolution, ratio }, fps, bitrate, hasAudio ] = await Promise.all([
getVideoStreamDimensionsInfo(inputUrl, probe),
getVideoStreamFPS(inputUrl, probe),
getVideoStreamBitrate(inputUrl, probe)
getVideoStreamBitrate(inputUrl, probe),
hasAudioStream(inputUrl, probe)
])
logger.info(
@ -259,26 +260,30 @@ class LiveManager {
return this.runMuxingSession({
sessionId,
videoLive,
streamingPlaylist,
inputUrl,
fps,
bitrate,
ratio,
allResolutions
allResolutions,
hasAudio
})
}
private async runMuxingSession (options: {
sessionId: string
videoLive: MVideoLiveVideo
streamingPlaylist: MStreamingPlaylistVideo
inputUrl: string
fps: number
bitrate: number
ratio: number
allResolutions: number[]
hasAudio: boolean
}) {
const { sessionId, videoLive, streamingPlaylist, allResolutions, fps, bitrate, ratio, inputUrl } = options
const { sessionId, videoLive } = options
const videoUUID = videoLive.Video.uuid
const localLTags = lTags(sessionId, videoUUID)
@ -289,15 +294,11 @@ class LiveManager {
const muxingSession = new MuxingSession({
context: this.getContext(),
user,
sessionId,
videoLive,
streamingPlaylist,
inputUrl,
bitrate,
ratio,
fps,
allResolutions
user,
...pick(options, [ 'streamingPlaylist', 'inputUrl', 'bitrate', 'ratio', 'fps', 'allResolutions', 'hasAudio' ])
})
muxingSession.on('master-playlist-created', () => this.publishAndFederateLive(videoLive, localLTags))

View File

@ -59,6 +59,8 @@ class MuxingSession extends EventEmitter {
private readonly bitrate: number
private readonly ratio: number
private readonly hasAudio: boolean
private readonly videoId: number
private readonly videoUUID: string
private readonly saveReplay: boolean
@ -94,6 +96,7 @@ class MuxingSession extends EventEmitter {
bitrate: number
ratio: number
allResolutions: number[]
hasAudio: boolean
}) {
super()
@ -108,6 +111,8 @@ class MuxingSession extends EventEmitter {
this.bitrate = options.bitrate
this.ratio = options.ratio
this.hasAudio = options.hasAudio
this.allResolutions = options.allResolutions
this.videoId = this.videoLive.Video.id
@ -140,6 +145,8 @@ class MuxingSession extends EventEmitter {
bitrate: this.bitrate,
ratio: this.ratio,
hasAudio: this.hasAudio,
availableEncoders: VideoTranscodingProfilesManager.Instance.getAvailableEncoders(),
profile: CONFIG.LIVE.TRANSCODING.PROFILE
})