aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--server/helpers/ffmpeg/ffmpeg-live.ts24
-rw-r--r--server/lib/live/live-manager.ts29
-rw-r--r--server/lib/live/shared/muxing-session.ts7
3 files changed, 43 insertions, 17 deletions
diff --git a/server/helpers/ffmpeg/ffmpeg-live.ts b/server/helpers/ffmpeg/ffmpeg-live.ts
index 8377dc7e2..379d7b1ad 100644
--- a/server/helpers/ffmpeg/ffmpeg-live.ts
+++ b/server/helpers/ffmpeg/ffmpeg-live.ts
@@ -23,11 +23,24 @@ async function getLiveTranscodingCommand (options: {
23 fps: number 23 fps: number
24 bitrate: number 24 bitrate: number
25 ratio: number 25 ratio: number
26 hasAudio: boolean
26 27
27 availableEncoders: AvailableEncoders 28 availableEncoders: AvailableEncoders
28 profile: string 29 profile: string
29}) { 30}) {
30 const { inputUrl, outPath, resolutions, fps, bitrate, availableEncoders, profile, masterPlaylistName, ratio, latencyMode } = options 31 const {
32 inputUrl,
33 outPath,
34 resolutions,
35 fps,
36 bitrate,
37 availableEncoders,
38 profile,
39 masterPlaylistName,
40 ratio,
41 latencyMode,
42 hasAudio
43 } = options
31 44
32 const command = getFFmpeg(inputUrl, 'live') 45 const command = getFFmpeg(inputUrl, 'live')
33 46
@@ -47,6 +60,7 @@ async function getLiveTranscodingCommand (options: {
47 addDefaultEncoderGlobalParams(command) 60 addDefaultEncoderGlobalParams(command)
48 61
49 for (let i = 0; i < resolutions.length; i++) { 62 for (let i = 0; i < resolutions.length; i++) {
63 const streamMap: string[] = []
50 const resolution = resolutions[i] 64 const resolution = resolutions[i]
51 const resolutionFPS = computeFPS(fps, resolution) 65 const resolutionFPS = computeFPS(fps, resolution)
52 66
@@ -94,9 +108,11 @@ async function getLiveTranscodingCommand (options: {
94 options: `w=-2:h=${resolution}`, 108 options: `w=-2:h=${resolution}`,
95 outputs: `vout${resolution}` 109 outputs: `vout${resolution}`
96 }) 110 })
111
112 streamMap.push(`v:${i}`)
97 } 113 }
98 114
99 { 115 if (hasAudio) {
100 const streamType: StreamType = 'audio' 116 const streamType: StreamType = 'audio'
101 const builderResult = await getEncoderBuilderResult({ ...baseEncoderBuilderParams, streamType }) 117 const builderResult = await getEncoderBuilderResult({ ...baseEncoderBuilderParams, streamType })
102 if (!builderResult) { 118 if (!builderResult) {
@@ -114,9 +130,11 @@ async function getLiveTranscodingCommand (options: {
114 130
115 command.outputOption(`${buildStreamSuffix('-c:a', i)} ${builderResult.encoder}`) 131 command.outputOption(`${buildStreamSuffix('-c:a', i)} ${builderResult.encoder}`)
116 applyEncoderOptions(command, builderResult.result) 132 applyEncoderOptions(command, builderResult.result)
133
134 streamMap.push(`a:${i}`)
117 } 135 }
118 136
119 varStreamMap.push(`v:${i},a:${i}`) 137 varStreamMap.push(streamMap.join(','))
120 } 138 }
121 139
122 command.complexFilter(complexFilter) 140 command.complexFilter(complexFilter)
diff --git a/server/lib/live/live-manager.ts b/server/lib/live/live-manager.ts
index aadd8e308..16715862b 100644
--- a/server/lib/live/live-manager.ts
+++ b/server/lib/live/live-manager.ts
@@ -1,4 +1,3 @@
1
2import { readdir, readFile } from 'fs-extra' 1import { readdir, readFile } from 'fs-extra'
3import { createServer, Server } from 'net' 2import { createServer, Server } from 'net'
4import { join } from 'path' 3import { join } from 'path'
@@ -9,7 +8,8 @@ import {
9 getLiveSegmentTime, 8 getLiveSegmentTime,
10 getVideoStreamBitrate, 9 getVideoStreamBitrate,
11 getVideoStreamDimensionsInfo, 10 getVideoStreamDimensionsInfo,
12 getVideoStreamFPS 11 getVideoStreamFPS,
12 hasAudioStream
13} from '@server/helpers/ffmpeg' 13} from '@server/helpers/ffmpeg'
14import { logger, loggerTagsFactory } from '@server/helpers/logger' 14import { logger, loggerTagsFactory } from '@server/helpers/logger'
15import { CONFIG, registerConfigChangedHandler } from '@server/initializers/config' 15import { CONFIG, registerConfigChangedHandler } from '@server/initializers/config'
@@ -20,7 +20,7 @@ import { VideoLiveModel } from '@server/models/video/video-live'
20import { VideoLiveSessionModel } from '@server/models/video/video-live-session' 20import { VideoLiveSessionModel } from '@server/models/video/video-live-session'
21import { VideoStreamingPlaylistModel } from '@server/models/video/video-streaming-playlist' 21import { VideoStreamingPlaylistModel } from '@server/models/video/video-streaming-playlist'
22import { MStreamingPlaylistVideo, MVideo, MVideoLiveSession, MVideoLiveVideo } from '@server/types/models' 22import { MStreamingPlaylistVideo, MVideo, MVideoLiveSession, MVideoLiveVideo } from '@server/types/models'
23import { wait } from '@shared/core-utils' 23import { pick, wait } from '@shared/core-utils'
24import { LiveVideoError, VideoState, VideoStreamingPlaylistType } from '@shared/models' 24import { LiveVideoError, VideoState, VideoStreamingPlaylistType } from '@shared/models'
25import { federateVideoIfNeeded } from '../activitypub/videos' 25import { federateVideoIfNeeded } from '../activitypub/videos'
26import { JobQueue } from '../job-queue' 26import { JobQueue } from '../job-queue'
@@ -232,10 +232,11 @@ class LiveManager {
232 const now = Date.now() 232 const now = Date.now()
233 const probe = await ffprobePromise(inputUrl) 233 const probe = await ffprobePromise(inputUrl)
234 234
235 const [ { resolution, ratio }, fps, bitrate ] = await Promise.all([ 235 const [ { resolution, ratio }, fps, bitrate, hasAudio ] = await Promise.all([
236 getVideoStreamDimensionsInfo(inputUrl, probe), 236 getVideoStreamDimensionsInfo(inputUrl, probe),
237 getVideoStreamFPS(inputUrl, probe), 237 getVideoStreamFPS(inputUrl, probe),
238 getVideoStreamBitrate(inputUrl, probe) 238 getVideoStreamBitrate(inputUrl, probe),
239 hasAudioStream(inputUrl, probe)
239 ]) 240 ])
240 241
241 logger.info( 242 logger.info(
@@ -259,26 +260,30 @@ class LiveManager {
259 return this.runMuxingSession({ 260 return this.runMuxingSession({
260 sessionId, 261 sessionId,
261 videoLive, 262 videoLive,
263
262 streamingPlaylist, 264 streamingPlaylist,
263 inputUrl, 265 inputUrl,
264 fps, 266 fps,
265 bitrate, 267 bitrate,
266 ratio, 268 ratio,
267 allResolutions 269 allResolutions,
270 hasAudio
268 }) 271 })
269 } 272 }
270 273
271 private async runMuxingSession (options: { 274 private async runMuxingSession (options: {
272 sessionId: string 275 sessionId: string
273 videoLive: MVideoLiveVideo 276 videoLive: MVideoLiveVideo
277
274 streamingPlaylist: MStreamingPlaylistVideo 278 streamingPlaylist: MStreamingPlaylistVideo
275 inputUrl: string 279 inputUrl: string
276 fps: number 280 fps: number
277 bitrate: number 281 bitrate: number
278 ratio: number 282 ratio: number
279 allResolutions: number[] 283 allResolutions: number[]
284 hasAudio: boolean
280 }) { 285 }) {
281 const { sessionId, videoLive, streamingPlaylist, allResolutions, fps, bitrate, ratio, inputUrl } = options 286 const { sessionId, videoLive } = options
282 const videoUUID = videoLive.Video.uuid 287 const videoUUID = videoLive.Video.uuid
283 const localLTags = lTags(sessionId, videoUUID) 288 const localLTags = lTags(sessionId, videoUUID)
284 289
@@ -289,15 +294,11 @@ class LiveManager {
289 294
290 const muxingSession = new MuxingSession({ 295 const muxingSession = new MuxingSession({
291 context: this.getContext(), 296 context: this.getContext(),
292 user,
293 sessionId, 297 sessionId,
294 videoLive, 298 videoLive,
295 streamingPlaylist, 299 user,
296 inputUrl, 300
297 bitrate, 301 ...pick(options, [ 'streamingPlaylist', 'inputUrl', 'bitrate', 'ratio', 'fps', 'allResolutions', 'hasAudio' ])
298 ratio,
299 fps,
300 allResolutions
301 }) 302 })
302 303
303 muxingSession.on('master-playlist-created', () => this.publishAndFederateLive(videoLive, localLTags)) 304 muxingSession.on('master-playlist-created', () => this.publishAndFederateLive(videoLive, localLTags))
diff --git a/server/lib/live/shared/muxing-session.ts b/server/lib/live/shared/muxing-session.ts
index 310a7026d..505717dce 100644
--- a/server/lib/live/shared/muxing-session.ts
+++ b/server/lib/live/shared/muxing-session.ts
@@ -59,6 +59,8 @@ class MuxingSession extends EventEmitter {
59 private readonly bitrate: number 59 private readonly bitrate: number
60 private readonly ratio: number 60 private readonly ratio: number
61 61
62 private readonly hasAudio: boolean
63
62 private readonly videoId: number 64 private readonly videoId: number
63 private readonly videoUUID: string 65 private readonly videoUUID: string
64 private readonly saveReplay: boolean 66 private readonly saveReplay: boolean
@@ -94,6 +96,7 @@ class MuxingSession extends EventEmitter {
94 bitrate: number 96 bitrate: number
95 ratio: number 97 ratio: number
96 allResolutions: number[] 98 allResolutions: number[]
99 hasAudio: boolean
97 }) { 100 }) {
98 super() 101 super()
99 102
@@ -108,6 +111,8 @@ class MuxingSession extends EventEmitter {
108 this.bitrate = options.bitrate 111 this.bitrate = options.bitrate
109 this.ratio = options.ratio 112 this.ratio = options.ratio
110 113
114 this.hasAudio = options.hasAudio
115
111 this.allResolutions = options.allResolutions 116 this.allResolutions = options.allResolutions
112 117
113 this.videoId = this.videoLive.Video.id 118 this.videoId = this.videoLive.Video.id
@@ -140,6 +145,8 @@ class MuxingSession extends EventEmitter {
140 bitrate: this.bitrate, 145 bitrate: this.bitrate,
141 ratio: this.ratio, 146 ratio: this.ratio,
142 147
148 hasAudio: this.hasAudio,
149
143 availableEncoders: VideoTranscodingProfilesManager.Instance.getAvailableEncoders(), 150 availableEncoders: VideoTranscodingProfilesManager.Instance.getAvailableEncoders(),
144 profile: CONFIG.LIVE.TRANSCODING.PROFILE 151 profile: CONFIG.LIVE.TRANSCODING.PROFILE
145 }) 152 })