Provide public RTMP URL to runners

pull/5817/head
Chocobozzz 2023-05-16 09:12:50 +02:00
parent b30ad9888f
commit 2870570505
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
7 changed files with 67 additions and 30 deletions

View File

@ -55,8 +55,12 @@ const WEBSERVER = {
WS: '', WS: '',
HOSTNAME: '', HOSTNAME: '',
PORT: 0, PORT: 0,
RTMP_URL: '', RTMP_URL: '',
RTMPS_URL: '' RTMPS_URL: '',
RTMP_BASE_LIVE_URL: '',
RTMPS_BASE_LIVE_URL: ''
} }
// Sortable columns per schema // Sortable columns per schema
@ -1242,8 +1246,11 @@ function updateWebserverUrls () {
const rtmpHostname = CONFIG.LIVE.RTMP.PUBLIC_HOSTNAME || CONFIG.WEBSERVER.HOSTNAME const rtmpHostname = CONFIG.LIVE.RTMP.PUBLIC_HOSTNAME || CONFIG.WEBSERVER.HOSTNAME
const rtmpsHostname = CONFIG.LIVE.RTMPS.PUBLIC_HOSTNAME || CONFIG.WEBSERVER.HOSTNAME const rtmpsHostname = CONFIG.LIVE.RTMPS.PUBLIC_HOSTNAME || CONFIG.WEBSERVER.HOSTNAME
WEBSERVER.RTMP_URL = 'rtmp://' + rtmpHostname + ':' + CONFIG.LIVE.RTMP.PORT + '/' + VIDEO_LIVE.RTMP.BASE_PATH WEBSERVER.RTMP_URL = 'rtmp://' + rtmpHostname + ':' + CONFIG.LIVE.RTMP.PORT
WEBSERVER.RTMPS_URL = 'rtmps://' + rtmpsHostname + ':' + CONFIG.LIVE.RTMPS.PORT + '/' + VIDEO_LIVE.RTMP.BASE_PATH WEBSERVER.RTMPS_URL = 'rtmps://' + rtmpsHostname + ':' + CONFIG.LIVE.RTMPS.PORT
WEBSERVER.RTMP_BASE_LIVE_URL = WEBSERVER.RTMP_URL + '/' + VIDEO_LIVE.RTMP.BASE_PATH
WEBSERVER.RTMPS_BASE_LIVE_URL = WEBSERVER.RTMPS_URL + '/' + VIDEO_LIVE.RTMP.BASE_PATH
} }
function updateWebserverConfig () { function updateWebserverConfig () {

View File

@ -4,7 +4,7 @@ import { join } from 'path'
import { createServer as createServerTLS, Server as ServerTLS } from 'tls' import { createServer as createServerTLS, Server as ServerTLS } from 'tls'
import { logger, loggerTagsFactory } from '@server/helpers/logger' import { logger, loggerTagsFactory } from '@server/helpers/logger'
import { CONFIG, registerConfigChangedHandler } from '@server/initializers/config' import { CONFIG, registerConfigChangedHandler } from '@server/initializers/config'
import { VIDEO_LIVE } from '@server/initializers/constants' import { VIDEO_LIVE, WEBSERVER } from '@server/initializers/constants'
import { sequelizeTypescript } from '@server/initializers/database' import { sequelizeTypescript } from '@server/initializers/database'
import { RunnerJobModel } from '@server/models/runner/runner-job' import { RunnerJobModel } from '@server/models/runner/runner-job'
import { UserModel } from '@server/models/user/user' import { UserModel } from '@server/models/user/user'
@ -73,8 +73,10 @@ class LiveManager {
} }
const session = this.getContext().sessions.get(sessionId) const session = this.getContext().sessions.get(sessionId)
const inputLocalUrl = session.inputOriginLocalUrl + streamPath
const inputPublicUrl = session.inputOriginPublicUrl + streamPath
this.handleSession(sessionId, session.inputOriginUrl + streamPath, splittedPath[2]) this.handleSession({ sessionId, inputPublicUrl, inputLocalUrl, streamKey: splittedPath[2] })
.catch(err => logger.error('Cannot handle sessions.', { err, ...lTags(sessionId) })) .catch(err => logger.error('Cannot handle sessions.', { err, ...lTags(sessionId) }))
}) })
@ -110,7 +112,8 @@ class LiveManager {
this.rtmpServer = createServer(socket => { this.rtmpServer = createServer(socket => {
const session = new NodeRtmpSession(config, socket) const session = new NodeRtmpSession(config, socket)
session.inputOriginUrl = 'rtmp://127.0.0.1:' + CONFIG.LIVE.RTMP.PORT session.inputOriginLocalUrl = 'rtmp://127.0.0.1:' + CONFIG.LIVE.RTMP.PORT
session.inputOriginPublicUrl = WEBSERVER.RTMP_URL
session.run() session.run()
}) })
@ -133,7 +136,8 @@ class LiveManager {
this.rtmpsServer = createServerTLS(serverOptions, socket => { this.rtmpsServer = createServerTLS(serverOptions, socket => {
const session = new NodeRtmpSession(config, socket) const session = new NodeRtmpSession(config, socket)
session.inputOriginUrl = 'rtmps://127.0.0.1:' + CONFIG.LIVE.RTMPS.PORT session.inputOriginLocalUrl = 'rtmps://127.0.0.1:' + CONFIG.LIVE.RTMPS.PORT
session.inputOriginPublicUrl = WEBSERVER.RTMPS_URL
session.run() session.run()
}) })
@ -210,7 +214,14 @@ class LiveManager {
} }
} }
private async handleSession (sessionId: string, inputUrl: string, streamKey: string) { private async handleSession (options: {
sessionId: string
inputLocalUrl: string
inputPublicUrl: string
streamKey: string
}) {
const { inputLocalUrl, inputPublicUrl, sessionId, streamKey } = options
const videoLive = await VideoLiveModel.loadByStreamKey(streamKey) const videoLive = await VideoLiveModel.loadByStreamKey(streamKey)
if (!videoLive) { if (!videoLive) {
logger.warn('Unknown live video with stream key %s.', streamKey, lTags(sessionId)) logger.warn('Unknown live video with stream key %s.', streamKey, lTags(sessionId))
@ -239,18 +250,18 @@ class LiveManager {
this.videoSessions.set(video.uuid, sessionId) this.videoSessions.set(video.uuid, sessionId)
const now = Date.now() const now = Date.now()
const probe = await ffprobePromise(inputUrl) const probe = await ffprobePromise(inputLocalUrl)
const [ { resolution, ratio }, fps, bitrate, hasAudio ] = await Promise.all([ const [ { resolution, ratio }, fps, bitrate, hasAudio ] = await Promise.all([
getVideoStreamDimensionsInfo(inputUrl, probe), getVideoStreamDimensionsInfo(inputLocalUrl, probe),
getVideoStreamFPS(inputUrl, probe), getVideoStreamFPS(inputLocalUrl, probe),
getVideoStreamBitrate(inputUrl, probe), getVideoStreamBitrate(inputLocalUrl, probe),
hasAudioStream(inputUrl, probe) hasAudioStream(inputLocalUrl, probe)
]) ])
logger.info( logger.info(
'%s probing took %d ms (bitrate: %d, fps: %d, resolution: %d)', '%s probing took %d ms (bitrate: %d, fps: %d, resolution: %d)',
inputUrl, Date.now() - now, bitrate, fps, resolution, lTags(sessionId, video.uuid) inputLocalUrl, Date.now() - now, bitrate, fps, resolution, lTags(sessionId, video.uuid)
) )
const allResolutions = await Hooks.wrapObject( const allResolutions = await Hooks.wrapObject(
@ -268,7 +279,8 @@ class LiveManager {
sessionId, sessionId,
videoLive, videoLive,
inputUrl, inputLocalUrl,
inputPublicUrl,
fps, fps,
bitrate, bitrate,
ratio, ratio,
@ -281,7 +293,9 @@ class LiveManager {
sessionId: string sessionId: string
videoLive: MVideoLiveVideoWithSetting videoLive: MVideoLiveVideoWithSetting
inputUrl: string inputLocalUrl: string
inputPublicUrl: string
fps: number fps: number
bitrate: number bitrate: number
ratio: number ratio: number
@ -303,7 +317,7 @@ class LiveManager {
videoLive, videoLive,
user, user,
...pick(options, [ 'inputUrl', 'bitrate', 'ratio', 'fps', 'allResolutions', 'hasAudio' ]) ...pick(options, [ 'inputLocalUrl', 'inputPublicUrl', 'bitrate', 'ratio', 'fps', 'allResolutions', 'hasAudio' ])
}) })
muxingSession.on('live-ready', () => this.publishAndFederateLive(videoLive, localLTags)) muxingSession.on('live-ready', () => this.publishAndFederateLive(videoLive, localLTags))

View File

@ -62,7 +62,10 @@ class MuxingSession extends EventEmitter {
private readonly user: MUserId private readonly user: MUserId
private readonly sessionId: string private readonly sessionId: string
private readonly videoLive: MVideoLiveVideo private readonly videoLive: MVideoLiveVideo
private readonly inputUrl: string
private readonly inputLocalUrl: string
private readonly inputPublicUrl: string
private readonly fps: number private readonly fps: number
private readonly allResolutions: number[] private readonly allResolutions: number[]
@ -107,7 +110,10 @@ class MuxingSession extends EventEmitter {
user: MUserId user: MUserId
sessionId: string sessionId: string
videoLive: MVideoLiveVideo videoLive: MVideoLiveVideo
inputUrl: string
inputLocalUrl: string
inputPublicUrl: string
fps: number fps: number
bitrate: number bitrate: number
ratio: number ratio: number
@ -120,7 +126,10 @@ class MuxingSession extends EventEmitter {
this.user = options.user this.user = options.user
this.sessionId = options.sessionId this.sessionId = options.sessionId
this.videoLive = options.videoLive this.videoLive = options.videoLive
this.inputUrl = options.inputUrl
this.inputLocalUrl = options.inputLocalUrl
this.inputPublicUrl = options.inputPublicUrl
this.fps = options.fps this.fps = options.fps
this.bitrate = options.bitrate this.bitrate = options.bitrate
@ -375,7 +384,7 @@ class MuxingSession extends EventEmitter {
private onTranscodedEnded () { private onTranscodedEnded () {
this.emit('transcoding-end', ({ videoUUID: this.videoUUID })) this.emit('transcoding-end', ({ videoUUID: this.videoUUID }))
logger.info('RTMP transmuxing for video %s ended. Scheduling cleanup', this.inputUrl, this.lTags()) logger.info('RTMP transmuxing for video %s ended. Scheduling cleanup', this.inputLocalUrl, this.lTags())
setTimeout(() => { setTimeout(() => {
// Wait latest segments generation, and close watchers // Wait latest segments generation, and close watchers
@ -468,7 +477,8 @@ class MuxingSession extends EventEmitter {
lTags: this.lTags, lTags: this.lTags,
inputUrl: this.inputUrl, inputLocalUrl: this.inputLocalUrl,
inputPublicUrl: this.inputPublicUrl,
toTranscode: this.allResolutions.map(resolution => ({ toTranscode: this.allResolutions.map(resolution => ({
resolution, resolution,

View File

@ -25,7 +25,9 @@ interface AbstractTranscodingWrapperOptions {
lTags: LoggerTagsFn lTags: LoggerTagsFn
inputUrl: string inputLocalUrl: string
inputPublicUrl: string
fps: number fps: number
toTranscode: { toTranscode: {
resolution: number resolution: number
@ -50,7 +52,9 @@ abstract class AbstractTranscodingWrapper extends EventEmitter {
fps: number fps: number
}[] }[]
protected readonly inputUrl: string protected readonly inputLocalUrl: string
protected readonly inputPublicUrl: string
protected readonly fps: number protected readonly fps: number
protected readonly bitrate: number protected readonly bitrate: number
protected readonly ratio: number protected readonly ratio: number
@ -76,7 +80,9 @@ abstract class AbstractTranscodingWrapper extends EventEmitter {
this.videoUUID = options.videoLive.Video.uuid this.videoUUID = options.videoLive.Video.uuid
this.streamingPlaylist = options.streamingPlaylist this.streamingPlaylist = options.streamingPlaylist
this.inputUrl = options.inputUrl this.inputLocalUrl = options.inputLocalUrl
this.inputPublicUrl = options.inputPublicUrl
this.fps = options.fps this.fps = options.fps
this.toTranscode = options.toTranscode this.toTranscode = options.toTranscode

View File

@ -15,7 +15,7 @@ export class FFmpegTranscodingWrapper extends AbstractTranscodingWrapper {
async run () { async run () {
this.ffmpegCommand = CONFIG.LIVE.TRANSCODING.ENABLED this.ffmpegCommand = CONFIG.LIVE.TRANSCODING.ENABLED
? await this.buildFFmpegLive().getLiveTranscodingCommand({ ? await this.buildFFmpegLive().getLiveTranscodingCommand({
inputUrl: this.inputUrl, inputUrl: this.inputLocalUrl,
outPath: this.outDirectory, outPath: this.outDirectory,
masterPlaylistName: this.streamingPlaylist.playlistFilename, masterPlaylistName: this.streamingPlaylist.playlistFilename,
@ -31,7 +31,7 @@ export class FFmpegTranscodingWrapper extends AbstractTranscodingWrapper {
hasAudio: this.hasAudio hasAudio: this.hasAudio
}) })
: this.buildFFmpegLive().getLiveMuxingCommand({ : this.buildFFmpegLive().getLiveMuxingCommand({
inputUrl: this.inputUrl, inputUrl: this.inputLocalUrl,
outPath: this.outDirectory, outPath: this.outDirectory,
masterPlaylistName: this.streamingPlaylist.playlistFilename, masterPlaylistName: this.streamingPlaylist.playlistFilename,

View File

@ -4,7 +4,7 @@ import { AbstractTranscodingWrapper } from './abstract-transcoding-wrapper'
export class RemoteTranscodingWrapper extends AbstractTranscodingWrapper { export class RemoteTranscodingWrapper extends AbstractTranscodingWrapper {
async run () { async run () {
await new LiveRTMPHLSTranscodingJobHandler().create({ await new LiveRTMPHLSTranscodingJobHandler().create({
rtmpUrl: this.inputUrl, rtmpUrl: this.inputPublicUrl,
toTranscode: this.toTranscode, toTranscode: this.toTranscode,
video: this.videoLive.Video, video: this.videoLive.Video,
outputDirectory: this.outDirectory, outputDirectory: this.outDirectory,

View File

@ -159,11 +159,11 @@ export class VideoLiveModel extends Model<Partial<AttributesOnly<VideoLiveModel>
streamKey: this.streamKey, streamKey: this.streamKey,
rtmpUrl: CONFIG.LIVE.RTMP.ENABLED rtmpUrl: CONFIG.LIVE.RTMP.ENABLED
? WEBSERVER.RTMP_URL ? WEBSERVER.RTMP_BASE_LIVE_URL
: null, : null,
rtmpsUrl: CONFIG.LIVE.RTMPS.ENABLED rtmpsUrl: CONFIG.LIVE.RTMPS.ENABLED
? WEBSERVER.RTMPS_URL ? WEBSERVER.RTMPS_BASE_LIVE_URL
: null : null
} }
} }