+// Run encoder builder depending on available encoders
+// Try encoders by priority: if the encoder is available, run the chosen profile or fallback to the default one
+// If the default one does not exist, check the next encoder
+async function getEncoderBuilderResult (options: EncoderOptionsBuilderParams & {
+ streamType: 'video' | 'audio'
+ input: string
+
+ availableEncoders: AvailableEncoders
+ profile: string
+
+ videoType: 'vod' | 'live'
+}) {
+ const { availableEncoders, profile, streamType, videoType } = options
+
+ const encodersToTry = availableEncoders.encodersToTry[videoType][streamType]
+ const encoders = availableEncoders.available[videoType]
+
+ for (const encoder of encodersToTry) {
+ if (!(await checkFFmpegEncoders(availableEncoders)).get(encoder)) {
+ logger.debug('Encoder %s not available in ffmpeg, skipping.', encoder, lTags())
+ continue
+ }
+
+ if (!encoders[encoder]) {
+ logger.debug('Encoder %s not available in peertube encoders, skipping.', encoder, lTags())
+ continue
+ }
+
+ // An object containing available profiles for this encoder
+ const builderProfiles: EncoderProfile<EncoderOptionsBuilder> = encoders[encoder]
+ let builder = builderProfiles[profile]
+
+ if (!builder) {
+ logger.debug('Profile %s for encoder %s not available. Fallback to default.', profile, encoder, lTags())
+ builder = builderProfiles.default
+
+ if (!builder) {
+ logger.debug('Default profile for encoder %s not available. Try next available encoder.', encoder, lTags())
+ continue
+ }
+ }
+
+ const result = await builder(pick(options, [ 'input', 'resolution', 'inputBitrate', 'fps', 'inputRatio', 'streamNum' ]))
+
+ return {
+ result,
+
+ // If we don't have output options, then copy the input stream
+ encoder: result.copy === true
+ ? 'copy'
+ : encoder
+ }
+ }
+
+ return null
+}
+
+async function presetVideo (options: {
+ command: FfmpegCommand
+ input: string
+ transcodeOptions: TranscodeOptions