import { GraphAILogger } from "graphai";
import { FfmpegContextAddInput, FfmpegContextInit, FfmpegContextGenerateOutput, ffmpegGetMediaDuration } from "../utils/ffmpeg_utils.js";
import { MulmoStudioContextMethods } from "../methods/mulmo_studio_context.js";
import { isFile } from "../utils/file.js";
import { agentGenerationError, agentFileNotExistError, audioAction, audioFileTarget } from "../utils/error_cause.js";
export const resolveAddBgmMixParams = (audioParams) => {
    const useExplicitMix = audioParams.ttsVolume !== undefined;
    const ttsVolume = audioParams.ttsVolume ?? 1.0;
    return {
        useExplicitMix,
        voiceVolume: audioParams.audioVolume * ttsVolume,
    };
};
export const resolveAddBgmFilterConfig = (useExplicitMix) => {
    const amixNormalize = useExplicitMix ? ":normalize=0" : "";
    return {
        amixNormalize,
        mixedOutputId: useExplicitMix ? "mixed_limited" : "mixed",
        limiterFilter: useExplicitMix ? "[mixed]alimiter=limit=0.95:attack=5:release=50[mixed_limited]" : undefined,
    };
};
const addBGMAgent = async ({ namedInputs, params, }) => {
    const { voiceFile, outputFile, context } = namedInputs;
    const { musicFile } = params;
    if (!isFile(voiceFile)) {
        throw new Error(`AddBGMAgent voiceFile not exist: ${voiceFile}`, {
            cause: agentFileNotExistError("addBGMAgent", audioAction, audioFileTarget, voiceFile),
        });
    }
    if (!musicFile.match(/^http/) && !isFile(musicFile)) {
        throw new Error(`AddBGMAgent musicFile not exist: ${musicFile}`, {
            cause: agentFileNotExistError("addBGMAgent", audioAction, audioFileTarget, musicFile),
        });
    }
    const { duration: speechDuration } = await ffmpegGetMediaDuration(voiceFile);
    const introPadding = MulmoStudioContextMethods.getIntroPadding(context);
    const outroPadding = context.presentationStyle.audioParams.outroPadding;
    const totalDuration = speechDuration + introPadding + outroPadding;
    GraphAILogger.log("totalDucation:", speechDuration, totalDuration);
    const ffmpegContext = FfmpegContextInit();
    const musicInputIndex = FfmpegContextAddInput(ffmpegContext, musicFile, ["-stream_loop", "-1"]);
    const voiceInputIndex = FfmpegContextAddInput(ffmpegContext, voiceFile);
    const audioParams = context.presentationStyle.audioParams;
    const { useExplicitMix, voiceVolume } = resolveAddBgmMixParams(audioParams);
    ffmpegContext.filterComplex.push(`[${musicInputIndex}:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo, volume=${audioParams.bgmVolume}[music]`);
    ffmpegContext.filterComplex.push(`[${voiceInputIndex}:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo, volume=${voiceVolume}, adelay=${introPadding * 1000}|${introPadding * 1000}[voice]`);
    const { amixNormalize, mixedOutputId, limiterFilter } = resolveAddBgmFilterConfig(useExplicitMix);
    ffmpegContext.filterComplex.push(`[music][voice]amix=inputs=2:duration=longest${amixNormalize}[mixed]`);
    if (limiterFilter) {
        ffmpegContext.filterComplex.push(limiterFilter);
    }
    ffmpegContext.filterComplex.push(`[${mixedOutputId}]atrim=start=0:end=${totalDuration}[trimmed]`);
    ffmpegContext.filterComplex.push(`[trimmed]afade=t=out:st=${totalDuration - outroPadding}:d=${outroPadding}[faded]`);
    try {
        await FfmpegContextGenerateOutput(ffmpegContext, outputFile, ["-map", "[faded]"]);
        return outputFile;
    }
    catch (e) {
        GraphAILogger.log(e);
        throw new Error(`AddBGMAgent ffmpeg run Error`, {
            cause: agentGenerationError("addBGMAgent", audioAction, audioFileTarget),
        });
    }
};
const addBGMAgentInfo = {
    name: "addBGMAgent",
    agent: addBGMAgent,
    mock: addBGMAgent,
    samples: [],
    description: "addBGMAgent",
    category: ["ffmpeg"],
    author: "satoshi nakajima",
    repository: "https://github.com/snakajima/ai-podcaster",
    license: "MIT",
};
export default addBGMAgentInfo;
