"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.processVideoLiveEnding = void 0;
const tslib_1 = require("tslib");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const ffmpeg_1 = require("../../../helpers/ffmpeg");
const url_1 = require("../../activitypub/url");
const videos_1 = require("../../activitypub/videos");
const live_1 = require("../../live");
const paths_1 = require("../../paths");
const thumbnail_1 = require("../../thumbnail");
const transcoding_1 = require("../../transcoding/transcoding");
const video_state_1 = require("../../video-state");
const video_1 = require("../../../models/video/video");
const video_blacklist_1 = require("../../../models/video/video-blacklist");
const video_file_1 = require("../../../models/video/video-file");
const video_live_1 = require("../../../models/video/video-live");
const video_live_session_1 = require("../../../models/video/video-live-session");
const video_streaming_playlist_1 = require("../../../models/video/video-streaming-playlist");
const logger_1 = require("../../../helpers/logger");
const video_path_manager_1 = require("../../video-path-manager");
const lTags = (0, logger_1.loggerTagsFactory)('live', 'job');
function processVideoLiveEnding(job) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const payload = job.data;
        logger_1.logger.info('Processing video live ending for %s.', payload.videoId, Object.assign({ payload }, lTags()));
        function logError() {
            logger_1.logger.warn('Video live %d does not exist anymore. Cannot process live ending.', payload.videoId, lTags());
        }
        const video = yield video_1.VideoModel.load(payload.videoId);
        const live = yield video_live_1.VideoLiveModel.loadByVideoId(payload.videoId);
        const liveSession = yield video_live_session_1.VideoLiveSessionModel.load(payload.liveSessionId);
        if (!video || !live || !liveSession) {
            logError();
            return;
        }
        const permanentLive = live.permanentLive;
        liveSession.endingProcessed = true;
        yield liveSession.save();
        if (liveSession.saveReplay !== true) {
            return cleanupLiveAndFederate({ permanentLive, video, streamingPlaylistId: payload.streamingPlaylistId });
        }
        if (permanentLive) {
            yield saveReplayToExternalVideo({
                liveVideo: video,
                liveSession,
                publishedAt: payload.publishedAt,
                replayDirectory: payload.replayDirectory
            });
            return cleanupLiveAndFederate({ permanentLive, video, streamingPlaylistId: payload.streamingPlaylistId });
        }
        return replaceLiveByReplay({ video, liveSession, live, permanentLive, replayDirectory: payload.replayDirectory });
    });
}
exports.processVideoLiveEnding = processVideoLiveEnding;
function saveReplayToExternalVideo(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { liveVideo, liveSession, publishedAt, replayDirectory } = options;
        const replayVideo = new video_1.VideoModel({
            name: `${liveVideo.name} - ${new Date(publishedAt).toLocaleString()}`,
            isLive: false,
            state: 2,
            duration: 0,
            remote: liveVideo.remote,
            category: liveVideo.category,
            licence: liveVideo.licence,
            language: liveVideo.language,
            commentsEnabled: liveVideo.commentsEnabled,
            downloadEnabled: liveVideo.downloadEnabled,
            waitTranscoding: true,
            nsfw: liveVideo.nsfw,
            description: liveVideo.description,
            support: liveVideo.support,
            privacy: liveVideo.privacy,
            channelId: liveVideo.channelId
        });
        replayVideo.Thumbnails = [];
        replayVideo.VideoFiles = [];
        replayVideo.VideoStreamingPlaylists = [];
        replayVideo.url = (0, url_1.getLocalVideoActivityPubUrl)(replayVideo);
        yield replayVideo.save();
        liveSession.replayVideoId = replayVideo.id;
        yield liveSession.save();
        const blacklist = yield video_blacklist_1.VideoBlacklistModel.loadByVideoId(liveVideo.id);
        if (blacklist) {
            yield video_blacklist_1.VideoBlacklistModel.create({
                videoId: replayVideo.id,
                unfederated: blacklist.unfederated,
                reason: blacklist.reason,
                type: blacklist.type
            });
        }
        yield assignReplayFilesToVideo({ video: replayVideo, replayDirectory });
        yield (0, fs_extra_1.remove)(replayDirectory);
        for (const type of [1, 2]) {
            const image = yield (0, thumbnail_1.generateVideoMiniature)({ video: replayVideo, videoFile: replayVideo.getMaxQualityFile(), type });
            yield replayVideo.addAndSaveThumbnail(image);
        }
        yield (0, video_state_1.moveToNextState)({ video: replayVideo, isNewVideo: true });
    });
}
function replaceLiveByReplay(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { video, liveSession, live, permanentLive, replayDirectory } = options;
        const videoWithFiles = yield video_1.VideoModel.loadFull(video.id);
        const hlsPlaylist = videoWithFiles.getHLSPlaylist();
        yield (0, live_1.cleanupTMPLiveFiles)(videoWithFiles, hlsPlaylist);
        yield live.destroy();
        videoWithFiles.isLive = false;
        videoWithFiles.waitTranscoding = true;
        videoWithFiles.state = 2;
        yield videoWithFiles.save();
        liveSession.replayVideoId = videoWithFiles.id;
        yield liveSession.save();
        yield video_file_1.VideoFileModel.removeHLSFilesOfVideoId(hlsPlaylist.id);
        hlsPlaylist.VideoFiles = [];
        hlsPlaylist.playlistFilename = (0, paths_1.generateHLSMasterPlaylistFilename)();
        hlsPlaylist.segmentsSha256Filename = (0, paths_1.generateHlsSha256SegmentsFilename)();
        yield hlsPlaylist.save();
        yield assignReplayFilesToVideo({ video: videoWithFiles, replayDirectory });
        if (permanentLive) {
            yield (0, fs_extra_1.remove)(replayDirectory);
        }
        else {
            yield (0, fs_extra_1.remove)((0, paths_1.getLiveReplayBaseDirectory)(videoWithFiles));
        }
        if (videoWithFiles.getMiniature().automaticallyGenerated === true) {
            const miniature = yield (0, thumbnail_1.generateVideoMiniature)({
                video: videoWithFiles,
                videoFile: videoWithFiles.getMaxQualityFile(),
                type: 1
            });
            yield videoWithFiles.addAndSaveThumbnail(miniature);
        }
        if (videoWithFiles.getPreview().automaticallyGenerated === true) {
            const preview = yield (0, thumbnail_1.generateVideoMiniature)({
                video: videoWithFiles,
                videoFile: videoWithFiles.getMaxQualityFile(),
                type: 2
            });
            yield videoWithFiles.addAndSaveThumbnail(preview);
        }
        yield (0, video_state_1.moveToNextState)({ video: videoWithFiles, isNewVideo: true });
    });
}
function assignReplayFilesToVideo(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { video, replayDirectory } = options;
        const concatenatedTsFiles = yield (0, fs_extra_1.readdir)(replayDirectory);
        for (const concatenatedTsFile of concatenatedTsFiles) {
            const inputFileMutexReleaser = yield video_path_manager_1.VideoPathManager.Instance.lockFiles(video.uuid);
            const concatenatedTsFilePath = (0, path_1.join)(replayDirectory, concatenatedTsFile);
            const probe = yield (0, ffmpeg_1.ffprobePromise)(concatenatedTsFilePath);
            const { audioStream } = yield (0, ffmpeg_1.getAudioStream)(concatenatedTsFilePath, probe);
            const { resolution } = yield (0, ffmpeg_1.getVideoStreamDimensionsInfo)(concatenatedTsFilePath, probe);
            try {
                yield (0, transcoding_1.generateHlsPlaylistResolutionFromTS)({
                    video,
                    inputFileMutexReleaser,
                    concatenatedTsFilePath,
                    resolution,
                    isAAC: (audioStream === null || audioStream === void 0 ? void 0 : audioStream.codec_name) === 'aac'
                });
            }
            catch (err) {
                logger_1.logger.error('Cannot generate HLS playlist resolution from TS files.', { err });
            }
            inputFileMutexReleaser();
        }
        return video;
    });
}
function cleanupLiveAndFederate(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { permanentLive, video, streamingPlaylistId } = options;
        const streamingPlaylist = yield video_streaming_playlist_1.VideoStreamingPlaylistModel.loadWithVideo(streamingPlaylistId);
        if (streamingPlaylist) {
            if (permanentLive) {
                yield (0, live_1.cleanupAndDestroyPermanentLive)(video, streamingPlaylist);
            }
            else {
                yield (0, live_1.cleanupUnsavedNormalLive)(video, streamingPlaylist);
            }
        }
        try {
            const fullVideo = yield video_1.VideoModel.loadFull(video.id);
            return (0, videos_1.federateVideoIfNeeded)(fullVideo, false, undefined);
        }
        catch (err) {
            logger_1.logger.warn('Cannot federate live after cleanup', { videoId: video.id, err });
        }
    });
}
//# sourceMappingURL=video-live-ending.js.map