"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildVODCommand = exports.transcodeVOD = void 0;
const tslib_1 = require("tslib");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const constants_1 = require("../../initializers/constants");
const core_utils_1 = require("../../../shared/core-utils");
const logger_1 = require("../logger");
const ffmpeg_commons_1 = require("./ffmpeg-commons");
const ffmpeg_presets_1 = require("./ffmpeg-presets");
const ffprobe_utils_1 = require("./ffprobe-utils");
const lTags = (0, logger_1.loggerTagsFactory)('ffmpeg');
const builders = {
    'quick-transcode': buildQuickTranscodeCommand,
    'hls': buildHLSVODCommand,
    'hls-from-ts': buildHLSVODFromTSCommand,
    'merge-audio': buildAudioMergeCommand,
    'only-audio': buildOnlyAudioCommand,
    'video': buildVODCommand
};
function transcodeVOD(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        logger_1.logger.debug('Will run transcode.', Object.assign({ options }, lTags()));
        let command = (0, ffmpeg_commons_1.getFFmpeg)(options.inputPath, 'vod')
            .output(options.outputPath);
        command = yield builders[options.type](command, options);
        command.on('start', () => {
            setTimeout(() => {
                options.inputFileMutexReleaser();
            }, 1000);
        });
        yield (0, ffmpeg_commons_1.runCommand)({ command, job: options.job });
        yield fixHLSPlaylistIfNeeded(options);
    });
}
exports.transcodeVOD = transcodeVOD;
function buildVODCommand(command, options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const probe = yield (0, ffprobe_utils_1.ffprobePromise)(options.inputPath);
        let fps = yield (0, ffprobe_utils_1.getVideoStreamFPS)(options.inputPath, probe);
        fps = (0, ffprobe_utils_1.computeFPS)(fps, options.resolution);
        let scaleFilterValue;
        if (options.resolution !== undefined) {
            const videoStreamInfo = yield (0, ffprobe_utils_1.getVideoStreamDimensionsInfo)(options.inputPath, probe);
            scaleFilterValue = (videoStreamInfo === null || videoStreamInfo === void 0 ? void 0 : videoStreamInfo.isPortraitMode) === true
                ? `w=${options.resolution}:h=-2`
                : `w=-2:h=${options.resolution}`;
        }
        command = yield (0, ffmpeg_presets_1.presetVOD)(Object.assign(Object.assign({}, (0, core_utils_1.pick)(options, ['resolution', 'availableEncoders', 'profile'])), { command, input: options.inputPath, canCopyAudio: true, canCopyVideo: true, fps,
            scaleFilterValue }));
        return command;
    });
}
exports.buildVODCommand = buildVODCommand;
function buildQuickTranscodeCommand(command) {
    command = (0, ffmpeg_presets_1.presetCopy)(command);
    command = command.outputOption('-map_metadata -1')
        .outputOption('-movflags faststart');
    return command;
}
function buildAudioMergeCommand(command, options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        command = command.loop(undefined);
        const scaleFilterValue = getMergeAudioScaleFilterValue();
        command = yield (0, ffmpeg_presets_1.presetVOD)(Object.assign(Object.assign({}, (0, core_utils_1.pick)(options, ['resolution', 'availableEncoders', 'profile'])), { command, input: options.audioPath, canCopyAudio: true, canCopyVideo: true, fps: constants_1.VIDEO_TRANSCODING_FPS.AUDIO_MERGE, scaleFilterValue }));
        command.outputOption('-preset:v veryfast');
        command = command.input(options.audioPath)
            .outputOption('-tune stillimage')
            .outputOption('-shortest');
        return command;
    });
}
function buildOnlyAudioCommand(command, _options) {
    command = (0, ffmpeg_presets_1.presetOnlyAudio)(command);
    return command;
}
function buildHLSVODCommand(command, options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const videoPath = getHLSVideoPath(options);
        if (options.copyCodecs)
            command = (0, ffmpeg_presets_1.presetCopy)(command);
        else if (options.resolution === 0)
            command = (0, ffmpeg_presets_1.presetOnlyAudio)(command);
        else
            command = yield buildVODCommand(command, options);
        addCommonHLSVODCommandOptions(command, videoPath);
        return command;
    });
}
function buildHLSVODFromTSCommand(command, options) {
    const videoPath = getHLSVideoPath(options);
    command.outputOption('-c copy');
    if (options.isAAC) {
        command.outputOption('-bsf:a aac_adtstoasc');
    }
    addCommonHLSVODCommandOptions(command, videoPath);
    return command;
}
function addCommonHLSVODCommandOptions(command, outputPath) {
    return command.outputOption('-hls_time 4')
        .outputOption('-hls_list_size 0')
        .outputOption('-hls_playlist_type vod')
        .outputOption('-hls_segment_filename ' + outputPath)
        .outputOption('-hls_segment_type fmp4')
        .outputOption('-f hls')
        .outputOption('-hls_flags single_file');
}
function fixHLSPlaylistIfNeeded(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        if (options.type !== 'hls' && options.type !== 'hls-from-ts')
            return;
        const fileContent = yield (0, fs_extra_1.readFile)(options.outputPath);
        const videoFileName = options.hlsPlaylist.videoFilename;
        const videoFilePath = getHLSVideoPath(options);
        const newContent = fileContent.toString()
            .replace(`#EXT-X-MAP:URI="${videoFilePath}",`, `#EXT-X-MAP:URI="${videoFileName}",`);
        yield (0, fs_extra_1.writeFile)(options.outputPath, newContent);
    });
}
function getHLSVideoPath(options) {
    return `${(0, path_1.dirname)(options.outputPath)}/${options.hlsPlaylist.videoFilename}`;
}
function getMergeAudioScaleFilterValue() {
    return 'trunc(iw/2)*2:trunc(ih/2)*2';
}
//# sourceMappingURL=ffmpeg-vod.js.map