@agimon-ai/video-editor-mcp 0.8.2 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/index.cjs +1 -1
- package/dist/{stdio-CH0Bk0m7.cjs → stdio-1ofTrT91.cjs} +1 -1
- package/package.json +19 -19
package/dist/cli.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const e=require(`./stdio-
|
|
2
|
+
const e=require(`./stdio-1ofTrT91.cjs`);let t=require(`node:child_process`),n=require(`node:fs`);n=e.M(n,1);let r=require(`node:path`);r=e.M(r,1);let i=require(`commander`),a=require(`@agimon-ai/foundation-port-registry`),o=require(`@agimon-ai/foundation-process-registry`),s=require(`chalk`);s=e.M(s,1);var c=`0.8.3`;const l=[`pnpm-workspace.yaml`,`nx.json`,`.git`],u=`video-editor-mcp-http`,d=`tool`;function f(e=process.cwd()){let t=r.default.resolve(e);for(;;){for(let e of l)if((0,n.existsSync)(r.default.join(t,e)))return t;let e=r.default.dirname(t);if(e===t)return process.cwd();t=e}}const p=new i.Command(`http-serve`).description(`Start Remotion Studio for video editing`).option(`-p, --port <port>`,`Port to run Remotion Studio on`,String(a.DEFAULT_PORT_RANGE.min)).action(async e=>{let n;try{let i=Number.parseInt(e.port,10),c=new a.PortRegistryService(process.env.PORT_REGISTRY_PATH),l=f(),p=i?{min:i,max:i}:a.DEFAULT_PORT_RANGE,m=await c.reservePort({repositoryPath:l,serviceName:u,serviceType:d,preferredPort:i||a.DEFAULT_PORT_RANGE.min,portRange:p,pid:process.pid,host:`127.0.0.1`,force:!0});if(!m.success||!m.record)throw Error(m.error||`Failed to reserve port ${i}`);let h=m.record.port;n=await(0,o.createProcessLease)({repositoryPath:l,serviceName:u,serviceType:d,pid:process.pid,port:h,host:`127.0.0.1`,command:process.argv[1],args:process.argv.slice(2)});let g=r.default.resolve(__dirname,`..`);console.error(s.default.green(`Starting Remotion Studio on port ${h}...`)),console.error(s.default.gray(` Working directory: ${g}`));let _=(0,t.spawn)(r.default.join(g,`node_modules`,`.bin`,`remotion`),[`studio`,`--port`,String(h)],{stdio:`inherit`,cwd:g});_.on(`error`,e=>{console.error(s.default.red(`Failed to start Remotion Studio: ${e.message}`)),process.exit(1)});let v=async e=>{_.kill(e),await n?.release(),await c.releasePort({repositoryPath:l,serviceName:u,serviceType:d,pid:process.pid}),process.exit(0)};process.on(`SIGINT`,()=>v(`SIGINT`)),process.on(`SIGTERM`,()=>v(`SIGTERM`))}catch(e){await n?.release(),console.error(`Error executing http-serve:`,e),process.exit(1)}}),m=[`pnpm-workspace.yaml`,`nx.json`,`.git`];function h(e=process.cwd()){let t=r.default.resolve(e);for(;;){for(let e of m)if((0,n.existsSync)(r.default.join(t,e)))return t;let e=r.default.dirname(t);if(e===t)return process.cwd();t=e}}async function g(e,t){await e.start();let n=async n=>{console.error(`\nReceived ${n}, shutting down gracefully...`);try{await e.stop(),await t?.(),process.exit(0)}catch(e){console.error(`Error during shutdown:`,e),process.exit(1)}};process.on(`SIGINT`,()=>n(`SIGINT`)),process.on(`SIGTERM`,()=>n(`SIGTERM`))}const _=new i.Command(`mcp-serve`).description(`Start MCP server with specified transport`).option(`-t, --type <type>`,`Transport type: stdio`,`stdio`).option(`--proxy <url>`,`Proxy URL for yt-dlp (HTTP/HTTPS/SOCKS5, e.g. socks5://user:pass@host:port)`).action(async t=>{let n;try{let r=t.type.toLowerCase(),i=h();if(r===`stdio`){let r=new e.t(e.n(e.r({proxyUrl:t.proxy})));n=await(0,o.createProcessLease)({repositoryPath:i,serviceName:`video-editor-mcp-stdio`,pid:process.pid,metadata:{transport:`stdio`}}),await g(r,async()=>{await n?.release()})}else console.error(`Unknown transport type: ${r}. Use: stdio`),process.exit(1)}catch(e){await n?.release(),console.error(`Failed to start MCP server:`,e),process.exit(1)}}),v=new i.Command(`analyze-video`).description(`Analyze one or more local video files with Gemini Code Assist`).requiredOption(`-v, --video <paths...>`,`Paths to local video files to analyze`).requiredOption(`-p, --prompt <text>`,`Prompt to send with the video(s)`).option(`-m, --model <id>`,`Gemini model to use`,`gemini-2.5-flash-lite`).option(`--pretty`,`Pretty-print the full JSON result`,!1).action(async t=>{try{if(!Array.isArray(t.video)||t.video.length===0)throw Error(`At least one video path is required.`);process.stderr.write(s.default.blue(`🎥 Starting video analysis...
|
|
3
3
|
`)),process.stderr.write(s.default.gray(` Videos: ${t.video.join(`, `)}\n`)),process.stderr.write(s.default.gray(` Prompt: ${t.prompt}\n`)),process.stderr.write(s.default.gray(` Model: ${t.model}\n`));let n=await e.r().get(e.h.VideoAnalysisService).analyzeVideos({videoPaths:t.video,prompt:t.prompt,model:t.model});if(process.stderr.write(s.default.green(`✓ Resolved project: ${n.resolvedProject}\n`)),process.stderr.write(s.default.green(`✓ Videos processed: ${n.videoCount}\n`)),t.pretty){process.stdout.write(`${JSON.stringify(n,null,2)}\n`);return}if(n.responseText){process.stdout.write(`${n.responseText}\n`);return}process.stdout.write(`${JSON.stringify(n.rawResponse,null,2)}\n`)}catch(e){let t=e instanceof Error?e.message:String(e);process.stderr.write(s.default.red(`Error analyzing video: ${t}\n`)),process.exit(1)}}),y=e=>Number(e),b=e=>Number.parseInt(e,10),x=()=>(0,n.existsSync)(r.default.resolve(__dirname,`../package.json`))?r.default.resolve(__dirname,`..`):r.default.resolve(__dirname,`../..`),S=e=>{if(e.output)return r.default.resolve(e.output);let t=r.default.resolve(e.outputDir??r.default.join(x(),`public/music`)),n=e.filename??`ace-step-music`;return r.default.join(t,`${n}.${e.audioFormat}`)},C=new i.Command(`generate-music`).description(`Generate background music using ACE-Step 1.5`).requiredOption(`-p, --prompt <text>`,`Music description for ACE-Step text-to-music generation`).option(`-f, --filename <name>`,`Output filename without extension (default: ace-step-music)`).option(`-o, --output <path>`,`Explicit output audio path. Overrides filename/output-dir.`).option(`--output-dir <path>`,`Custom output directory (default: Remotion public/music/)`).option(`--ace-step-path <path>`,`Path to local ACE-Step-1.5 checkout`).option(`--lyrics <text>`,`Lyrics to use. Defaults to [Instrumental] for background music.`).option(`--duration <seconds>`,`Target duration in seconds (default: 30)`,y).option(`--bpm <number>`,`Optional BPM metadata`,y).option(`--keyscale <text>`,`Optional key/scale metadata, e.g. C minor`).option(`--time-signature <text>`,`Optional time signature metadata, e.g. 4/4`).option(`--vocal-language <code>`,`Vocal language code, or unknown`).option(`--seed <number>`,`Optional fixed seed for reproducible generation`,b).option(`--inference-steps <number>`,`Diffusion inference steps (default: 8)`,b).option(`--audio-format <format>`,`Output audio format: wav, mp3, flac`,`wav`).option(`--backend <backend>`,`ACE-Step LM backend: mlx, pt, vllm`,`mlx`).option(`--config-path <name>`,`ACE-Step DiT model config (default: acestep-v15-turbo)`).option(`--lm-model-path <name>`,`ACE-Step LM model (default: acestep-5Hz-lm-0.6B)`).option(`--timeout-ms <number>`,`Generation timeout in milliseconds`,b).option(`--pretty`,`Pretty-print the JSON result`,!1).action(async t=>{try{if(![`wav`,`mp3`,`flac`].includes(t.audioFormat))throw Error(`Unsupported audio format: ${t.audioFormat}`);if(![`mlx`,`pt`,`vllm`].includes(t.backend))throw Error(`Unsupported backend: ${t.backend}`);let n=S(t);process.stderr.write(s.default.blue(`Starting ACE-Step music generation...
|
|
4
4
|
`)),process.stderr.write(s.default.gray(` Prompt: ${t.prompt}\n`)),process.stderr.write(s.default.gray(` Output: ${n}\n`)),process.stderr.write(s.default.gray(` Backend: ${t.backend}\n`));let i=e.r().get(e.h.AceStepMusicService);if(!await i.isAvailable(t.aceStepPath))throw Error(`ACE-Step 1.5 is not available. Clone https://github.com/ACE-Step/ACE-Step-1.5 and set ACE_STEP_15_DIR or pass --ace-step-path.`);let a=await i.generateMusic({prompt:t.prompt,outputPath:n,aceStepPath:t.aceStepPath,lyrics:t.lyrics,duration:t.duration,bpm:t.bpm,keyscale:t.keyscale,timeSignature:t.timeSignature,vocalLanguage:t.vocalLanguage,seed:t.seed,inferenceSteps:t.inferenceSteps,audioFormat:t.audioFormat,backend:t.backend,configPath:t.configPath,lmModelPath:t.lmModelPath,timeoutMs:t.timeoutMs}),o={...a,compositionSrc:r.default.dirname(n)===r.default.resolve(x(),`public/music`)?`/music/${r.default.basename(n)}`:void 0};process.stderr.write(s.default.green(`Music generated successfully: ${a.outputPath}\n`)),process.stdout.write(`${JSON.stringify(o,null,t.pretty?2:0)}\n`)}catch(e){let t=e instanceof Error?e.message:String(e);process.stderr.write(s.default.red(`Error generating music: ${t}\n`)),process.exit(1)}}),w=new i.Command(`render`).description(`Render a video from JSON props file`).requiredOption(`-i, --input <path>`,`Path to JSON props file`).requiredOption(`-o, --output <path>`,`Output video file path`).option(`-c, --composition <id>`,`Composition ID`,`Main`).option(`--codec <codec>`,`Video codec (h264, h265, vp8, vp9)`,`h264`).option(`--dry-run`,`Validate props and assets without rendering`).action(async t=>{try{process.stderr.write(s.default.blue(t.dryRun?`🔎 Starting render dry run...
|
|
5
5
|
`:`🎬 Starting video render...
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{_ as e,h as t,n,r,t as i}from"./stdio-KMqWPqUm.mjs";import{spawn as a}from"node:child_process";import o,{existsSync as s}from"node:fs";import c from"node:path";import{Command as l}from"commander";import{DEFAULT_PORT_RANGE as u,PortRegistryService as d}from"@agimon-ai/foundation-port-registry";import{createProcessLease as f}from"@agimon-ai/foundation-process-registry";import p from"chalk";var m=`0.8.
|
|
2
|
+
import{_ as e,h as t,n,r,t as i}from"./stdio-KMqWPqUm.mjs";import{spawn as a}from"node:child_process";import o,{existsSync as s}from"node:fs";import c from"node:path";import{Command as l}from"commander";import{DEFAULT_PORT_RANGE as u,PortRegistryService as d}from"@agimon-ai/foundation-port-registry";import{createProcessLease as f}from"@agimon-ai/foundation-process-registry";import p from"chalk";var m=`0.8.3`;const h=[`pnpm-workspace.yaml`,`nx.json`,`.git`],g=`video-editor-mcp-http`,_=`tool`;function v(e=process.cwd()){let t=c.resolve(e);for(;;){for(let e of h)if(s(c.join(t,e)))return t;let e=c.dirname(t);if(e===t)return process.cwd();t=e}}const y=new l(`http-serve`).description(`Start Remotion Studio for video editing`).option(`-p, --port <port>`,`Port to run Remotion Studio on`,String(u.min)).action(async e=>{let t;try{let n=Number.parseInt(e.port,10),r=new d(process.env.PORT_REGISTRY_PATH),i=v(),o=n?{min:n,max:n}:u,s=await r.reservePort({repositoryPath:i,serviceName:g,serviceType:_,preferredPort:n||u.min,portRange:o,pid:process.pid,host:`127.0.0.1`,force:!0});if(!s.success||!s.record)throw Error(s.error||`Failed to reserve port ${n}`);let l=s.record.port;t=await f({repositoryPath:i,serviceName:g,serviceType:_,pid:process.pid,port:l,host:`127.0.0.1`,command:process.argv[1],args:process.argv.slice(2)});let m=c.resolve(import.meta.dirname,`..`);console.error(p.green(`Starting Remotion Studio on port ${l}...`)),console.error(p.gray(` Working directory: ${m}`));let h=a(c.join(m,`node_modules`,`.bin`,`remotion`),[`studio`,`--port`,String(l)],{stdio:`inherit`,cwd:m});h.on(`error`,e=>{console.error(p.red(`Failed to start Remotion Studio: ${e.message}`)),process.exit(1)});let y=async e=>{h.kill(e),await t?.release(),await r.releasePort({repositoryPath:i,serviceName:g,serviceType:_,pid:process.pid}),process.exit(0)};process.on(`SIGINT`,()=>y(`SIGINT`)),process.on(`SIGTERM`,()=>y(`SIGTERM`))}catch(e){await t?.release(),console.error(`Error executing http-serve:`,e),process.exit(1)}}),b=[`pnpm-workspace.yaml`,`nx.json`,`.git`];function x(e=process.cwd()){let t=c.resolve(e);for(;;){for(let e of b)if(s(c.join(t,e)))return t;let e=c.dirname(t);if(e===t)return process.cwd();t=e}}async function S(e,t){await e.start();let n=async n=>{console.error(`\nReceived ${n}, shutting down gracefully...`);try{await e.stop(),await t?.(),process.exit(0)}catch(e){console.error(`Error during shutdown:`,e),process.exit(1)}};process.on(`SIGINT`,()=>n(`SIGINT`)),process.on(`SIGTERM`,()=>n(`SIGTERM`))}const C=new l(`mcp-serve`).description(`Start MCP server with specified transport`).option(`-t, --type <type>`,`Transport type: stdio`,`stdio`).option(`--proxy <url>`,`Proxy URL for yt-dlp (HTTP/HTTPS/SOCKS5, e.g. socks5://user:pass@host:port)`).action(async e=>{let t;try{let a=e.type.toLowerCase(),o=x();if(a===`stdio`){let a=new i(n(r({proxyUrl:e.proxy})));t=await f({repositoryPath:o,serviceName:`video-editor-mcp-stdio`,pid:process.pid,metadata:{transport:`stdio`}}),await S(a,async()=>{await t?.release()})}else console.error(`Unknown transport type: ${a}. Use: stdio`),process.exit(1)}catch(e){await t?.release(),console.error(`Failed to start MCP server:`,e),process.exit(1)}}),w=new l(`analyze-video`).description(`Analyze one or more local video files with Gemini Code Assist`).requiredOption(`-v, --video <paths...>`,`Paths to local video files to analyze`).requiredOption(`-p, --prompt <text>`,`Prompt to send with the video(s)`).option(`-m, --model <id>`,`Gemini model to use`,`gemini-2.5-flash-lite`).option(`--pretty`,`Pretty-print the full JSON result`,!1).action(async e=>{try{if(!Array.isArray(e.video)||e.video.length===0)throw Error(`At least one video path is required.`);process.stderr.write(p.blue(`🎥 Starting video analysis...
|
|
3
3
|
`)),process.stderr.write(p.gray(` Videos: ${e.video.join(`, `)}\n`)),process.stderr.write(p.gray(` Prompt: ${e.prompt}\n`)),process.stderr.write(p.gray(` Model: ${e.model}\n`));let n=await r().get(t.VideoAnalysisService).analyzeVideos({videoPaths:e.video,prompt:e.prompt,model:e.model});if(process.stderr.write(p.green(`✓ Resolved project: ${n.resolvedProject}\n`)),process.stderr.write(p.green(`✓ Videos processed: ${n.videoCount}\n`)),e.pretty){process.stdout.write(`${JSON.stringify(n,null,2)}\n`);return}if(n.responseText){process.stdout.write(`${n.responseText}\n`);return}process.stdout.write(`${JSON.stringify(n.rawResponse,null,2)}\n`)}catch(e){let t=e instanceof Error?e.message:String(e);process.stderr.write(p.red(`Error analyzing video: ${t}\n`)),process.exit(1)}}),T=e=>Number(e),E=e=>Number.parseInt(e,10),D=()=>s(c.resolve(import.meta.dirname,`../package.json`))?c.resolve(import.meta.dirname,`..`):c.resolve(import.meta.dirname,`../..`),O=e=>{if(e.output)return c.resolve(e.output);let t=c.resolve(e.outputDir??c.join(D(),`public/music`)),n=e.filename??`ace-step-music`;return c.join(t,`${n}.${e.audioFormat}`)},k=new l(`generate-music`).description(`Generate background music using ACE-Step 1.5`).requiredOption(`-p, --prompt <text>`,`Music description for ACE-Step text-to-music generation`).option(`-f, --filename <name>`,`Output filename without extension (default: ace-step-music)`).option(`-o, --output <path>`,`Explicit output audio path. Overrides filename/output-dir.`).option(`--output-dir <path>`,`Custom output directory (default: Remotion public/music/)`).option(`--ace-step-path <path>`,`Path to local ACE-Step-1.5 checkout`).option(`--lyrics <text>`,`Lyrics to use. Defaults to [Instrumental] for background music.`).option(`--duration <seconds>`,`Target duration in seconds (default: 30)`,T).option(`--bpm <number>`,`Optional BPM metadata`,T).option(`--keyscale <text>`,`Optional key/scale metadata, e.g. C minor`).option(`--time-signature <text>`,`Optional time signature metadata, e.g. 4/4`).option(`--vocal-language <code>`,`Vocal language code, or unknown`).option(`--seed <number>`,`Optional fixed seed for reproducible generation`,E).option(`--inference-steps <number>`,`Diffusion inference steps (default: 8)`,E).option(`--audio-format <format>`,`Output audio format: wav, mp3, flac`,`wav`).option(`--backend <backend>`,`ACE-Step LM backend: mlx, pt, vllm`,`mlx`).option(`--config-path <name>`,`ACE-Step DiT model config (default: acestep-v15-turbo)`).option(`--lm-model-path <name>`,`ACE-Step LM model (default: acestep-5Hz-lm-0.6B)`).option(`--timeout-ms <number>`,`Generation timeout in milliseconds`,E).option(`--pretty`,`Pretty-print the JSON result`,!1).action(async e=>{try{if(![`wav`,`mp3`,`flac`].includes(e.audioFormat))throw Error(`Unsupported audio format: ${e.audioFormat}`);if(![`mlx`,`pt`,`vllm`].includes(e.backend))throw Error(`Unsupported backend: ${e.backend}`);let n=O(e);process.stderr.write(p.blue(`Starting ACE-Step music generation...
|
|
4
4
|
`)),process.stderr.write(p.gray(` Prompt: ${e.prompt}\n`)),process.stderr.write(p.gray(` Output: ${n}\n`)),process.stderr.write(p.gray(` Backend: ${e.backend}\n`));let i=r().get(t.AceStepMusicService);if(!await i.isAvailable(e.aceStepPath))throw Error(`ACE-Step 1.5 is not available. Clone https://github.com/ACE-Step/ACE-Step-1.5 and set ACE_STEP_15_DIR or pass --ace-step-path.`);let a=await i.generateMusic({prompt:e.prompt,outputPath:n,aceStepPath:e.aceStepPath,lyrics:e.lyrics,duration:e.duration,bpm:e.bpm,keyscale:e.keyscale,timeSignature:e.timeSignature,vocalLanguage:e.vocalLanguage,seed:e.seed,inferenceSteps:e.inferenceSteps,audioFormat:e.audioFormat,backend:e.backend,configPath:e.configPath,lmModelPath:e.lmModelPath,timeoutMs:e.timeoutMs}),o={...a,compositionSrc:c.dirname(n)===c.resolve(D(),`public/music`)?`/music/${c.basename(n)}`:void 0};process.stderr.write(p.green(`Music generated successfully: ${a.outputPath}\n`)),process.stdout.write(`${JSON.stringify(o,null,e.pretty?2:0)}\n`)}catch(e){let t=e instanceof Error?e.message:String(e);process.stderr.write(p.red(`Error generating music: ${t}\n`)),process.exit(1)}}),A=new l(`render`).description(`Render a video from JSON props file`).requiredOption(`-i, --input <path>`,`Path to JSON props file`).requiredOption(`-o, --output <path>`,`Output video file path`).option(`-c, --composition <id>`,`Composition ID`,`Main`).option(`--codec <codec>`,`Video codec (h264, h265, vp8, vp9)`,`h264`).option(`--dry-run`,`Validate props and assets without rendering`).action(async n=>{try{process.stderr.write(p.blue(n.dryRun?`🔎 Starting render dry run...
|
|
5
5
|
`:`🎬 Starting video render...
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./stdio-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./stdio-1ofTrT91.cjs`);exports.AnimationConfigSchema=e.S,exports.AudioClipSchema=e.C,Object.defineProperty(exports,`BaseTool`,{enumerable:!0,get:function(){return e.p}}),exports.CaptionConfigSchema=e.v,exports.CaptionSchema=e.y,exports.ClipSchema=e.w,Object.defineProperty(exports,`ExtractVideoContextTool`,{enumerable:!0,get:function(){return e.f}}),exports.FontConfigSchema=e.b,Object.defineProperty(exports,`GenerateCaptionsTool`,{enumerable:!0,get:function(){return e.d}}),Object.defineProperty(exports,`GenerateVoiceoverTool`,{enumerable:!0,get:function(){return e.u}}),Object.defineProperty(exports,`GetMediaInfoTool`,{enumerable:!0,get:function(){return e.l}}),exports.GifClipSchema=e.T,exports.ImageClipSchema=e.E,Object.defineProperty(exports,`ImportSrtTool`,{enumerable:!0,get:function(){return e.c}}),Object.defineProperty(exports,`ListCompositionsTool`,{enumerable:!0,get:function(){return e.s}}),exports.LottieClipSchema=e.D,exports.MainCompositionSchema=e.x,Object.defineProperty(exports,`PreviewFrameTool`,{enumerable:!0,get:function(){return e.o}}),Object.defineProperty(exports,`RenderService`,{enumerable:!0,get:function(){return e.g}}),Object.defineProperty(exports,`RenderVideoTool`,{enumerable:!0,get:function(){return e.a}}),exports.StdioTransportHandler=e.t,exports.SubtitleClipSchema=e.O,exports.TYPES=e.h,exports.TextClipSchema=e.k,exports.TransitionConfigSchema=e.A,exports.VideoClipSchema=e.j,Object.defineProperty(exports,`VideoContextService`,{enumerable:!0,get:function(){return e.m}}),Object.defineProperty(exports,`VideoUnderstandingTool`,{enumerable:!0,get:function(){return e.i}}),exports.createContainer=e.r,exports.createServer=e.n;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));require(`reflect-metadata`);let c=require(`inversify`),l=require(`node:child_process`),u=require(`node:fs`);u=s(u);let d=require(`node:fs/promises`);d=s(d);let f=require(`node:os`);f=s(f);let p=require(`node:path`);p=s(p);let m=require(`node:util`),h=require(`node:crypto`);h=s(h);let g=require(`node:url`),_=require(`@remotion/bundler`),v=require(`@remotion/renderer`),y=require(`sharp`);y=s(y);let b=require(`zod`),ee=require(`@agimon-ai/foundation-validator`),te=require(`@modelcontextprotocol/sdk/server/index.js`),ne=require(`@modelcontextprotocol/sdk/types.js`),re=require(`@modelcontextprotocol/sdk/server/stdio.js`);function x(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}const ie=(0,m.promisify)(l.execFile);let S=class{async isAvailable(e){let t=this.resolveAceStepPath(e);if(!this.isAceStepCheckout(t))return!1;try{return await ie(`uv`,[`--version`]),!0}catch{return!1}}async generateMusic(e){let t=this.resolveAceStepPath(e.aceStepPath);if(!this.isAceStepCheckout(t))throw Error(`ACE-Step 1.5 checkout not found at ${t}. Pass aceStepPath or set ACE_STEP_15_DIR.`);let n=e.audioFormat??this.getFormatFromPath(e.outputPath),r=e.backend??`mlx`,i=e.duration??30,a=await d.default.mkdtemp(p.default.join(f.default.tmpdir(),`ace-step-music-`)),o=p.default.join(a,`generation.toml`),s=p.default.join(a,`output`);await d.default.mkdir(s,{recursive:!0}),await d.default.mkdir(p.default.dirname(e.outputPath),{recursive:!0});try{let a=this.buildConfig({...e,aceStepPath:t,audioFormat:n,backend:r,duration:i,outputDir:s});await d.default.writeFile(o,a,`utf-8`);let{stdout:c,stderr:l}=await ie(`uv`,[`run`,`python`,`cli.py`,`-c`,o,`--backend`,r,`--log-level`,`INFO`],{cwd:t,timeout:e.timeoutMs??1200*1e3,maxBuffer:50*1024*1024}),u=await this.findNewestGeneratedAudio(s,n);return await d.default.copyFile(u,e.outputPath),{outputPath:e.outputPath,sourcePath:u,duration:i,audioFormat:n,backend:r,aceStepPath:t,stdout:c,stderr:l}}catch(e){throw Error(`Failed to generate ACE-Step music: ${e instanceof Error?e.message:String(e)}`,{cause:e})}finally{await d.default.rm(a,{recursive:!0,force:!0}).catch(()=>void 0)}}resolveAceStepPath(e){return p.default.resolve(e??process.env.ACE_STEP_15_DIR??process.env.ACESTEP_15_DIR??p.default.join(f.default.homedir(),`workspace`,`ACE-Step-1.5`))}isAceStepCheckout(e){return(0,u.existsSync)(p.default.join(e,`cli.py`))&&(0,u.existsSync)(p.default.join(e,`pyproject.toml`))}getFormatFromPath(e){let t=p.default.extname(e).toLowerCase().replace(`.`,``);return t===`mp3`||t===`flac`||t===`wav`?t:`wav`}async findNewestGeneratedAudio(e,t){let n=await d.default.readdir(e,{withFileTypes:!0}),r=await Promise.all(n.filter(e=>e.isFile()&&e.name.endsWith(`.${t}`)).map(async t=>{let n=p.default.join(e,t.name);return{filePath:n,mtimeMs:(await d.default.stat(n)).mtimeMs}}));if(r.sort((e,t)=>t.mtimeMs-e.mtimeMs),!r[0])throw Error(`ACE-Step completed but no .${t} file was found in ${e}`);return r[0].filePath}buildConfig(e){let t=e.lyrics?.trim()||`[Instrumental]`,n=t.toLowerCase()===`[instrumental]`,r={project_root:e.aceStepPath,checkpoint_dir:p.default.join(e.aceStepPath,`checkpoints`),config_path:e.configPath??`acestep-v15-turbo`,lm_model_path:e.lmModelPath??`acestep-5Hz-lm-0.6B`,backend:e.backend,device:`auto`,offload_to_cpu:!1,offload_dit_to_cpu:!1,save_dir:e.outputDir,audio_format:e.audioFormat,caption:e.prompt,lyrics:t,duration:e.duration,instrumental:n,bpm:e.bpm??null,keyscale:e.keyscale??``,timesignature:e.timeSignature??``,vocal_language:e.vocalLanguage??`unknown`,task_type:`text2music`,sample_mode:!1,sample_query:``,use_format:!1,inference_steps:e.inferenceSteps??8,seed:e.seed??-1,use_random_seed:e.seed===void 0,guidance_scale:7,use_adg:!1,shift:3,infer_method:`ode`,thinking:!0,lm_temperature:.85,lm_cfg_scale:2,lm_top_k:0,lm_top_p:.9,use_cot_metas:!0,use_cot_caption:!0,use_cot_lyrics:!1,use_cot_language:!0,use_constrained_decoding:!0,batch_size:1,allow_lm_batch:!1,lm_batch_chunk_size:8,constrained_decoding_debug:!1,cfg_interval_start:0,cfg_interval_end:1,lm_negative_prompt:`NO USER INPUT`,log_level:`INFO`};return Object.entries(r).filter(e=>e[1]!==null).map(([e,t])=>`${e} = ${this.toTomlValue(t)}`).join(`
|
|
1
|
+
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));require(`reflect-metadata`);let c=require(`inversify`),l=require(`node:child_process`),u=require(`node:fs`);u=s(u,1);let d=require(`node:fs/promises`);d=s(d,1);let f=require(`node:os`);f=s(f,1);let p=require(`node:path`);p=s(p,1);let m=require(`node:util`),h=require(`node:crypto`);h=s(h,1);let g=require(`node:url`),_=require(`@remotion/bundler`),v=require(`@remotion/renderer`),y=require(`sharp`);y=s(y,1);let b=require(`zod`),ee=require(`@agimon-ai/foundation-validator`),te=require(`@modelcontextprotocol/sdk/server/index.js`),ne=require(`@modelcontextprotocol/sdk/types.js`),re=require(`@modelcontextprotocol/sdk/server/stdio.js`);function x(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}const ie=(0,m.promisify)(l.execFile);let S=class{async isAvailable(e){let t=this.resolveAceStepPath(e);if(!this.isAceStepCheckout(t))return!1;try{return await ie(`uv`,[`--version`]),!0}catch{return!1}}async generateMusic(e){let t=this.resolveAceStepPath(e.aceStepPath);if(!this.isAceStepCheckout(t))throw Error(`ACE-Step 1.5 checkout not found at ${t}. Pass aceStepPath or set ACE_STEP_15_DIR.`);let n=e.audioFormat??this.getFormatFromPath(e.outputPath),r=e.backend??`mlx`,i=e.duration??30,a=await d.default.mkdtemp(p.default.join(f.default.tmpdir(),`ace-step-music-`)),o=p.default.join(a,`generation.toml`),s=p.default.join(a,`output`);await d.default.mkdir(s,{recursive:!0}),await d.default.mkdir(p.default.dirname(e.outputPath),{recursive:!0});try{let a=this.buildConfig({...e,aceStepPath:t,audioFormat:n,backend:r,duration:i,outputDir:s});await d.default.writeFile(o,a,`utf-8`);let{stdout:c,stderr:l}=await ie(`uv`,[`run`,`python`,`cli.py`,`-c`,o,`--backend`,r,`--log-level`,`INFO`],{cwd:t,timeout:e.timeoutMs??1200*1e3,maxBuffer:50*1024*1024}),u=await this.findNewestGeneratedAudio(s,n);return await d.default.copyFile(u,e.outputPath),{outputPath:e.outputPath,sourcePath:u,duration:i,audioFormat:n,backend:r,aceStepPath:t,stdout:c,stderr:l}}catch(e){throw Error(`Failed to generate ACE-Step music: ${e instanceof Error?e.message:String(e)}`,{cause:e})}finally{await d.default.rm(a,{recursive:!0,force:!0}).catch(()=>void 0)}}resolveAceStepPath(e){return p.default.resolve(e??process.env.ACE_STEP_15_DIR??process.env.ACESTEP_15_DIR??p.default.join(f.default.homedir(),`workspace`,`ACE-Step-1.5`))}isAceStepCheckout(e){return(0,u.existsSync)(p.default.join(e,`cli.py`))&&(0,u.existsSync)(p.default.join(e,`pyproject.toml`))}getFormatFromPath(e){let t=p.default.extname(e).toLowerCase().replace(`.`,``);return t===`mp3`||t===`flac`||t===`wav`?t:`wav`}async findNewestGeneratedAudio(e,t){let n=await d.default.readdir(e,{withFileTypes:!0}),r=await Promise.all(n.filter(e=>e.isFile()&&e.name.endsWith(`.${t}`)).map(async t=>{let n=p.default.join(e,t.name);return{filePath:n,mtimeMs:(await d.default.stat(n)).mtimeMs}}));if(r.sort((e,t)=>t.mtimeMs-e.mtimeMs),!r[0])throw Error(`ACE-Step completed but no .${t} file was found in ${e}`);return r[0].filePath}buildConfig(e){let t=e.lyrics?.trim()||`[Instrumental]`,n=t.toLowerCase()===`[instrumental]`,r={project_root:e.aceStepPath,checkpoint_dir:p.default.join(e.aceStepPath,`checkpoints`),config_path:e.configPath??`acestep-v15-turbo`,lm_model_path:e.lmModelPath??`acestep-5Hz-lm-0.6B`,backend:e.backend,device:`auto`,offload_to_cpu:!1,offload_dit_to_cpu:!1,save_dir:e.outputDir,audio_format:e.audioFormat,caption:e.prompt,lyrics:t,duration:e.duration,instrumental:n,bpm:e.bpm??null,keyscale:e.keyscale??``,timesignature:e.timeSignature??``,vocal_language:e.vocalLanguage??`unknown`,task_type:`text2music`,sample_mode:!1,sample_query:``,use_format:!1,inference_steps:e.inferenceSteps??8,seed:e.seed??-1,use_random_seed:e.seed===void 0,guidance_scale:7,use_adg:!1,shift:3,infer_method:`ode`,thinking:!0,lm_temperature:.85,lm_cfg_scale:2,lm_top_k:0,lm_top_p:.9,use_cot_metas:!0,use_cot_caption:!0,use_cot_lyrics:!1,use_cot_language:!0,use_constrained_decoding:!0,batch_size:1,allow_lm_batch:!1,lm_batch_chunk_size:8,constrained_decoding_debug:!1,cfg_interval_start:0,cfg_interval_end:1,lm_negative_prompt:`NO USER INPUT`,log_level:`INFO`};return Object.entries(r).filter(e=>e[1]!==null).map(([e,t])=>`${e} = ${this.toTomlValue(t)}`).join(`
|
|
2
2
|
`)}toTomlValue(e){return typeof e==`string`?JSON.stringify(e):String(e)}};S=x([(0,c.injectable)()],S);const ae={tiktok:{top:270,right:140,bottom:480,left:80},reels:{top:220,right:110,bottom:420,left:80},shorts:{top:220,right:100,bottom:420,left:80},universal:{top:240,right:140,bottom:480,left:80}};let C=class{parseSrt(e){let t=[],n=e.split(`
|
|
3
3
|
`),r=0;for(;r<n.length;){if(!n[r]?.trim()){r++;continue}r++;let e=n[r];if(!e?.includes(`-->`)){r++;continue}let[i,a]=e.split(`-->`).map(e=>e.trim());if(!i||!a){r++;continue}let o=this.parseTimestamp(i),s=this.parseTimestamp(a);r++;let c=[];for(;r<n.length&&n[r]?.trim();)c.push(n[r]??``),r++;let l=c.join(`
|
|
4
4
|
`);l&&t.push({text:l,startMs:o,endMs:s})}return t}parseTimestamp(e){let[t,n]=e.split(`,`);if(!t||!n)throw Error(`Invalid timestamp format: ${e}`);let[r,i,a]=t.split(`:`).map(Number);if(r===void 0||i===void 0||a===void 0)throw Error(`Invalid time format: ${t}`);return(r*3600+i*60+a)*1e3+Number(n)}createTikTokCaptions(e,t=100){let n=typeof t==`number`?{combineMs:t}:t,r=n.combineMs??100,i=n.maxWordsPerPage??6,a=n.maxCharsPerLine??22,o=n.platform??`tiktok`,s=n.preset??`tiktok-bold`,c=this.createCaptionPages(e,{combineMs:r,maxWordsPerPage:i});return{pages:c,captionConfig:{captions:e,pages:c,style:s===`karaoke`?`karaoke`:`tiktok`,preset:s,platform:o,combineTokensWithinMilliseconds:r,maxWordsPerPage:i,maxCharsPerLine:a,maxLines:2,maxWidthPct:.86,fontSize:60,minFontSize:42,fontFamily:`Arial, sans-serif`,fontWeight:800,lineHeight:1.08,color:`#ffffff`,inactiveColor:`#ffffff`,highlightColor:`#FFD700`,textColor:`#ffffff`,strokeColor:`#000000`,strokeWidth:5,shadow:!0,backgroundColor:`rgba(0, 0, 0, 0)`,backgroundRadius:8,safeZone:ae[o],position:`bottom`}}}createCaptionPages(e,t={}){let n=[],r=this.normalizeCaptionsToTokens(e),i=t.combineMs??100,a=t.maxWordsPerPage??6;if(r.length===0)return n;let o={startMs:r[0]?.startMs??0,endMs:r[0]?.endMs??0,tokens:[r[0]]};for(let e=1;e<r.length;e++){let t=r[e];if(!t)continue;let s=t.startMs-o.endMs,c=this.countWords(o.tokens.map(e=>e.text).join(` `)),l=this.countWords(t.text);s<=i&&c+l<=a?(o.tokens.push(t),o.endMs=t.endMs):(o.text=this.pageText(o.tokens),n.push(o),o={startMs:t.startMs,endMs:t.endMs,tokens:[t]})}return o.tokens.length>0&&(o.text=this.pageText(o.tokens),n.push(o)),n}normalizeCaptionsToTokens(e){return[...e].sort((e,t)=>e.startMs-t.startMs).flatMap(e=>this.captionToTokens(e))}getPlatformSafeZone(e){return ae[e]}captionToTokens(e){let t=e.text.trim().split(/\s+/).filter(Boolean);if(t.length===0)return[];if(t.length===1)return[{...e,text:t[0]??e.text,emphasis:e.emphasis??`none`}];let n=Math.max(1,e.endMs-e.startMs)/t.length;return t.map((r,i)=>{let a=Math.round(e.startMs+n*i),o=i===t.length-1?e.endMs:Math.round(e.startMs+n*(i+1));return{text:r,startMs:a,endMs:Math.max(o,a+1),timestampMs:a,confidence:e.confidence,emphasis:e.emphasis??`none`}})}pageText(e){return e.map(e=>e.text).join(` `)}countWords(e){return e.trim().split(/\s+/).filter(Boolean).length}};C=x([(0,c.injectable)()],C);const oe=[`Inter`,`Roboto`,`Open Sans`,`Montserrat`,`Lato`,`Poppins`,`Oswald`,`Raleway`,`Playfair Display`,`Merriweather`,`Source Sans Pro`,`PT Sans`,`Ubuntu`,`Nunito`,`Rubik`,`Work Sans`,`Karla`,`Noto Sans`,`Fira Sans`,`DM Sans`];let se=class{getAvailableGoogleFonts(){return[...oe]}validateFontFamily(e){let t=e.toLowerCase();return oe.some(e=>e.toLowerCase()===t)}};se=x([(0,c.injectable)()],se);var ce=class{tail=Promise.resolve();currentActiveCount=0;currentPendingCount=0;async run(e){let t=this.tail,n,r=new Promise(e=>{n=e});this.currentPendingCount+=1,this.tail=t.then(()=>r),await t,--this.currentPendingCount,this.currentActiveCount+=1;try{return await e()}finally{--this.currentActiveCount,n()}}getStatus(){return{activeCount:this.currentActiveCount,pendingCount:this.currentPendingCount}}};const w=(0,m.promisify)(l.execFile);let T=class{async getVideoDuration(e){try{let{stdout:t}=await w(`ffprobe`,[`-v`,`error`,`-show_entries`,`format=duration`,`-of`,`json`,e]),n=JSON.parse(t),r=Number.parseFloat(n.format?.duration??`0`);if(Number.isNaN(r)||r<=0)throw Error(`Invalid duration for video: ${e}`);return r}catch(t){throw Error(`Failed to get video duration for ${e}: ${t instanceof Error?t.message:String(t)}`,{cause:t})}}async getAudioDuration(e){try{let{stdout:t}=await w(`ffprobe`,[`-v`,`error`,`-show_entries`,`format=duration`,`-of`,`json`,e]),n=JSON.parse(t),r=Number.parseFloat(n.format?.duration??`0`);if(Number.isNaN(r)||r<=0)throw Error(`Invalid duration for audio: ${e}`);return r}catch(t){throw Error(`Failed to get audio duration for ${e}: ${t instanceof Error?t.message:String(t)}`,{cause:t})}}async getVideoDimensions(e){try{let{stdout:t}=await w(`ffprobe`,[`-v`,`error`,`-select_streams`,`v:0`,`-show_entries`,`stream=width,height`,`-of`,`json`,e]),n=JSON.parse(t).streams?.[0];if(!n?.width||!n?.height)throw Error(`No video stream found in: ${e}`);return{width:Number(n.width),height:Number(n.height)}}catch(t){throw Error(`Failed to get video dimensions for ${e}: ${t instanceof Error?t.message:String(t)}`,{cause:t})}}async canDecode(e){try{return await w(`ffprobe`,[`-v`,`error`,`-show_entries`,`format=duration`,`-of`,`json`,e]),!0}catch{return!1}}};T=x([(0,c.injectable)()],T);const E=b.z.coerce.number(),D=b.z.coerce.number().int(),O=b.z.preprocess(e=>{if(typeof e!=`string`)return e;let t=e.trim().toLowerCase();return t===`true`?!0:t===`false`?!1:e},b.z.boolean()),k=b.z.string().min(1).refine(e=>/^(\/|file:|https?:|data:|blob:)/i.test(e),{message:`src must be an absolute filesystem path or a file:// / http(s):// / data: / blob: URL — relative paths are not allowed.`}),le=b.z.object({frame:D.nonnegative(),volume:E.min(0).max(1)}),A=b.z.object({type:b.z.enum([`interpolate`,`spring`]).default(`interpolate`),easing:b.z.enum([`linear`,`ease-in`,`ease-out`,`ease-in-out`]).optional(),springConfig:b.z.object({mass:E.positive().default(1),damping:E.positive().default(10),stiffness:E.positive().default(100)}).optional(),delay:D.nonnegative().default(0)}),ue=b.z.object({type:b.z.enum([`fade`,`slide`,`wipe`,`flip`,`clockWipe`,`none`]).default(`fade`),durationInFrames:D.positive().default(15),direction:b.z.enum([`from-left`,`from-right`,`from-top`,`from-bottom`]).optional()}),j={startFrame:D.nonnegative(),durationInFrames:D.positive(),premountFor:D.nonnegative().default(30),entrance:A.optional(),exit:A.optional(),transition:ue.optional()},de=b.z.object({type:b.z.literal(`video`),...j,src:k,volume:E.min(0).max(1).optional(),playbackRate:E.positive().optional(),muted:O.optional(),loop:O.optional(),trimBefore:E.nonnegative().optional(),trimAfter:E.nonnegative().optional(),transparent:O.optional(),noFadeIn:O.optional(),style:b.z.record(b.z.string(),b.z.unknown()).optional()}),fe=b.z.object({type:b.z.literal(`image`),...j,src:k,fit:b.z.enum([`contain`,`cover`,`fill`]).optional(),noFadeIn:O.optional(),baseScale:E.positive().optional(),transformOriginX:b.z.string().optional(),transformOriginY:b.z.string().optional(),style:b.z.record(b.z.string(),b.z.unknown()).optional()}),pe=b.z.object({type:b.z.literal(`text`),...j,text:b.z.string(),fontSize:E.positive().default(80),fontFamily:b.z.string().default(`sans-serif`),fontWeight:b.z.union([b.z.string(),E]).optional(),color:b.z.string().default(`#ffffff`),backgroundColor:b.z.string().optional(),position:b.z.enum([`top`,`center`,`bottom`]).default(`center`),animation:b.z.enum([`none`,`fade`,`slide`,`typewriter`,`highlight`]).default(`none`),highlightColor:b.z.string().optional(),highlightWord:b.z.string().optional(),style:b.z.record(b.z.string(),b.z.unknown()).optional()}),me=b.z.object({type:b.z.literal(`audio`),...j,src:k,volume:E.min(0).max(1).optional(),volumeAutomation:b.z.array(le).optional(),playbackRate:E.positive().optional(),muted:O.optional(),loop:O.optional(),trimBefore:E.nonnegative().optional(),trimAfter:E.nonnegative().optional(),toneFrequency:E.positive().optional()}),he=b.z.object({type:b.z.literal(`subtitle`),...j,text:b.z.string(),position:b.z.enum([`top`,`center`,`bottom`]).default(`bottom`),animation:b.z.enum([`none`,`fade`,`slide`]).default(`fade`),fontSize:E.positive().default(36),fontFamily:b.z.string().default(`Arial, sans-serif`),color:b.z.string().default(`#ffffff`),backgroundColor:b.z.string().default(`rgba(0, 0, 0, 0.7)`),style:b.z.record(b.z.string(),b.z.unknown()).optional()}),ge=b.z.object({type:b.z.literal(`gif`),...j,src:k,width:E.positive().optional(),height:E.positive().optional(),fit:b.z.enum([`contain`,`cover`,`fill`]).optional(),playbackRate:E.positive().optional(),loopBehavior:b.z.enum([`loop`,`pause-after-finish`]).optional(),style:b.z.record(b.z.string(),b.z.unknown()).optional()}),_e=b.z.object({type:b.z.literal(`lottie`),...j,src:k,width:E.positive().optional(),height:E.positive().optional(),loop:O.optional(),style:b.z.record(b.z.string(),b.z.unknown()).optional()}),ve=b.z.discriminatedUnion(`type`,[de,fe,pe,me,he,ge,_e]),ye=b.z.object({text:b.z.string(),startMs:E.nonnegative(),endMs:E.nonnegative(),timestampMs:E.nonnegative().optional(),confidence:E.min(0).max(1).optional(),emphasis:b.z.enum([`none`,`keyword`,`stat`,`negation`,`cta`]).optional()}),be=ye.extend({emphasis:b.z.enum([`none`,`keyword`,`stat`,`negation`,`cta`]).default(`none`)}),xe=b.z.object({x:E.min(0).max(1).optional(),y:E.min(0).max(1).optional(),position:b.z.enum([`top`,`center`,`bottom`]).optional()}),Se=b.z.object({text:b.z.string().optional(),startMs:E.nonnegative(),endMs:E.nonnegative(),tokens:b.z.array(be).min(1),placement:xe.optional()}),Ce=b.z.object({top:E.nonnegative().optional(),right:E.nonnegative().optional(),bottom:E.nonnegative().optional(),left:E.nonnegative().optional()}),we=b.z.object({color:b.z.string().default(`rgba(0, 0, 0, 0.85)`),blur:E.nonnegative().default(8),offsetX:E.default(0),offsetY:E.default(3)}),Te=b.z.object({captions:b.z.array(ye).default([]),pages:b.z.array(Se).optional(),style:b.z.enum([`tiktok`,`standard`,`karaoke`]).default(`tiktok`),preset:b.z.enum([`tiktok-bold`,`karaoke`,`premium-pill`,`minimal`,`ugc`]).default(`tiktok-bold`),platform:b.z.enum([`tiktok`,`reels`,`shorts`,`universal`]).default(`tiktok`),combineTokensWithinMilliseconds:E.nonnegative().default(800),maxWordsPerPage:D.positive().default(6),maxCharsPerLine:D.positive().default(22),maxLines:D.positive().default(2),maxWidthPct:E.positive().max(1).default(.86),fontSize:E.positive().default(60),minFontSize:E.positive().default(42),fontFamily:b.z.string().default(`Arial, sans-serif`),fontWeight:b.z.union([D.positive(),b.z.string()]).default(800),lineHeight:E.positive().default(1.08),color:b.z.string().default(`#ffffff`),inactiveColor:b.z.string().default(`#ffffff`),highlightColor:b.z.string().default(`#FFD700`),textColor:b.z.string().default(`#ffffff`),strokeColor:b.z.string().default(`#000000`),strokeWidth:E.nonnegative().default(5),shadow:b.z.union([O,we]).default(!0),backgroundColor:b.z.string().default(`rgba(0, 0, 0, 0)`),backgroundRadius:E.nonnegative().default(8),safeZone:Ce.optional(),position:b.z.enum([`top`,`center`,`bottom`]).default(`bottom`)}).superRefine((e,t)=>{e.captions.length===0&&(!e.pages||e.pages.length===0)&&t.addIssue({code:`custom`,message:`Caption config must include captions or pages.`,path:[`captions`]})}),Ee={src:k,volume:E.min(0).max(1).default(1),fadeInMs:E.nonnegative().default(0),fadeOutMs:E.nonnegative().default(0),trimBeforeMs:E.nonnegative().default(0),trimAfterMs:E.nonnegative().optional(),playbackRate:E.positive().default(1)},De=b.z.object({...Ee,definesTimeline:O.default(!0),durationMs:E.positive().optional()}),Oe=b.z.object({...Ee,loop:O.default(!0)}),ke=b.z.object({...Ee,atMs:E.nonnegative(),durationMs:E.positive().optional()}),Ae=b.z.object({voiceover:De.optional(),music:Oe.optional(),sfx:b.z.array(ke).default([])}),je=b.z.object({family:b.z.string(),source:b.z.enum([`google`,`local`]).default(`google`),weights:b.z.array(D.positive()).optional(),url:b.z.string().optional()}),Me=b.z.object({clips:b.z.array(ve).default([]),backgroundColor:b.z.string().default(`#000000`),fps:D.positive().default(30),width:D.positive().default(1920),height:D.positive().default(1080),captions:Te.optional(),globalTransition:ue.optional(),fonts:b.z.array(je).optional(),audio:Ae.optional()}).passthrough(),Ne=`${p.default.sep}public${p.default.sep}`,Pe=/^(https?:|data:|blob:)/i,Fe=/\b(undefined|NaN|null)\b|blur\(px\)/i,Ie={Main:{width:1920,height:1080},Vertical:{width:1080,height:1920},Square:{width:1080,height:1080}},Le=new Set([`video`,`image`,`audio`,`gif`,`lottie`]),Re=new Set([`video`,`image`,`gif`,`lottie`,`text`,`subtitle`]),ze={tiktok:480,reels:420,shorts:420,universal:480},Be={tiktok:{top:270,right:140,bottom:480,left:80},reels:{top:220,right:110,bottom:420,left:80},shorts:{top:220,right:100,bottom:420,left:80},universal:{top:240,right:140,bottom:480,left:80}};var Ve=class e extends Error{constructor(t){super(e.formatMessage(t)),this.validation=t,this.name=`RenderValidationError`}static formatMessage(e){return`Render validation failed: ${e.errors.map(e=>`${e.path??e.code}: ${e.message}`).join(`; `)}`}};let M=class{bundlePromise=null;mediaInfoService=new T;projectRoot=(0,u.existsSync)(p.default.resolve(__dirname,`../package.json`))?p.default.resolve(__dirname,`..`):p.default.resolve(__dirname,`../..`);async getServeUrl(){return this.bundlePromise||=(0,_.bundle)({entryPoint:p.default.resolve(this.projectRoot,`src/remotion/index.ts`),publicDir:p.default.resolve(this.projectRoot,`public`),webpackOverride:e=>({...e,resolve:{...e.resolve,extensionAlias:{".js":[`.ts`,`.tsx`,`.js`,`.jsx`]}}})}),this.bundlePromise}isTransientRendererNavigationError(e){let t=e instanceof Error?e.message:String(e);return t.includes(`ERR_EMPTY_RESPONSE`)||t.includes(`ERR_CONNECTION_RESET`)}async withTransientRendererRetry(e){for(let t=1;t<=2;t+=1)try{return await e()}catch(e){if(t===2||!this.isTransientRendererNavigationError(e))throw e;this.bundlePromise=null,await new Promise(e=>setTimeout(e,150))}throw Error(`Renderer retry exhausted unexpectedly.`)}get publicDir(){return p.default.resolve(this.projectRoot,`public`)}toPublicRelativePath(e){let t=p.default.normalize(e),n=t.indexOf(Ne);return n===-1?null:t.slice(n+Ne.length).split(p.default.sep).join(`/`)}toLocalFilesystemPath(e){return e.startsWith(`file://`)?(0,g.fileURLToPath)(e):p.default.isAbsolute(e)?e:null}toPublicFilesystemPath(e){let t=e.replace(/^\/+/,``).replace(/^public\//,``);return p.default.join(this.publicDir,...t.split(`/`))}resolveValidationSource(e){if(Pe.test(e))return{kind:`remote`,src:e};let t=this.toLocalFilesystemPath(e);return t?{kind:`local`,src:e,filePath:t}:{kind:`local`,src:e,filePath:this.toPublicFilesystemPath(e)}}hasExplicitDimension(e,t){return Object.prototype.hasOwnProperty.call(e,t)}voiceoverFrames(e,t){let n=e?.voiceover;if(!n||n.definesTimeline===!1||!n.durationMs)return 0;let r=Math.max(0,(n.trimAfterMs??n.durationMs)-(n.trimBeforeMs??0))/(n.playbackRate??1);return Math.ceil(r/1e3*t)}framesToSeconds(e,t){return Number((e/t).toFixed(3))}canExtendVisualClip(e){return e.type===`image`||e.type===`text`||e.type===`subtitle`||e.type===`lottie`}createVisualGapIssue({gapStart:e,gapEnd:t,fps:n,previous:r,next:i,durationInFrames:a,message:o}){let s=t-e,c={gapStartFrame:e,gapEndFrame:t,gapDurationInFrames:s,gapStartSeconds:this.framesToSeconds(e,n),gapEndSeconds:this.framesToSeconds(t,n),gapDurationSeconds:this.framesToSeconds(s,n),renderDurationInFrames:a};if(r&&(c.previousVisualClip={index:r.clipIndex,type:r.type,startFrame:r.start,endFrame:r.end,durationInFrames:r.durationInFrames,canExtendSafely:r.canExtendSafely}),i&&(c.nextVisualClip={index:i.clipIndex,type:i.type,startFrame:i.start,endFrame:i.end,durationInFrames:i.durationInFrames}),r?.canExtendSafely){let n=r.durationInFrames+s;return{code:`timeline.visual_gap`,message:o,path:`clips`,details:c,fix:{instruction:`Extend clips[${r.clipIndex}].durationInFrames from ${r.durationInFrames} to ${n} so visuals cover frames ${e}..${t}.`,edits:[{path:`inputProps.clips.${r.clipIndex}.durationInFrames`,value:n,reason:`Covers the ${s}-frame visual gap without changing audio timing.`}]}}}return{code:`timeline.visual_gap`,message:o,path:`clips`,details:c,fix:{instruction:r&&!r.canExtendSafely?`Add a still/image/text visual from frame ${e} for ${s} frames, or replace/loop the preceding visual before extending it.`:`Add a visual clip starting at frame ${e} with durationInFrames ${s}.`}}}createSummary(e,t,n){let r=t.clips.reduce((e,t)=>Math.max(e,t.startFrame+t.durationInFrames),0),i=this.voiceoverFrames(t.audio,t.fps),a=Math.max(r,i);return{compositionId:e.compositionId,width:this.hasExplicitDimension(e.inputProps,`width`)?t.width:n.width,height:this.hasExplicitDimension(e.inputProps,`height`)?t.height:n.height,fps:t.fps,durationInFrames:a,clipCount:t.clips.length}}pushBadStringIssues(e,t,n,r){if(typeof e==`string`){Fe.test(e)&&n.push({code:`${r}.invalid_value`,message:`Invalid ${r} value: ${e}`,path:t});return}if(!(!e||typeof e!=`object`)){if(Array.isArray(e)){e.forEach((e,i)=>this.pushBadStringIssues(e,`${t}.${i}`,n,r));return}Object.entries(e).forEach(([e,i])=>{this.pushBadStringIssues(i,`${t}.${e}`,n,r)})}}validateTextClip(e,t,n){`text`in e&&(e.text.trim()||n.push({code:`text.empty`,message:`Text and subtitle clips must not be empty.`,path:`${t}.text`}),this.pushBadStringIssues(e.text,`${t}.text`,n,`text`))}validateStyle(e,t,n){`style`in e&&e.style&&this.pushBadStringIssues(e.style,`${t}.style`,n,`style`)}isSourceClip(e){return Le.has(e.type)}async validateLocalAsset(e,t,n,r,i){if(!t.filePath)return;let a;try{a=await(0,d.stat)(t.filePath)}catch{i.push({code:`asset.missing`,message:`Render asset does not exist: ${t.src}`,path:`${n}.src`});return}if(!a.isFile()){i.push({code:`asset.not_file`,message:`Render asset is not a file: ${t.src}`,path:`${n}.src`});return}try{if(e.type===`image`||e.type===`gif`){let n=await(0,y.default)(t.filePath,{animated:e.type===`gif`}).metadata();if(!n.width||!n.height)throw Error(`Missing image dimensions`)}else if(e.type===`lottie`)JSON.parse(await(0,d.readFile)(t.filePath,`utf-8`));else if(e.type===`video`){await this.mediaInfoService.getVideoDimensions(t.filePath);let a=await this.mediaInfoService.getVideoDuration(t.filePath);this.validateMediaDuration(e,a,r,n,i)}else if(e.type===`audio`){let a=await this.mediaInfoService.getAudioDuration(t.filePath);this.validateMediaDuration(e,a,r,n,i)}}catch(e){i.push({code:`asset.decode_failed`,message:`Render asset cannot be decoded: ${t.src}. ${e instanceof Error?e.message:String(e)}`,path:`${n}.src`})}}validateMediaDuration(e,t,n,r,i){let a=e.trimBefore??0,o=e.trimAfter??0,s=e.playbackRate??1;if(o>0&&o<=a){i.push({code:`media.invalid_trim`,message:`trimAfter must be greater than trimBefore when provided.`,path:r});return}if(e.loop)return;let c=t*n,l=(o>0?o-a:c-a)/s;l+2<e.durationInFrames&&i.push({code:`media.too_short`,message:`Clip duration (${e.durationInFrames} frames) exceeds available media (${Math.floor(l)} frames).`,path:r})}async validateClipAssets(e,t,n){await Promise.all(e.clips.map(async(r,i)=>{let a=`clips.${i}`;if(this.validateTextClip(r,a,n),this.validateStyle(r,a,n),!this.isSourceClip(r))return;let o=this.resolveValidationSource(r.src);if(o.kind===`remote`){t.push({code:`asset.remote_unprobed`,message:`Remote asset will be fetched during render and cannot be decoded in preflight: ${r.src}`,path:`${a}.src`});return}await this.validateLocalAsset(r,o,a,e.fps,n)}))}async validateAudioLayer(e,t,n){if(!e)return;let r=[];e.voiceover&&r.push({src:e.voiceover.src,path:`audio.voiceover.src`}),e.music&&r.push({src:e.music.src,path:`audio.music.src`}),e.sfx?.forEach((e,t)=>{r.push({src:e.src,path:`audio.sfx.${t}.src`})}),await Promise.all(r.map(async({src:e,path:r})=>{let i=this.resolveValidationSource(e);if(i.kind===`remote`){t.push({code:`audio.remote_unprobed`,message:`Remote audio asset will be fetched during render and cannot be decoded in preflight: ${e}`,path:r});return}if(i.filePath)try{if(!(await(0,d.stat)(i.filePath)).isFile()){n.push({code:`audio.not_file`,message:`Audio asset is not a file: ${e}`,path:r});return}await this.mediaInfoService.getAudioDuration(i.filePath)}catch(t){if(t.code===`ENOENT`){n.push({code:`audio.missing`,message:`Audio asset does not exist: ${e}`,path:r});return}n.push({code:`audio.decode_failed`,message:`Audio asset cannot be decoded: ${e}. ${t instanceof Error?t.message:String(t)}`,path:r})}}))}async resolveAudioDurationMs(e){let t=this.resolveValidationSource(e);if(t.kind===`remote`||!t.filePath)return null;try{return await this.mediaInfoService.getAudioDuration(t.filePath)*1e3}catch{return null}}async injectAudioDurations(e){let t=e.audio;if(!t?.voiceover||t.voiceover.durationMs)return e;let n=await this.resolveAudioDurationMs(t.voiceover.src);return n?{...e,audio:{...t,voiceover:{...t.voiceover,durationMs:n}}}:e}validateTimeline(e,t,n){let r=!!(e.audio?.voiceover||e.audio?.music||e.audio?.sfx&&e.audio.sfx.length>0);if(e.clips.length===0){if(r){n.push({code:`timeline.audio_only`,message:`Render has no visual clips; output will show backgroundColor under the audio layer.`,path:`clips`});return}t.push({code:`timeline.empty`,message:`Render must contain at least one clip.`,path:`clips`});return}let i=e.clips.map((e,t)=>({clip:e,clipIndex:t})).filter(({clip:e})=>Re.has(e.type)).map(({clip:e,clipIndex:t})=>({clipIndex:t,type:e.type,start:e.startFrame,end:e.startFrame+e.durationInFrames,durationInFrames:e.durationInFrames,canExtendSafely:this.canExtendVisualClip(e)})).sort((e,t)=>e.start-t.start);if(i.length===0){if(r){n.push({code:`timeline.audio_only`,message:`Render has no visual clips; output will show backgroundColor under the audio layer.`,path:`clips`});return}t.push({code:`timeline.no_visual`,message:`Render must contain at least one visual clip.`,path:`clips`});return}let a=e.clips.reduce((e,t)=>Math.max(e,t.startFrame+t.durationInFrames),0),o=Math.max(a,this.voiceoverFrames(e.audio,e.fps));i[0]&&i[0].start>3&&t.push(this.createVisualGapIssue({gapStart:0,gapEnd:i[0].start,fps:e.fps,next:i[0],durationInFrames:o,message:`Visual timeline starts at frame ${i[0].start}; expected coverage from frame 0.`}));let s=i[0]?.end??0,c=i[0];for(let n of i.slice(1))n.start>s+3&&t.push(this.createVisualGapIssue({gapStart:s,gapEnd:n.start,fps:e.fps,previous:c,next:n,durationInFrames:o,message:`Visual timeline has a gap from frame ${s} to ${n.start}.`})),n.end>s&&(c=n),s=Math.max(s,n.end);s+3<o&&t.push(this.createVisualGapIssue({gapStart:s,gapEnd:o,fps:e.fps,previous:c,durationInFrames:o,message:`Visual timeline ends at frame ${s}; render duration is ${o}.`}))}validateCaptions(e,t,n,r){if(!e.captions)return;let i=e.captions,a=t.durationInFrames/e.fps*1e3,o=-1,s=-1;i.captions.forEach((e,t)=>{let i=`captions.captions.${t}`;e.text.trim()||n.push({code:`captions.empty_text`,message:`Caption text must not be empty.`,path:`${i}.text`}),e.endMs<=e.startMs&&n.push({code:`captions.invalid_timing`,message:`Caption endMs must be greater than startMs.`,path:i}),e.startMs<o&&n.push({code:`captions.unsorted`,message:`Captions must be sorted by startMs.`,path:i}),e.startMs<s&&r.push({code:`captions.overlap`,message:`Caption overlaps the previous caption; prefer page/token timing for intentional karaoke overlap.`,path:i}),e.endMs>a+100&&n.push({code:`captions.out_of_range`,message:`Caption ends after render duration (${Math.round(a)}ms).`,path:i}),o=e.startMs,s=Math.max(s,e.endMs),this.pushBadStringIssues(e.text,`${i}.text`,n,`text`)}),i.pages?.forEach((t,o)=>{let s=`captions.pages.${o}`;t.endMs<=t.startMs&&n.push({code:`captions.page_invalid_timing`,message:`Caption page endMs must be greater than startMs.`,path:s}),t.endMs>a+100&&n.push({code:`captions.page_out_of_range`,message:`Caption page ends after render duration (${Math.round(a)}ms).`,path:s});let c=-1,l=-1;t.tokens.forEach((e,i)=>{let a=`${s}.tokens.${i}`;e.text.trim()||n.push({code:`captions.token_empty_text`,message:`Caption token text must not be empty.`,path:`${a}.text`}),e.endMs<=e.startMs&&n.push({code:`captions.token_invalid_timing`,message:`Caption token endMs must be greater than startMs.`,path:a}),(e.startMs<t.startMs||e.endMs>t.endMs)&&n.push({code:`captions.token_outside_page`,message:`Caption token timing must stay within its page timing.`,path:a}),e.startMs<c&&n.push({code:`captions.token_unsorted`,message:`Caption page tokens must be sorted by startMs.`,path:a}),e.startMs<l&&r.push({code:`captions.token_overlap`,message:`Caption token overlaps the previous token.`,path:a}),e.confidence!==void 0&&e.confidence<.75&&r.push({code:`captions.low_confidence`,message:`Low-confidence caption token should be reviewed before render.`,path:a}),c=e.startMs,l=Math.max(l,e.endMs),this.pushBadStringIssues(e.text,`${a}.text`,n,`text`)});let u=this.countCaptionWords(t.tokens.map(e=>e.text).join(` `));u>i.maxWordsPerPage&&r.push({code:`captions.page_too_dense`,message:`Caption page has ${u} words; configured maxWordsPerPage is ${i.maxWordsPerPage}.`,path:s});let d=t.placement?.x!==void 0,f=t.placement?.y!==void 0;if(d!==f&&r.push({code:`captions.page_partial_placement`,message:`Caption page placement should provide both x and y for predictable focal-target avoidance.`,path:`${s}.placement`}),d||f){let n={...Be[i.platform],...i.safeZone},a=n.left/e.width,o=1-n.right/e.width,c=n.top/e.height,l=1-n.bottom/e.height,u=t.placement?.x??.5,d=t.placement?.y??.5;(u<a||u>o||d<c||d>l)&&r.push({code:`captions.page_placement_safe_zone`,message:`Caption page explicit placement sits outside the configured platform safe zone.`,path:`${s}.placement`})}});let c=ze[i.platform]??480,l=i.safeZone?.bottom??c;i.position===`bottom`&&l<c&&r.push({code:`captions.safe_zone_bottom`,message:`Bottom caption safe zone ${l}px is smaller than ${i.platform} preset ${c}px.`,path:`captions.safeZone.bottom`}),i.style===`karaoke`&&!i.pages&&i.captions.some(e=>/\s/.test(e.text.trim()))&&r.push({code:`captions.karaoke_legacy_timing`,message:`Karaoke legacy captions use proportional word timing; provide pages/tokens for accurate word sync.`,path:`captions.captions`})}countCaptionWords(e){return e.trim().split(/\s+/).filter(Boolean).length}async copyToPublic(e){let t=await(0,d.stat)(e);if(!t.isFile())throw Error(`Render asset is not a file: ${e}`);let n=p.default.extname(e),r=p.default.basename(e,n).replace(/[^a-zA-Z0-9._-]/g,`-`),i=(0,h.createHash)(`sha256`).update(e).update(String(t.mtimeMs)).update(String(t.size)).digest(`hex`).slice(0,16),a=p.default.posix.join(`mcp-render-assets`,`${r}-${i}${n}`),o=p.default.join(this.publicDir,...a.split(`/`));return await(0,d.mkdir)(p.default.dirname(o),{recursive:!0}),await(0,d.copyFile)(e,o),a}async prepareValue(e){if(Array.isArray(e)){let t=!1;return{value:await Promise.all(e.map(async e=>{let n=await this.prepareValue(e);return t||=n.usesLocalAssets,n.value})),usesLocalAssets:t}}if(!e||typeof e!=`object`)return{value:e,usesLocalAssets:!1};let t=!1,n={};for(let[r,i]of Object.entries(e)){if(r===`src`&&typeof i==`string`){let e=this.toLocalFilesystemPath(i);if(e){n[r]=this.toPublicRelativePath(e)??await this.copyToPublic(e),t=!0;continue}}let e=await this.prepareValue(i);n[r]=e.value,t||=e.usesLocalAssets}return{value:n,usesLocalAssets:t}}async prepareInputProps(e){let t=await this.prepareValue(e);return{inputProps:t.value,usesLocalAssets:t.usesLocalAssets}}normalizeProvidedValues(e,t){if(Array.isArray(e)&&Array.isArray(t))return e.map((e,n)=>this.normalizeProvidedValues(e,t[n]));if(e&&t&&typeof e==`object`&&typeof t==`object`&&!Array.isArray(e)&&!Array.isArray(t)){let n={},r=t;for(let[t,i]of Object.entries(e))n[t]=this.normalizeProvidedValues(i,r[t]);return n}return t}normalizeInputProps(e){let t=Me.parse(e);return this.normalizeProvidedValues(e,t)}async validateRender(e){let t=[],n=[],r=Ie[e.compositionId];r||t.push({code:`composition.unknown`,message:`Unknown composition: ${e.compositionId}`,path:`compositionId`});let i=await this.injectAudioDurations(e.inputProps),a=Me.safeParse(i);if(!a.success)return{passed:!1,errors:a.error.issues.map(e=>({code:`schema.invalid`,message:e.message,path:e.path.join(`.`)})),warnings:n,summary:{compositionId:e.compositionId,width:r?.width??0,height:r?.height??0,fps:0,durationInFrames:0,clipCount:0}};let o=a.data,s=r??{width:o.width,height:o.height},c=this.createSummary(e,o,s);return this.hasExplicitDimension(e.inputProps,`width`)&&o.width!==s.width&&t.push({code:`composition.width_mismatch`,message:`${e.compositionId} expects width ${s.width}, received ${o.width}.`,path:`width`}),this.hasExplicitDimension(e.inputProps,`height`)&&o.height!==s.height&&t.push({code:`composition.height_mismatch`,message:`${e.compositionId} expects height ${s.height}, received ${o.height}.`,path:`height`}),this.validateTimeline(o,t,n),this.validateCaptions(o,c,t,n),await this.validateClipAssets(o,n,t),await this.validateAudioLayer(o.audio,n,t),{passed:t.length===0,errors:t,warnings:n,summary:c}}async render(e){let t=await this.validateRender(e);if(!t.passed)throw new Ve(t);if(e.dryRun)return{outputPath:e.outputPath,dryRun:!0,validation:t};let n=await this.injectAudioDurations(e.inputProps),r=this.normalizeInputProps(n),i=await this.prepareInputProps(r);return i.usesLocalAssets&&(this.bundlePromise=null),await this.withTransientRendererRetry(async()=>{let t=await this.getServeUrl();await(0,v.renderMedia)({composition:await(0,v.selectComposition)({serveUrl:t,id:e.compositionId,inputProps:i.inputProps}),serveUrl:t,codec:e.codec??`h264`,outputLocation:e.outputPath,inputProps:i.inputProps})}),{outputPath:e.outputPath,validation:t}}async renderStill(e){let t=await this.injectAudioDurations(e.inputProps),n=this.normalizeInputProps(t),r=await this.prepareInputProps(n);return r.usesLocalAssets&&(this.bundlePromise=null),await this.withTransientRendererRetry(async()=>{let t=await this.getServeUrl();await(0,v.renderStill)({composition:await(0,v.selectComposition)({serveUrl:t,id:e.compositionId,inputProps:r.inputProps}),serveUrl:t,output:e.outputPath,frame:e.frame??0,imageFormat:e.imageFormat??`png`,inputProps:r.inputProps})}),{outputPath:e.outputPath}}};M=x([(0,c.injectable)()],M);const He=(0,m.promisify)(l.execFile),Ue=[`af_sarah`,`af_nicole`,`af_bella`,`af_sky`,`am_adam`,`am_michael`,`bf_emma`,`bf_isabella`,`bm_george`,`bm_lewis`];let N=class{async isAvailable(){try{return await He(`kokoro-tts`,[`--version`]),!0}catch{return!1}}async generateVoiceover(e){let{text:t,voice:n=`af_sarah`,speed:r=1,outputPath:i}=e,a=await d.default.mkdtemp(p.default.join(f.default.tmpdir(),`kokoro-`)),o=p.default.join(a,`input.txt`);try{return await d.default.writeFile(o,t,`utf-8`),await He(`kokoro-tts`,[o,i,`--voice`,n,`--speed`,r.toString()]),{outputPath:i}}catch(e){throw Error(`Failed to generate voiceover: ${e instanceof Error?e.message:String(e)}`,{cause:e})}finally{try{await d.default.rm(a,{recursive:!0,force:!0})}catch{}}}listVoices(){return[...Ue]}};N=x([(0,c.injectable)()],N);const P={AceStepMusicService:Symbol.for(`AceStepMusicService`),RenderService:Symbol.for(`RenderService`),MediaInfoService:Symbol.for(`MediaInfoService`),CaptionService:Symbol.for(`CaptionService`),FontService:Symbol.for(`FontService`),VoiceoverService:Symbol.for(`VoiceoverService`),VideoDownloadService:Symbol.for(`VideoDownloadService`),VideoAnalysisService:Symbol.for(`VideoAnalysisService`),VideoContextService:Symbol.for(`VideoContextService`),ProxyUrl:Symbol.for(`ProxyUrl`),Tool:Symbol.for(`Tool`)};function F(e,t){if(typeof Reflect==`object`&&typeof Reflect.metadata==`function`)return Reflect.metadata(e,t)}function I(e,t){return function(n,r){t(n,r,e)}}const L=(0,m.promisify)(l.execFile);let R=class{constructor(e=null){this.proxyUrl=e}getProxyArgs(){let e=this.proxyUrl||process.env.YTDLP_PROXY;return e?[`--proxy`,e]:[]}async ensureYtDlp(){try{let{stdout:e}=await L(`which`,[`yt-dlp`]);return e.trim()}catch{throw Error(`yt-dlp is not installed. Install it with: brew install yt-dlp`)}}async search(e,t){let n=await this.ensureYtDlp(),r=`ytsearch${t}:${e}`,{stdout:i}=await L(n,[...this.getProxyArgs(),r,`--flat-playlist`,`--print`,`%(id)s %(title)s %(duration)s %(url)s %(channel)s %(view_count)s %(upload_date)s`,`--no-warnings`],{timeout:3e4});return i.trim().split(`
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/video-editor-mcp",
|
|
3
3
|
"description": "MCP server for video editing with Remotion",
|
|
4
|
-
"version": "0.8.
|
|
4
|
+
"version": "0.8.4",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mcp",
|
|
@@ -26,36 +26,36 @@
|
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
29
|
-
"@remotion/bundler": "4.0.
|
|
30
|
-
"@remotion/captions": "4.0.
|
|
31
|
-
"@remotion/cli": "4.0.
|
|
32
|
-
"@remotion/fonts": "4.0.
|
|
33
|
-
"@remotion/gif": "4.0.
|
|
34
|
-
"@remotion/google-fonts": "4.0.
|
|
35
|
-
"@remotion/lottie": "4.0.
|
|
36
|
-
"@remotion/media-utils": "4.0.
|
|
37
|
-
"@remotion/renderer": "4.0.
|
|
38
|
-
"@remotion/transitions": "4.0.
|
|
29
|
+
"@remotion/bundler": "4.0.454",
|
|
30
|
+
"@remotion/captions": "4.0.454",
|
|
31
|
+
"@remotion/cli": "4.0.454",
|
|
32
|
+
"@remotion/fonts": "4.0.454",
|
|
33
|
+
"@remotion/gif": "4.0.454",
|
|
34
|
+
"@remotion/google-fonts": "4.0.454",
|
|
35
|
+
"@remotion/lottie": "4.0.454",
|
|
36
|
+
"@remotion/media-utils": "4.0.454",
|
|
37
|
+
"@remotion/renderer": "4.0.454",
|
|
38
|
+
"@remotion/transitions": "4.0.454",
|
|
39
39
|
"chalk": "5.6.2",
|
|
40
40
|
"commander": "14.0.3",
|
|
41
41
|
"inversify": "8.1.0",
|
|
42
42
|
"react": "19.2.5",
|
|
43
43
|
"react-dom": "19.2.5",
|
|
44
44
|
"reflect-metadata": "0.2.2",
|
|
45
|
-
"remotion": "4.0.
|
|
45
|
+
"remotion": "4.0.454",
|
|
46
46
|
"sharp": "0.34.5",
|
|
47
|
-
"zod": "4.
|
|
48
|
-
"@agimon-ai/foundation-port-registry": "0.8.
|
|
49
|
-
"@agimon-ai/foundation-
|
|
50
|
-
"@agimon-ai/foundation-
|
|
47
|
+
"zod": "4.4.1",
|
|
48
|
+
"@agimon-ai/foundation-port-registry": "0.8.4",
|
|
49
|
+
"@agimon-ai/foundation-validator": "0.5.4",
|
|
50
|
+
"@agimon-ai/foundation-process-registry": "0.8.4"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/node": "25.6.0",
|
|
54
54
|
"@types/react": "19.2.14",
|
|
55
|
-
"tsdown": "0.21.
|
|
55
|
+
"tsdown": "0.21.10",
|
|
56
56
|
"tsx": "4.21.0",
|
|
57
|
-
"typescript": "6.0.
|
|
58
|
-
"vitest": "4.1.
|
|
57
|
+
"typescript": "6.0.3",
|
|
58
|
+
"vitest": "4.1.5"
|
|
59
59
|
},
|
|
60
60
|
"type": "module",
|
|
61
61
|
"exports": {
|