diff options
7 files changed, 67 insertions, 30 deletions
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 1dfc9fb27..46455dd5b 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -55,8 +55,12 @@ const WEBSERVER = { | |||
55 | WS: '', | 55 | WS: '', |
56 | HOSTNAME: '', | 56 | HOSTNAME: '', |
57 | PORT: 0, | 57 | PORT: 0, |
58 | |||
58 | RTMP_URL: '', | 59 | RTMP_URL: '', |
59 | RTMPS_URL: '' | 60 | RTMPS_URL: '', |
61 | |||
62 | RTMP_BASE_LIVE_URL: '', | ||
63 | RTMPS_BASE_LIVE_URL: '' | ||
60 | } | 64 | } |
61 | 65 | ||
62 | // Sortable columns per schema | 66 | // Sortable columns per schema |
@@ -1242,8 +1246,11 @@ function updateWebserverUrls () { | |||
1242 | const rtmpHostname = CONFIG.LIVE.RTMP.PUBLIC_HOSTNAME || CONFIG.WEBSERVER.HOSTNAME | 1246 | const rtmpHostname = CONFIG.LIVE.RTMP.PUBLIC_HOSTNAME || CONFIG.WEBSERVER.HOSTNAME |
1243 | const rtmpsHostname = CONFIG.LIVE.RTMPS.PUBLIC_HOSTNAME || CONFIG.WEBSERVER.HOSTNAME | 1247 | const rtmpsHostname = CONFIG.LIVE.RTMPS.PUBLIC_HOSTNAME || CONFIG.WEBSERVER.HOSTNAME |
1244 | 1248 | ||
1245 | WEBSERVER.RTMP_URL = 'rtmp://' + rtmpHostname + ':' + CONFIG.LIVE.RTMP.PORT + '/' + VIDEO_LIVE.RTMP.BASE_PATH | 1249 | WEBSERVER.RTMP_URL = 'rtmp://' + rtmpHostname + ':' + CONFIG.LIVE.RTMP.PORT |
1246 | WEBSERVER.RTMPS_URL = 'rtmps://' + rtmpsHostname + ':' + CONFIG.LIVE.RTMPS.PORT + '/' + VIDEO_LIVE.RTMP.BASE_PATH | 1250 | WEBSERVER.RTMPS_URL = 'rtmps://' + rtmpsHostname + ':' + CONFIG.LIVE.RTMPS.PORT |
1251 | |||
1252 | WEBSERVER.RTMP_BASE_LIVE_URL = WEBSERVER.RTMP_URL + '/' + VIDEO_LIVE.RTMP.BASE_PATH | ||
1253 | WEBSERVER.RTMPS_BASE_LIVE_URL = WEBSERVER.RTMPS_URL + '/' + VIDEO_LIVE.RTMP.BASE_PATH | ||
1247 | } | 1254 | } |
1248 | 1255 | ||
1249 | function updateWebserverConfig () { | 1256 | function updateWebserverConfig () { |
diff --git a/server/lib/live/live-manager.ts b/server/lib/live/live-manager.ts index 6d51f4de7..68aa18443 100644 --- a/server/lib/live/live-manager.ts +++ b/server/lib/live/live-manager.ts | |||
@@ -4,7 +4,7 @@ import { join } from 'path' | |||
4 | import { createServer as createServerTLS, Server as ServerTLS } from 'tls' | 4 | import { createServer as createServerTLS, Server as ServerTLS } from 'tls' |
5 | import { logger, loggerTagsFactory } from '@server/helpers/logger' | 5 | import { logger, loggerTagsFactory } from '@server/helpers/logger' |
6 | import { CONFIG, registerConfigChangedHandler } from '@server/initializers/config' | 6 | import { CONFIG, registerConfigChangedHandler } from '@server/initializers/config' |
7 | import { VIDEO_LIVE } from '@server/initializers/constants' | 7 | import { VIDEO_LIVE, WEBSERVER } from '@server/initializers/constants' |
8 | import { sequelizeTypescript } from '@server/initializers/database' | 8 | import { sequelizeTypescript } from '@server/initializers/database' |
9 | import { RunnerJobModel } from '@server/models/runner/runner-job' | 9 | import { RunnerJobModel } from '@server/models/runner/runner-job' |
10 | import { UserModel } from '@server/models/user/user' | 10 | import { UserModel } from '@server/models/user/user' |
@@ -73,8 +73,10 @@ class LiveManager { | |||
73 | } | 73 | } |
74 | 74 | ||
75 | const session = this.getContext().sessions.get(sessionId) | 75 | const session = this.getContext().sessions.get(sessionId) |
76 | const inputLocalUrl = session.inputOriginLocalUrl + streamPath | ||
77 | const inputPublicUrl = session.inputOriginPublicUrl + streamPath | ||
76 | 78 | ||
77 | this.handleSession(sessionId, session.inputOriginUrl + streamPath, splittedPath[2]) | 79 | this.handleSession({ sessionId, inputPublicUrl, inputLocalUrl, streamKey: splittedPath[2] }) |
78 | .catch(err => logger.error('Cannot handle sessions.', { err, ...lTags(sessionId) })) | 80 | .catch(err => logger.error('Cannot handle sessions.', { err, ...lTags(sessionId) })) |
79 | }) | 81 | }) |
80 | 82 | ||
@@ -110,7 +112,8 @@ class LiveManager { | |||
110 | this.rtmpServer = createServer(socket => { | 112 | this.rtmpServer = createServer(socket => { |
111 | const session = new NodeRtmpSession(config, socket) | 113 | const session = new NodeRtmpSession(config, socket) |
112 | 114 | ||
113 | session.inputOriginUrl = 'rtmp://127.0.0.1:' + CONFIG.LIVE.RTMP.PORT | 115 | session.inputOriginLocalUrl = 'rtmp://127.0.0.1:' + CONFIG.LIVE.RTMP.PORT |
116 | session.inputOriginPublicUrl = WEBSERVER.RTMP_URL | ||
114 | session.run() | 117 | session.run() |
115 | }) | 118 | }) |
116 | 119 | ||
@@ -133,7 +136,8 @@ class LiveManager { | |||
133 | this.rtmpsServer = createServerTLS(serverOptions, socket => { | 136 | this.rtmpsServer = createServerTLS(serverOptions, socket => { |
134 | const session = new NodeRtmpSession(config, socket) | 137 | const session = new NodeRtmpSession(config, socket) |
135 | 138 | ||
136 | session.inputOriginUrl = 'rtmps://127.0.0.1:' + CONFIG.LIVE.RTMPS.PORT | 139 | session.inputOriginLocalUrl = 'rtmps://127.0.0.1:' + CONFIG.LIVE.RTMPS.PORT |
140 | session.inputOriginPublicUrl = WEBSERVER.RTMPS_URL | ||
137 | session.run() | 141 | session.run() |
138 | }) | 142 | }) |
139 | 143 | ||
@@ -210,7 +214,14 @@ class LiveManager { | |||
210 | } | 214 | } |
211 | } | 215 | } |
212 | 216 | ||
213 | private async handleSession (sessionId: string, inputUrl: string, streamKey: string) { | 217 | private async handleSession (options: { |
218 | sessionId: string | ||
219 | inputLocalUrl: string | ||
220 | inputPublicUrl: string | ||
221 | streamKey: string | ||
222 | }) { | ||
223 | const { inputLocalUrl, inputPublicUrl, sessionId, streamKey } = options | ||
224 | |||
214 | const videoLive = await VideoLiveModel.loadByStreamKey(streamKey) | 225 | const videoLive = await VideoLiveModel.loadByStreamKey(streamKey) |
215 | if (!videoLive) { | 226 | if (!videoLive) { |
216 | logger.warn('Unknown live video with stream key %s.', streamKey, lTags(sessionId)) | 227 | logger.warn('Unknown live video with stream key %s.', streamKey, lTags(sessionId)) |
@@ -239,18 +250,18 @@ class LiveManager { | |||
239 | this.videoSessions.set(video.uuid, sessionId) | 250 | this.videoSessions.set(video.uuid, sessionId) |
240 | 251 | ||
241 | const now = Date.now() | 252 | const now = Date.now() |
242 | const probe = await ffprobePromise(inputUrl) | 253 | const probe = await ffprobePromise(inputLocalUrl) |
243 | 254 | ||
244 | const [ { resolution, ratio }, fps, bitrate, hasAudio ] = await Promise.all([ | 255 | const [ { resolution, ratio }, fps, bitrate, hasAudio ] = await Promise.all([ |
245 | getVideoStreamDimensionsInfo(inputUrl, probe), | 256 | getVideoStreamDimensionsInfo(inputLocalUrl, probe), |
246 | getVideoStreamFPS(inputUrl, probe), | 257 | getVideoStreamFPS(inputLocalUrl, probe), |
247 | getVideoStreamBitrate(inputUrl, probe), | 258 | getVideoStreamBitrate(inputLocalUrl, probe), |
248 | hasAudioStream(inputUrl, probe) | 259 | hasAudioStream(inputLocalUrl, probe) |
249 | ]) | 260 | ]) |
250 | 261 | ||
251 | logger.info( | 262 | logger.info( |
252 | '%s probing took %d ms (bitrate: %d, fps: %d, resolution: %d)', | 263 | '%s probing took %d ms (bitrate: %d, fps: %d, resolution: %d)', |
253 | inputUrl, Date.now() - now, bitrate, fps, resolution, lTags(sessionId, video.uuid) | 264 | inputLocalUrl, Date.now() - now, bitrate, fps, resolution, lTags(sessionId, video.uuid) |
254 | ) | 265 | ) |
255 | 266 | ||
256 | const allResolutions = await Hooks.wrapObject( | 267 | const allResolutions = await Hooks.wrapObject( |
@@ -268,7 +279,8 @@ class LiveManager { | |||
268 | sessionId, | 279 | sessionId, |
269 | videoLive, | 280 | videoLive, |
270 | 281 | ||
271 | inputUrl, | 282 | inputLocalUrl, |
283 | inputPublicUrl, | ||
272 | fps, | 284 | fps, |
273 | bitrate, | 285 | bitrate, |
274 | ratio, | 286 | ratio, |
@@ -281,7 +293,9 @@ class LiveManager { | |||
281 | sessionId: string | 293 | sessionId: string |
282 | videoLive: MVideoLiveVideoWithSetting | 294 | videoLive: MVideoLiveVideoWithSetting |
283 | 295 | ||
284 | inputUrl: string | 296 | inputLocalUrl: string |
297 | inputPublicUrl: string | ||
298 | |||
285 | fps: number | 299 | fps: number |
286 | bitrate: number | 300 | bitrate: number |
287 | ratio: number | 301 | ratio: number |
@@ -303,7 +317,7 @@ class LiveManager { | |||
303 | videoLive, | 317 | videoLive, |
304 | user, | 318 | user, |
305 | 319 | ||
306 | ...pick(options, [ 'inputUrl', 'bitrate', 'ratio', 'fps', 'allResolutions', 'hasAudio' ]) | 320 | ...pick(options, [ 'inputLocalUrl', 'inputPublicUrl', 'bitrate', 'ratio', 'fps', 'allResolutions', 'hasAudio' ]) |
307 | }) | 321 | }) |
308 | 322 | ||
309 | muxingSession.on('live-ready', () => this.publishAndFederateLive(videoLive, localLTags)) | 323 | muxingSession.on('live-ready', () => this.publishAndFederateLive(videoLive, localLTags)) |
diff --git a/server/lib/live/shared/muxing-session.ts b/server/lib/live/shared/muxing-session.ts index 57e28aabf..6632499ff 100644 --- a/server/lib/live/shared/muxing-session.ts +++ b/server/lib/live/shared/muxing-session.ts | |||
@@ -62,7 +62,10 @@ class MuxingSession extends EventEmitter { | |||
62 | private readonly user: MUserId | 62 | private readonly user: MUserId |
63 | private readonly sessionId: string | 63 | private readonly sessionId: string |
64 | private readonly videoLive: MVideoLiveVideo | 64 | private readonly videoLive: MVideoLiveVideo |
65 | private readonly inputUrl: string | 65 | |
66 | private readonly inputLocalUrl: string | ||
67 | private readonly inputPublicUrl: string | ||
68 | |||
66 | private readonly fps: number | 69 | private readonly fps: number |
67 | private readonly allResolutions: number[] | 70 | private readonly allResolutions: number[] |
68 | 71 | ||
@@ -107,7 +110,10 @@ class MuxingSession extends EventEmitter { | |||
107 | user: MUserId | 110 | user: MUserId |
108 | sessionId: string | 111 | sessionId: string |
109 | videoLive: MVideoLiveVideo | 112 | videoLive: MVideoLiveVideo |
110 | inputUrl: string | 113 | |
114 | inputLocalUrl: string | ||
115 | inputPublicUrl: string | ||
116 | |||
111 | fps: number | 117 | fps: number |
112 | bitrate: number | 118 | bitrate: number |
113 | ratio: number | 119 | ratio: number |
@@ -120,7 +126,10 @@ class MuxingSession extends EventEmitter { | |||
120 | this.user = options.user | 126 | this.user = options.user |
121 | this.sessionId = options.sessionId | 127 | this.sessionId = options.sessionId |
122 | this.videoLive = options.videoLive | 128 | this.videoLive = options.videoLive |
123 | this.inputUrl = options.inputUrl | 129 | |
130 | this.inputLocalUrl = options.inputLocalUrl | ||
131 | this.inputPublicUrl = options.inputPublicUrl | ||
132 | |||
124 | this.fps = options.fps | 133 | this.fps = options.fps |
125 | 134 | ||
126 | this.bitrate = options.bitrate | 135 | this.bitrate = options.bitrate |
@@ -375,7 +384,7 @@ class MuxingSession extends EventEmitter { | |||
375 | private onTranscodedEnded () { | 384 | private onTranscodedEnded () { |
376 | this.emit('transcoding-end', ({ videoUUID: this.videoUUID })) | 385 | this.emit('transcoding-end', ({ videoUUID: this.videoUUID })) |
377 | 386 | ||
378 | logger.info('RTMP transmuxing for video %s ended. Scheduling cleanup', this.inputUrl, this.lTags()) | 387 | logger.info('RTMP transmuxing for video %s ended. Scheduling cleanup', this.inputLocalUrl, this.lTags()) |
379 | 388 | ||
380 | setTimeout(() => { | 389 | setTimeout(() => { |
381 | // Wait latest segments generation, and close watchers | 390 | // Wait latest segments generation, and close watchers |
@@ -468,7 +477,8 @@ class MuxingSession extends EventEmitter { | |||
468 | 477 | ||
469 | lTags: this.lTags, | 478 | lTags: this.lTags, |
470 | 479 | ||
471 | inputUrl: this.inputUrl, | 480 | inputLocalUrl: this.inputLocalUrl, |
481 | inputPublicUrl: this.inputPublicUrl, | ||
472 | 482 | ||
473 | toTranscode: this.allResolutions.map(resolution => ({ | 483 | toTranscode: this.allResolutions.map(resolution => ({ |
474 | resolution, | 484 | resolution, |
diff --git a/server/lib/live/shared/transcoding-wrapper/abstract-transcoding-wrapper.ts b/server/lib/live/shared/transcoding-wrapper/abstract-transcoding-wrapper.ts index 226ba4573..ee61d7690 100644 --- a/server/lib/live/shared/transcoding-wrapper/abstract-transcoding-wrapper.ts +++ b/server/lib/live/shared/transcoding-wrapper/abstract-transcoding-wrapper.ts | |||
@@ -25,7 +25,9 @@ interface AbstractTranscodingWrapperOptions { | |||
25 | 25 | ||
26 | lTags: LoggerTagsFn | 26 | lTags: LoggerTagsFn |
27 | 27 | ||
28 | inputUrl: string | 28 | inputLocalUrl: string |
29 | inputPublicUrl: string | ||
30 | |||
29 | fps: number | 31 | fps: number |
30 | toTranscode: { | 32 | toTranscode: { |
31 | resolution: number | 33 | resolution: number |
@@ -50,7 +52,9 @@ abstract class AbstractTranscodingWrapper extends EventEmitter { | |||
50 | fps: number | 52 | fps: number |
51 | }[] | 53 | }[] |
52 | 54 | ||
53 | protected readonly inputUrl: string | 55 | protected readonly inputLocalUrl: string |
56 | protected readonly inputPublicUrl: string | ||
57 | |||
54 | protected readonly fps: number | 58 | protected readonly fps: number |
55 | protected readonly bitrate: number | 59 | protected readonly bitrate: number |
56 | protected readonly ratio: number | 60 | protected readonly ratio: number |
@@ -76,7 +80,9 @@ abstract class AbstractTranscodingWrapper extends EventEmitter { | |||
76 | this.videoUUID = options.videoLive.Video.uuid | 80 | this.videoUUID = options.videoLive.Video.uuid |
77 | this.streamingPlaylist = options.streamingPlaylist | 81 | this.streamingPlaylist = options.streamingPlaylist |
78 | 82 | ||
79 | this.inputUrl = options.inputUrl | 83 | this.inputLocalUrl = options.inputLocalUrl |
84 | this.inputPublicUrl = options.inputPublicUrl | ||
85 | |||
80 | this.fps = options.fps | 86 | this.fps = options.fps |
81 | this.toTranscode = options.toTranscode | 87 | this.toTranscode = options.toTranscode |
82 | 88 | ||
diff --git a/server/lib/live/shared/transcoding-wrapper/ffmpeg-transcoding-wrapper.ts b/server/lib/live/shared/transcoding-wrapper/ffmpeg-transcoding-wrapper.ts index 1f4c12bd4..c82970b88 100644 --- a/server/lib/live/shared/transcoding-wrapper/ffmpeg-transcoding-wrapper.ts +++ b/server/lib/live/shared/transcoding-wrapper/ffmpeg-transcoding-wrapper.ts | |||
@@ -15,7 +15,7 @@ export class FFmpegTranscodingWrapper extends AbstractTranscodingWrapper { | |||
15 | async run () { | 15 | async run () { |
16 | this.ffmpegCommand = CONFIG.LIVE.TRANSCODING.ENABLED | 16 | this.ffmpegCommand = CONFIG.LIVE.TRANSCODING.ENABLED |
17 | ? await this.buildFFmpegLive().getLiveTranscodingCommand({ | 17 | ? await this.buildFFmpegLive().getLiveTranscodingCommand({ |
18 | inputUrl: this.inputUrl, | 18 | inputUrl: this.inputLocalUrl, |
19 | 19 | ||
20 | outPath: this.outDirectory, | 20 | outPath: this.outDirectory, |
21 | masterPlaylistName: this.streamingPlaylist.playlistFilename, | 21 | masterPlaylistName: this.streamingPlaylist.playlistFilename, |
@@ -31,7 +31,7 @@ export class FFmpegTranscodingWrapper extends AbstractTranscodingWrapper { | |||
31 | hasAudio: this.hasAudio | 31 | hasAudio: this.hasAudio |
32 | }) | 32 | }) |
33 | : this.buildFFmpegLive().getLiveMuxingCommand({ | 33 | : this.buildFFmpegLive().getLiveMuxingCommand({ |
34 | inputUrl: this.inputUrl, | 34 | inputUrl: this.inputLocalUrl, |
35 | outPath: this.outDirectory, | 35 | outPath: this.outDirectory, |
36 | 36 | ||
37 | masterPlaylistName: this.streamingPlaylist.playlistFilename, | 37 | masterPlaylistName: this.streamingPlaylist.playlistFilename, |
diff --git a/server/lib/live/shared/transcoding-wrapper/remote-transcoding-wrapper.ts b/server/lib/live/shared/transcoding-wrapper/remote-transcoding-wrapper.ts index 345eaf442..6770a5e6f 100644 --- a/server/lib/live/shared/transcoding-wrapper/remote-transcoding-wrapper.ts +++ b/server/lib/live/shared/transcoding-wrapper/remote-transcoding-wrapper.ts | |||
@@ -4,7 +4,7 @@ import { AbstractTranscodingWrapper } from './abstract-transcoding-wrapper' | |||
4 | export class RemoteTranscodingWrapper extends AbstractTranscodingWrapper { | 4 | export class RemoteTranscodingWrapper extends AbstractTranscodingWrapper { |
5 | async run () { | 5 | async run () { |
6 | await new LiveRTMPHLSTranscodingJobHandler().create({ | 6 | await new LiveRTMPHLSTranscodingJobHandler().create({ |
7 | rtmpUrl: this.inputUrl, | 7 | rtmpUrl: this.inputPublicUrl, |
8 | toTranscode: this.toTranscode, | 8 | toTranscode: this.toTranscode, |
9 | video: this.videoLive.Video, | 9 | video: this.videoLive.Video, |
10 | outputDirectory: this.outDirectory, | 10 | outputDirectory: this.outDirectory, |
diff --git a/server/models/video/video-live.ts b/server/models/video/video-live.ts index 1acf9cbf3..ca1118641 100644 --- a/server/models/video/video-live.ts +++ b/server/models/video/video-live.ts | |||
@@ -159,11 +159,11 @@ export class VideoLiveModel extends Model<Partial<AttributesOnly<VideoLiveModel> | |||
159 | streamKey: this.streamKey, | 159 | streamKey: this.streamKey, |
160 | 160 | ||
161 | rtmpUrl: CONFIG.LIVE.RTMP.ENABLED | 161 | rtmpUrl: CONFIG.LIVE.RTMP.ENABLED |
162 | ? WEBSERVER.RTMP_URL | 162 | ? WEBSERVER.RTMP_BASE_LIVE_URL |
163 | : null, | 163 | : null, |
164 | 164 | ||
165 | rtmpsUrl: CONFIG.LIVE.RTMPS.ENABLED | 165 | rtmpsUrl: CONFIG.LIVE.RTMPS.ENABLED |
166 | ? WEBSERVER.RTMPS_URL | 166 | ? WEBSERVER.RTMPS_BASE_LIVE_URL |
167 | : null | 167 | : null |
168 | } | 168 | } |
169 | } | 169 | } |