diff options
Diffstat (limited to 'server/helpers')
-rw-r--r-- | server/helpers/activitypub.ts | 4 | ||||
-rw-r--r-- | server/helpers/custom-validators/activitypub/videos.ts | 4 | ||||
-rw-r--r-- | server/helpers/custom-validators/video-lives.ts | 11 | ||||
-rw-r--r-- | server/helpers/ffmpeg/ffmpeg-live.ts | 39 |
4 files changed, 50 insertions, 8 deletions
diff --git a/server/helpers/activitypub.ts b/server/helpers/activitypub.ts index cbba2f51c..d0bcc6785 100644 --- a/server/helpers/activitypub.ts +++ b/server/helpers/activitypub.ts | |||
@@ -50,6 +50,10 @@ function getContextData (type: ContextType) { | |||
50 | '@type': 'sc:Boolean', | 50 | '@type': 'sc:Boolean', |
51 | '@id': 'pt:permanentLive' | 51 | '@id': 'pt:permanentLive' |
52 | }, | 52 | }, |
53 | latencyMode: { | ||
54 | '@type': 'sc:Number', | ||
55 | '@id': 'pt:latencyMode' | ||
56 | }, | ||
53 | 57 | ||
54 | Infohash: 'pt:Infohash', | 58 | Infohash: 'pt:Infohash', |
55 | Playlist: 'pt:Playlist', | 59 | Playlist: 'pt:Playlist', |
diff --git a/server/helpers/custom-validators/activitypub/videos.ts b/server/helpers/custom-validators/activitypub/videos.ts index a41d37810..80a321117 100644 --- a/server/helpers/custom-validators/activitypub/videos.ts +++ b/server/helpers/custom-validators/activitypub/videos.ts | |||
@@ -1,10 +1,11 @@ | |||
1 | import validator from 'validator' | 1 | import validator from 'validator' |
2 | import { logger } from '@server/helpers/logger' | 2 | import { logger } from '@server/helpers/logger' |
3 | import { ActivityTrackerUrlObject, ActivityVideoFileMetadataUrlObject } from '@shared/models' | 3 | import { ActivityTrackerUrlObject, ActivityVideoFileMetadataUrlObject } from '@shared/models' |
4 | import { VideoState } from '../../../../shared/models/videos' | 4 | import { LiveVideoLatencyMode, VideoState } from '../../../../shared/models/videos' |
5 | import { ACTIVITY_PUB, CONSTRAINTS_FIELDS } from '../../../initializers/constants' | 5 | import { ACTIVITY_PUB, CONSTRAINTS_FIELDS } from '../../../initializers/constants' |
6 | import { peertubeTruncate } from '../../core-utils' | 6 | import { peertubeTruncate } from '../../core-utils' |
7 | import { exists, isArray, isBooleanValid, isDateValid, isUUIDValid } from '../misc' | 7 | import { exists, isArray, isBooleanValid, isDateValid, isUUIDValid } from '../misc' |
8 | import { isLiveLatencyModeValid } from '../video-lives' | ||
8 | import { | 9 | import { |
9 | isVideoDurationValid, | 10 | isVideoDurationValid, |
10 | isVideoNameValid, | 11 | isVideoNameValid, |
@@ -65,6 +66,7 @@ function sanitizeAndCheckVideoTorrentObject (video: any) { | |||
65 | if (!isBooleanValid(video.isLiveBroadcast)) video.isLiveBroadcast = false | 66 | if (!isBooleanValid(video.isLiveBroadcast)) video.isLiveBroadcast = false |
66 | if (!isBooleanValid(video.liveSaveReplay)) video.liveSaveReplay = false | 67 | if (!isBooleanValid(video.liveSaveReplay)) video.liveSaveReplay = false |
67 | if (!isBooleanValid(video.permanentLive)) video.permanentLive = false | 68 | if (!isBooleanValid(video.permanentLive)) video.permanentLive = false |
69 | if (!isLiveLatencyModeValid(video.latencyMode)) video.latencyMode = LiveVideoLatencyMode.DEFAULT | ||
68 | 70 | ||
69 | return isActivityPubUrlValid(video.id) && | 71 | return isActivityPubUrlValid(video.id) && |
70 | isVideoNameValid(video.name) && | 72 | isVideoNameValid(video.name) && |
diff --git a/server/helpers/custom-validators/video-lives.ts b/server/helpers/custom-validators/video-lives.ts new file mode 100644 index 000000000..69d08ae68 --- /dev/null +++ b/server/helpers/custom-validators/video-lives.ts | |||
@@ -0,0 +1,11 @@ | |||
1 | import { LiveVideoLatencyMode } from '@shared/models' | ||
2 | |||
3 | function isLiveLatencyModeValid (value: any) { | ||
4 | return [ LiveVideoLatencyMode.DEFAULT, LiveVideoLatencyMode.SMALL_LATENCY, LiveVideoLatencyMode.HIGH_LATENCY ].includes(value) | ||
5 | } | ||
6 | |||
7 | // --------------------------------------------------------------------------- | ||
8 | |||
9 | export { | ||
10 | isLiveLatencyModeValid | ||
11 | } | ||
diff --git a/server/helpers/ffmpeg/ffmpeg-live.ts b/server/helpers/ffmpeg/ffmpeg-live.ts index ff571626c..fd20971eb 100644 --- a/server/helpers/ffmpeg/ffmpeg-live.ts +++ b/server/helpers/ffmpeg/ffmpeg-live.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import { FfmpegCommand, FilterSpecification } from 'fluent-ffmpeg' | 1 | import { FfmpegCommand, FilterSpecification } from 'fluent-ffmpeg' |
2 | import { join } from 'path' | 2 | import { join } from 'path' |
3 | import { VIDEO_LIVE } from '@server/initializers/constants' | 3 | import { VIDEO_LIVE } from '@server/initializers/constants' |
4 | import { AvailableEncoders } from '@shared/models' | 4 | import { AvailableEncoders, LiveVideoLatencyMode } from '@shared/models' |
5 | import { logger, loggerTagsFactory } from '../logger' | 5 | import { logger, loggerTagsFactory } from '../logger' |
6 | import { buildStreamSuffix, getFFmpeg, getScaleFilter, StreamType } from './ffmpeg-commons' | 6 | import { buildStreamSuffix, getFFmpeg, getScaleFilter, StreamType } from './ffmpeg-commons' |
7 | import { getEncoderBuilderResult } from './ffmpeg-encoders' | 7 | import { getEncoderBuilderResult } from './ffmpeg-encoders' |
@@ -15,6 +15,7 @@ async function getLiveTranscodingCommand (options: { | |||
15 | 15 | ||
16 | outPath: string | 16 | outPath: string |
17 | masterPlaylistName: string | 17 | masterPlaylistName: string |
18 | latencyMode: LiveVideoLatencyMode | ||
18 | 19 | ||
19 | resolutions: number[] | 20 | resolutions: number[] |
20 | 21 | ||
@@ -26,7 +27,7 @@ async function getLiveTranscodingCommand (options: { | |||
26 | availableEncoders: AvailableEncoders | 27 | availableEncoders: AvailableEncoders |
27 | profile: string | 28 | profile: string |
28 | }) { | 29 | }) { |
29 | const { inputUrl, outPath, resolutions, fps, bitrate, availableEncoders, profile, masterPlaylistName, ratio } = options | 30 | const { inputUrl, outPath, resolutions, fps, bitrate, availableEncoders, profile, masterPlaylistName, ratio, latencyMode } = options |
30 | 31 | ||
31 | const command = getFFmpeg(inputUrl, 'live') | 32 | const command = getFFmpeg(inputUrl, 'live') |
32 | 33 | ||
@@ -120,14 +121,21 @@ async function getLiveTranscodingCommand (options: { | |||
120 | 121 | ||
121 | command.complexFilter(complexFilter) | 122 | command.complexFilter(complexFilter) |
122 | 123 | ||
123 | addDefaultLiveHLSParams(command, outPath, masterPlaylistName) | 124 | addDefaultLiveHLSParams({ command, outPath, masterPlaylistName, latencyMode }) |
124 | 125 | ||
125 | command.outputOption('-var_stream_map', varStreamMap.join(' ')) | 126 | command.outputOption('-var_stream_map', varStreamMap.join(' ')) |
126 | 127 | ||
127 | return command | 128 | return command |
128 | } | 129 | } |
129 | 130 | ||
130 | function getLiveMuxingCommand (inputUrl: string, outPath: string, masterPlaylistName: string) { | 131 | function getLiveMuxingCommand (options: { |
132 | inputUrl: string | ||
133 | outPath: string | ||
134 | masterPlaylistName: string | ||
135 | latencyMode: LiveVideoLatencyMode | ||
136 | }) { | ||
137 | const { inputUrl, outPath, masterPlaylistName, latencyMode } = options | ||
138 | |||
131 | const command = getFFmpeg(inputUrl, 'live') | 139 | const command = getFFmpeg(inputUrl, 'live') |
132 | 140 | ||
133 | command.outputOption('-c:v copy') | 141 | command.outputOption('-c:v copy') |
@@ -135,22 +143,39 @@ function getLiveMuxingCommand (inputUrl: string, outPath: string, masterPlaylist | |||
135 | command.outputOption('-map 0:a?') | 143 | command.outputOption('-map 0:a?') |
136 | command.outputOption('-map 0:v?') | 144 | command.outputOption('-map 0:v?') |
137 | 145 | ||
138 | addDefaultLiveHLSParams(command, outPath, masterPlaylistName) | 146 | addDefaultLiveHLSParams({ command, outPath, masterPlaylistName, latencyMode }) |
139 | 147 | ||
140 | return command | 148 | return command |
141 | } | 149 | } |
142 | 150 | ||
151 | function getLiveSegmentTime (latencyMode: LiveVideoLatencyMode) { | ||
152 | if (latencyMode === LiveVideoLatencyMode.SMALL_LATENCY) { | ||
153 | return VIDEO_LIVE.SEGMENT_TIME_SECONDS.SMALL_LATENCY | ||
154 | } | ||
155 | |||
156 | return VIDEO_LIVE.SEGMENT_TIME_SECONDS.DEFAULT_LATENCY | ||
157 | } | ||
158 | |||
143 | // --------------------------------------------------------------------------- | 159 | // --------------------------------------------------------------------------- |
144 | 160 | ||
145 | export { | 161 | export { |
162 | getLiveSegmentTime, | ||
163 | |||
146 | getLiveTranscodingCommand, | 164 | getLiveTranscodingCommand, |
147 | getLiveMuxingCommand | 165 | getLiveMuxingCommand |
148 | } | 166 | } |
149 | 167 | ||
150 | // --------------------------------------------------------------------------- | 168 | // --------------------------------------------------------------------------- |
151 | 169 | ||
152 | function addDefaultLiveHLSParams (command: FfmpegCommand, outPath: string, masterPlaylistName: string) { | 170 | function addDefaultLiveHLSParams (options: { |
153 | command.outputOption('-hls_time ' + VIDEO_LIVE.SEGMENT_TIME_SECONDS) | 171 | command: FfmpegCommand |
172 | outPath: string | ||
173 | masterPlaylistName: string | ||
174 | latencyMode: LiveVideoLatencyMode | ||
175 | }) { | ||
176 | const { command, outPath, masterPlaylistName, latencyMode } = options | ||
177 | |||
178 | command.outputOption('-hls_time ' + getLiveSegmentTime(latencyMode)) | ||
154 | command.outputOption('-hls_list_size ' + VIDEO_LIVE.SEGMENTS_LIST_SIZE) | 179 | command.outputOption('-hls_list_size ' + VIDEO_LIVE.SEGMENTS_LIST_SIZE) |
155 | command.outputOption('-hls_flags delete_segments+independent_segments') | 180 | command.outputOption('-hls_flags delete_segments+independent_segments') |
156 | command.outputOption(`-hls_segment_filename ${join(outPath, '%v-%06d.ts')}`) | 181 | command.outputOption(`-hls_segment_filename ${join(outPath, '%v-%06d.ts')}`) |