@conceptcraft/mindframes 0.1.27 → 0.1.28
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/index.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2784,7 +2784,7 @@ execSync("${e} video generate plan --project .", { stdio: "inherit" });
|
|
|
2784
2784
|
const args = process.argv.slice(2).join(" ");
|
|
2785
2785
|
execSync("${e} video export --project . " + args, { stdio: "inherit" });
|
|
2786
2786
|
`;await ae(q(r,"plan.ts"),a,"utf-8"),await ae(q(r,"export.ts"),s,"utf-8")}async function Un(){return process.stdin.isTTY?null:new Promise(t=>{let o="",e=!1;process.stdin.setEncoding("utf-8"),process.stdin.on("data",n=>{o+=n}),process.stdin.on("end",()=>{e||(e=!0,t(o.trim()||null))}),process.stdin.on("error",()=>{e||(e=!0,t(null))}),setTimeout(()=>{!e&&!o&&(e=!0,t(null))},500)})}function Ei(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")}function Fi(t){let o={shortTitle:"Video",elements:[],audio:[],text:[],scenes:[]},e=!0;return t.forEach(n=>{let r=n.startTime*1e3,i=n.endTime*1e3,a=n.durationInSeconds*1e3;o.scenes.push({name:n.name||`Scene ${n.id}`,text:n.text,startMs:r,endMs:i}),n.imagePath?(o.elements.push({startMs:r,endMs:i,imageUrl:n.imagePath,enterTransition:"blur",exitTransition:"blur",animations:[{type:"scale",from:e?1.3:1,to:e?1:1.3,startMs:0,endMs:a}]}),e=!e):n.videoPath&&o.elements.push({startMs:r,endMs:i,videoUrl:n.videoPath,enterTransition:"blur",exitTransition:"blur",animations:[]}),n.audioPath&&o.audio.push({startMs:r,endMs:i,audioUrl:n.audioPath}),n.timestamps&&o.text.push({startMs:r,endMs:i,text:n.text,position:"bottom",animations:[],timestamps:n.timestamps})}),o}async function yt(t,o){if(t.startsWith("data:")){let r=t.match(/^data:[^;]+;base64,(.+)$/);if(!r)throw new Error("Invalid data URL format");let i=Buffer.from(r[1],"base64");await ae(o,i);return}let e=await fetch(t);if(!e.ok)throw new Error(`Failed to download: ${e.status}`);let n=await e.arrayBuffer();await ae(o,Buffer.from(n))}function Ui(t){try{let n=new URL(t).pathname.split(".").pop()?.toLowerCase();if(n&&["jpg","jpeg","png","gif","webp"].includes(n))return n}catch{}return"jpg"}var Di=new se("assets").description("Generate assets (voiceover per scene, music, images, video)").option("-s, --script <text>","Narration script (legacy single-script mode)").option("--script-file <path>","Path to script file (legacy) or scenes JSON").option("--scenes <path>","Path to scenes.json (defaults to <project>/public/scenes.json)").option("-p, --project <dir>","Project directory (defaults to current directory; uses <dir>/public for output)").option("-t, --topic <text>","Topic for image search").option("-v, --voice <name>","TTS voice ID (ElevenLabs: Rachel, Josh, Adam; OpenAI: alloy, nova; Gemini: Kore, Puck)").option("-m, --music-prompt <text>","Music description").option("-n, --num-images <number>","Number of images to search/download","5").option("-o, --output <dir>","Output directory","./public").option("-f, --format <format>","Output format: human, json, quiet","human").action(async t=>{let o=t.format,e=o==="human"?ze("Initializing...").start():null,n=t.project?Ye(process.cwd(),t.project):null;try{let r=await Un(),i=null;if(t.scenes&&!t.scriptFile&&(t.scriptFile=t.scenes),n&&(t.output=q(n,"public"),t.scriptFile?t.scriptFile=Ye(n,t.scriptFile):!t.script&&!r&&(t.scriptFile=q(n,"public","scenes.json"))),r)try{let b=JSON.parse(r);b.scenes&&Array.isArray(b.scenes)&&(i=b)}catch{}if(!i&&t.scriptFile)try{let b=await bt(t.scriptFile,"utf-8"),G=JSON.parse(b);G.scenes&&Array.isArray(G.scenes)&&(i=G)}catch{}let a=i?.voice||t.voice,s=i?.voiceId,d=i?.provider,u=i?.model,p=i?.voiceInstructions,k=i?.musicPrompt||t.musicPrompt||"uplifting background music, positive energy",y=i?.musicDuration,w=q(t.output,"audio"),$=q(t.output,"images"),I=q(t.output,"videos");e&&(e.text="Creating directories..."),await Me(w,{recursive:!0}),await Me($,{recursive:!0}),await Me(I,{recursive:!0});let T=0,x=[],D=0,S=[],f=[];if(i&&i.scenes.length>0){o==="human"&&(e?.stop(),l(`Processing ${i.scenes.length} scenes...`),e?.start());let b=i.scenes.map((z,j)=>{let re=z.script;return z.voiceStyle&&(re=`${z.voiceStyle} ${re}`),{text:re,id:`scene-${j}`}});e&&(e.text="Generating speech for all scenes...");let G=await Fo({texts:b,options:{provider:d,voice:a,voiceId:s,model:u,voiceSettings:i.voiceSettings,instructions:p}});T+=G.totalCost;let Y=0;for(let z=0;z<i.scenes.length;z++){let j=i.scenes[z],re=Ei(j.name),ee=G.results[z];e&&(e.text=`[${j.name}] Saving audio...`);let xt=q(w,`${re}.${ee.format}`);await ae(xt,ee.audioData);let we=ee.duration,Gn=Math.round(we*Ne),Ve={id:z+1,name:j.name,text:j.script,wordCount:j.script.split(/\s+/).length,startTime:Y,endTime:Y+we,durationInSeconds:we,durationInFrames:Gn,audioPath:`audio/${re}.${ee.format}`,timestamps:ee.timestamps};if(j.imageQuery){e&&(e.text=`[${j.name}] Searching image...`);try{let W=await at({query:j.imageQuery,options:{maxResults:1,size:"large",safeSearch:!0}}),Be=W.data.results.flatMap(_=>_.results);if(T+=W.data.totalCost,Be.length>0){let _=Be[0],Ge=Ui(_.url),ue=`${re}.${Ge}`,St=q($,ue);await yt(_.url,St),Ve.imagePath=`images/${ue}`,S.push({path:`images/${ue}`,url:_.url,width:_.width,height:_.height,query:j.imageQuery})}}catch(W){o==="human"&&(e?.stop(),R(`[${j.name}] Image search failed: ${W instanceof Error?W.message:"Unknown"}`),e?.start())}}if(j.videoQuery){e&&(e.text=`[${j.name}] Searching video...`);try{let W=await Ot({query:j.videoQuery,options:{maxResults:1,license:"free"}}),Be=W.data.results.flatMap(_=>_.results);if(T+=W.data.totalCost,Be.length>0){let _=Be[0],Ge=_.previewUrl||_.downloadUrl;if(Ge){let ue=`${re}.mp4`,St=q(I,ue);await yt(Ge,St),Ve.videoPath=`videos/${ue}`,f.push({path:`videos/${ue}`,url:Ge,width:_.width,height:_.height,duration:_.duration,query:j.videoQuery})}}}catch(W){o==="human"&&(e?.stop(),R(`[${j.name}] Video search failed: ${W instanceof Error?W.message:"Unknown"}`),e?.start())}}if(x.push(Ve),Y+=we,D+=we,o==="human"){e?.stop();let W=[`audio: ${we.toFixed(1)}s`,Ve.imagePath?"image":null,Ve.videoPath?"video":null].filter(Boolean).join(", ");g(` ${j.name}: ${W}`),e?.start()}}}else{let b=t.script;if(t.scriptFile)try{b=await bt(t.scriptFile,"utf-8")}catch(ee){e?.stop(),c(`Failed to read script file: ${ee instanceof Error?ee.message:"Unknown error"}`),process.exit(v.INVALID_INPUT)}(!b||b.trim().length===0)&&(e?.stop(),c("Provide scenes via stdin JSON, --scenes/--script-file with scenes JSON, or --script for legacy mode"),process.exit(v.INVALID_INPUT)),b=b.trim();let G=t.topic||b.split(".")[0].slice(0,50);e&&(e.text="Generating voiceover...");let Y=await rt({text:b,options:{voice:a}}),z=q(w,`voiceover.${Y.format}`);await ae(z,Y.audioData),T+=Y.cost,D=Y.duration;let j=Ii(b);x=Ri(j,Y.duration,Ne,Y.timestamps).map((ee,xt)=>({...ee,name:`Section${xt+1}`,audioPath:`audio/voiceover.${Y.format}`})),o==="human"&&(e?.stop(),g(`Voiceover: ${z} (${Y.duration.toFixed(1)}s)`),e?.start())}e&&(e.text="Creating timeline...");let A=Fi(x),B=Math.max(A.audio.length>0?Math.max(...A.audio.map(b=>b.endMs)):0,A.text.length>0?Math.max(...A.text.map(b=>b.endMs)):0,A.elements.length>0?Math.max(...A.elements.map(b=>b.endMs)):0),H=B/1e3,ne=y?Math.min(300,Math.max(3,y)):Math.min(300,Math.ceil(H));console.log("[Music Generation] Requesting music:",{prompt:k,requestedDuration:ne,totalAudioDuration:D,actualVideoDuration:H,timelineDurationMs:B});let be,qe;e&&(e.text="Generating music and thumbnail...");let qn=`YouTube thumbnail style: BIG BOLD short headline text (like "$50K/MONTH"), dramatic engaging scene, arrows pointing to key elements, high contrast, vibrant colors, clean composition, 16:9. Video context: ${x.map(b=>b.text).join(" ")}`,vt=[],Vn=(async()=>{if(ne<3)return o==="human"&&(e?.stop(),R(`Video duration (${H.toFixed(1)}s) is too short for music generation (minimum 3s).`),e?.start()),null;try{let b=await it({prompt:k,duration:ne});if(b.status!=="completed"&&b.status!=="failed"&&(b=await de(()=>_e(b.requestId),60,2e3)),b.status==="failed")throw new Error(b.error||"Unknown error");let G=q(w,"music.mp3");return b.audioUrl&&await yt(b.audioUrl,G),{path:"audio/music.mp3",duration:b.duration||ne,prompt:k,cost:b.cost||0}}catch(b){return o==="human"&&(e?.stop(),R(`Music generation failed: ${b.message}`),e?.start()),null}})();vt.push(Vn);let Bn=(async()=>{try{let b=await Lo({prompt:qn,options:{width:1280,height:720}});if(b.success&&b.data.url){let G=q(t.output,"thumbnail.jpg");return await yt(b.data.url,G),T+=b.data.cost||0,G}return null}catch(b){return o==="human"&&(e?.stop(),R(`Thumbnail generation failed: ${b.message}`),e?.start()),null}})();vt.push(Bn);let[ve,to]=await Promise.all(vt);ve&&(be=ve,T+=ve.cost||0,o==="human"&&(e?.stop(),g(`Music: ${q(w,"music.mp3")} (${ve.duration}s)`),ve.duration<H&&R(`Music duration (${ve.duration.toFixed(1)}s) is shorter than video duration (${H.toFixed(1)}s).`),e?.start())),to&&(qe=to,o==="human"&&(e?.stop(),g(`Thumbnail: ${qe}`),e?.start())),e&&(e.text="Writing manifest...");let oo=Math.round(H*Ne),no={music:be,thumbnail:qe?"thumbnail.jpg":void 0,images:S,videos:f,scenes:x,timeline:A,totalDurationInFrames:oo,fps:Ne,totalCost:T,createdAt:new Date().toISOString()},wt=q(t.output,"video-manifest.json");if(await ae(wt,JSON.stringify(no,null,2)),e?.stop(),o==="json"){V(no);return}if(o==="quiet"){console.log(wt);return}console.log(),g("Video assets created successfully!"),console.log(),l(`Scenes: ${x.length} (${oo} frames at ${Ne}fps)`);for(let b of x){let G=[b.audioPath?"audio":null,b.imagePath?"image":null,b.videoPath?"video":null].filter(Boolean).join(", ");l(` - ${b.name}: ${b.durationInSeconds.toFixed(1)}s [${G}]`)}l(`Music: ${be?.path} (${be?.duration}s)`),l(`Manifest: ${wt}`),console.log(),l(`Total cost: $${T.toFixed(4)}`)}catch(r){e?.stop(),c(r instanceof Error?r.message:"Unknown error"),process.exit(v.GENERAL_ERROR)}}),Li=new se("find").description("Find stock video clips (supporting)").argument("<query>","Search query").option("-n, --max-results <count>","Maximum number of results","10").option("-o, --orientation <type>","Video orientation: landscape, portrait, square, any","any").option("-l, --license <type>","License type: free, premium, any","free").option("-f, --format <format>","Output format: human, json, quiet","human").action(async(t,o)=>{let{maxResults:e,orientation:n,license:r,format:i}=o,a=i==="human"?ze("Finding videos...").start():null;try{let s=await Ot({query:t,options:{maxResults:parseInt(e,10),orientation:n,license:r}});a?.stop();let d=s.data.results.flatMap(u=>u.results);if(i==="json"){V(s);return}if(i==="quiet"){d.forEach(u=>{console.log(u.previewUrl||u.thumbnailUrl)});return}if(d.length===0){l("No videos found");return}g(`Found ${d.length} videos for "${t}"`),console.log(),d.forEach((u,p)=>{console.log(`[${p+1}] ${u.title}`),console.log(` URL: ${u.previewUrl||u.thumbnailUrl}`),console.log(` Duration: ${u.duration}s | Size: ${u.width}x${u.height}`),console.log(` Provider: ${u.provider}`),console.log()}),l(`Total cost: $${s.data.totalCost.toFixed(4)}`)}catch(s){a?.stop(),c(s instanceof Error?s.message:"Unknown error"),process.exit(v.GENERAL_ERROR)}}),Ni=new se("new").description("Create a new video project from a template").argument("<name>","Project directory name").option("-t, --template <repo>","GitHub repo (user/repo#commit)",Ci).option("--type <type>","Video type: youtube (16:9), tiktok (9:16), or audiogram (1:1)","youtube").option("--no-install","Skip dependency install").option("-f, --format <format>","Output format: human, json, quiet","human").action(async(t,o)=>{let e=o.format,n=e==="human"?ze("Initializing video project...").start():null;try{let r=Le();await Me(r,{recursive:!0});let i=ht(t),a=o.type,s=await Yt();if(s.includes(t)){let w=En(t,s);n?.stop(),c(`Project "${t}" already exists at: ${i}`),l(`Try: ${m.commands[0]} video generate new ${w}`),process.exit(v.INVALID_INPUT)}/^[a-zA-Z0-9_-]+\/[a-zA-Z0-9_.-]+(#[a-zA-Z0-9_.\/-]+)?$/.test(o.template)||(n?.stop(),c(`Invalid template format: "${o.template}". Expected format: owner/repo or owner/repo#branch`),process.exit(v.INVALID_INPUT)),["youtube","tiktok","audiogram"].includes(a)||(n?.stop(),c(`Invalid type "${a}". Use youtube, tiktok, or audiogram.`),process.exit(v.INVALID_INPUT)),n&&(n.text=`Cloning template from ${o.template}...`);let[u,p]=o.template.split("#"),k=p?`-b ${p}`:"";try{je(`git clone ${k} --depth 1 https://github.com/${u}.git "${i}"`,{stdio:"pipe"}),await Xt(q(i,".git"),{recursive:!0,force:!0})}catch(w){n?.stop(),c(`Failed to clone template: ${w instanceof Error?w.message:"Unknown error"}`),process.exit(v.GENERAL_ERROR)}e==="human"&&(n?.stop(),g(`Template downloaded to ${t}/`),n?.start());let y;try{y=await Ti(i)}catch{n?.stop(),c("template.manifest.json not found or invalid in template repo"),process.exit(v.INVALID_INPUT)}if(y.propsSchema&&y.propsSchema!=="video-plan.v1"&&(n?.stop(),c(`Template propsSchema must be video-plan.v1 (found ${y.propsSchema})`),process.exit(v.INVALID_INPUT)),n&&(n.text="Writing scaffold files..."),await Oi(i,a,m.commands[0]),o.install){let w=Fn()?"bun":"npm";n&&(n.text=`Installing dependencies with ${w}...`),await new Promise(($,I)=>{let T=xi(w,["install"],{cwd:i,stdio:"pipe",shell:!0});T.on("close",x=>{x===0?$():I(new Error(`${w} install failed with code ${x}`))}),T.on("error",I)}),e==="human"&&(n?.stop(),g("Dependencies installed"),n?.start())}if(n?.stop(),e==="json"){V({name:t,path:i,template:o.template,type:a,installed:o.install});return}if(e==="quiet"){console.log(i);return}console.log(),g(`Video project "${t}" created successfully!`),l(`Location: ${i}`),a==="tiktok"?l("Format: TikTok/Reels/Shorts (1080x1920 @ 30fps)"):a==="audiogram"?l("Format: Audiogram (1080x1080 @ 30fps)"):l("Format: YouTube (1920x1080 @ 30fps)"),console.log(),l("Next steps:"),l(` cd ${i}`),o.install||l(` ${Fn()?"bun":"npm"} install`),l(" bun run dev # Preview in Remotion Studio"),l(` ${m.commands[0]} video generate assets --scenes public/scenes.json`),l(` ${m.commands[0]} video generate plan`)}catch(r){n?.stop(),c(r instanceof Error?r.message:"Unknown error"),process.exit(v.GENERAL_ERROR)}}),ji=new se("plan").description("Generate video plan from context (via stdin or --context)").option("-c, --context <text>","Context for plan generation").option("-o, --output <path>","Save plan to file").option("-b, --branding <path>","Branding JSON file to include").action(async t=>{let o=ze("Generating video plan...").start();try{let e=t.context;if(!e){let a=await Un();a&&(e=a)}e||(o.stop(),c("Provide context via stdin or --context flag"),process.exit(v.INVALID_INPUT));let n;if(t.branding)try{n=await bt(t.branding,"utf-8")}catch{o.stop(),c(`Could not read branding file: ${t.branding}`),process.exit(v.INVALID_INPUT)}let r=await Mo({context:e,branding:n});o.stop(),r.success||(c(r.error||"Failed to generate plan"),process.exit(v.GENERAL_ERROR));let i=r.data;t.output?(await ae(t.output,i),g(`Plan saved to ${t.output}`)):console.log(i)}catch(e){o.stop(),c(e instanceof Error?e.message:"Unknown error"),process.exit(v.GENERAL_ERROR)}}),Mi=new se("generate").description("Generate parts of a video project").addCommand(Ni).addCommand(Di).addCommand(ji),qi=new se("projects").description("List all video projects").option("-f, --format <format>","Output format: human, json","human").action(async t=>{let o=await Yt();if(t.format==="json"){V({projectsDir:Le(),projects:o.map(e=>({name:e,path:ht(e)}))});return}if(o.length===0){l("No video projects found"),l(`Projects are stored in: ${Le()}`);return}console.log(`
|
|
2787
|
-
Video Projects:`),console.log("-".repeat(50));for(let e of o)console.log(` ${e}`),console.log(` ${ht(e)}`);console.log()}),Vi=new se("inject").description("Inject thumbnail into video (first frame + file icon)").requiredOption("-i, --video <path>","Input video file").requiredOption("-t, --thumbnail <path>","Thumbnail image").option("-o, --output <path>","Output video (default: video-with-thumb.mp4)").option("-f, --format <format>","Output format: human, json, quiet","human").action(async t=>{let o=t.format,e=o==="human"?ze("Injecting thumbnail...").start():null;try{let n=Ye(t.video),r=Ye(t.thumbnail),i=t.output?Ye(t.output):n.replace(/\.mp4$/,"-with-thumb.mp4");await zt(n),await zt(r);let a=$i;if(a)try{await zt(a)}catch{a=null}if(!a)try{a=je("which ffmpeg",{encoding:"utf8"}).trim()}catch{throw new Error("ffmpeg not found. Install ffmpeg or ffmpeg-static.")}let s=Si(a,["-i",n],{encoding:"utf8"});if(s.error)throw new Error(`Failed to probe video: ${s.error.message}`);let d=(s.stderr??"").match(/(\d{2,5})x(\d{2,5})/);if(!d)throw new Error("Could not detect video dimensions");let[,u,p]=d;e&&(e.text="Creating thumbnail frame...");let k="/tmp/cc-thumb-frame.mp4";je(`${a} -y -loop 1 -i "${r}" -vf "scale=${u}:${p}:force_original_aspect_ratio=decrease,pad=${u}:${p}:(ow-iw)/2:(oh-ih)/2,setsar=1" -t 0.033 -r 30 -c:v libx264 -pix_fmt yuv420p "${k}"`,{stdio:"pipe"}),e&&(e.text="Concatenating with video...");let y="/tmp/cc-concat-video.mp4";if(je(`${a} -y -i "${k}" -i "${n}" -filter_complex "[0:v][1:v]concat=n=2:v=1:a=0[v]" -map "[v]" -map 1:a -c:v libx264 -preset ultrafast -crf 18 -c:a copy "${y}"`,{stdio:"pipe"}),e&&(e.text="Adding file icon thumbnail..."),je(`${a} -y -i "${y}" -i "${r}" -map 0 -map 1 -c copy -c:v:1 png -disposition:v:1 attached_pic "${i}"`,{stdio:"pipe"}),await Xt(k,{force:!0}),await Xt(y,{force:!0}),e?.stop(),o==="json"){V({success:!0,output:i});return}if(o==="quiet"){console.log(i);return}g(`Thumbnail injected: ${i}`)}catch(n){e?.stop(),c(n instanceof Error?n.message:"Unknown error"),process.exit(v.GENERAL_ERROR)}}),Bi=new se("thumbnail").description("Thumbnail operations").addCommand(Vi),Dn=new se("video").description("Video generation commands").addCommand(Mi).addCommand(Li).addCommand(qi).addCommand(Bi);import{Command as Gi}from"commander";import _i from"ora";import{writeFile as Wi}from"fs/promises";var Ln=new Gi("scrape").description("Extract content from a URL").argument("<url>","URL to scrape").option("-o, --output <path>","Save content to file").option("-f, --format <format>","Output format: human, json, quiet","human").action(async(t,o)=>{let e=o.format,n=e==="human"?_i("Scraping URL...").start():null;try{let r=await No(t);n?.stop(),r.success||(c(r.error||"Failed to scrape URL"),process.exit(v.GENERAL_ERROR));let i=r.data;if(o.output&&(await Wi(o.output,i.content,"utf-8"),e==="human"&&g(`Content saved to: ${o.output}`)),e==="json"){V(i);return}if(e==="quiet"){console.log(i.content);return}i.title&&(console.log(),console.log(`Title: ${i.title}`)),i.metadata?.description&&console.log(`Description: ${i.metadata.description}`),console.log(`URL: ${i.url}`),console.log(`Tokens: ~${i.metadata?.tokenUsage?.toLocaleString()||"unknown"}`),i.warning&&R(i.warning),o.output||(console.log(),console.log("--- Content ---"),console.log(i.content)),i.cost&&i.cost>0&&l(`Cost: $${i.cost.toFixed(6)}`)}catch(r){n?.stop(),c(r instanceof Error?r.message:"Unknown error"),process.exit(v.GENERAL_ERROR)}});import{Command as eo}from"commander";import Qt from"ora";import{writeFile as Nn}from"fs/promises";function Zt(t,o){if(o==="json"){V(t);return}if(o==="quiet"){t.audioUrl?console.log(t.audioUrl):t.requestId?console.log(t.requestId):console.log(t.id);return}l(`Request ID: ${t.requestId||t.id}`),l(`Status: ${t.status}`),t.duration&&l(`Duration: ${t.duration}s`),t.audioUrl&&g(`Audio URL: ${t.audioUrl}`),t.cost!==void 0&&l(`Cost: $${t.cost.toFixed(4)}`),t.error&&c(`Error: ${t.error}`)}async function Ji(t,o){if(t.startsWith("data:")){let r=t.match(/^data:[^;]+;base64,(.+)$/);if(!r)throw new Error("Invalid data URL format");let i=Buffer.from(r[1],"base64");await Nn(o,i);return}let e=await fetch(t);if(!e.ok)throw new Error(`Failed to download: ${e.status}`);let n=await e.arrayBuffer();await Nn(o,Buffer.from(n))}var Ki=new eo("generate").description("Generate sound effects from a text prompt").requiredOption("-t, --text <text>","Sound effect description (e.g., 'thunder rumbling, rain on window')").option("-d, --duration <seconds>","Duration in seconds (0.5-30)").option("-p, --provider <provider>","Provider (elevenlabs)","elevenlabs").option("--prompt-influence <value>","How closely to follow prompt (0-1)","0.3").option("-l, --loop","Generate seamless looping audio",!1).option("--format <format>","Audio format: mp3, wav, ogg","mp3").option("-o, --output <path>","Output file path").option("--no-wait","Do not wait for completion").option("-f, --output-format <format>","Output format: human, json, quiet","human").action(async t=>{let o;t.duration&&(o=parseFloat(t.duration),(isNaN(o)||o<.5||o>30)&&(c("Duration must be between 0.5 and 30 seconds"),process.exit(v.INVALID_INPUT)));let e;t.promptInfluence&&(e=parseFloat(t.promptInfluence),(isNaN(e)||e<0||e>1)&&(c("Prompt influence must be between 0 and 1"),process.exit(v.INVALID_INPUT)));let n=t.outputFormat,r=n==="human"?Qt("Generating sound effects...").start():null;try{let i=await jo({text:t.text,duration:o,options:{provider:t.provider,promptInfluence:e,loop:t.loop,format:t.format}});if(!t.wait){r?.stop(),Zt(i,n);return}let a=i;if(i.status!=="completed"&&i.status!=="failed"){let s=i.requestId||i.id;r&&(r.text=`Processing (ID: ${s})...`),a=await de(()=>Et(s),60,2e3)}if(r?.stop(),a.status==="failed"&&(c(a.error||"Sound effects generation failed"),process.exit(v.GENERAL_ERROR)),Zt(a,n),t.output&&a.audioUrl){let s=n==="human"?Qt("Downloading...").start():null;try{await Ji(a.audioUrl,t.output),s?.stop(),n==="human"&&g(`Saved to: ${t.output}`)}catch(d){s?.stop(),R(`Failed to download: ${d instanceof Error?d.message:"Unknown error"}`)}}}catch(i){r?.stop(),c(i instanceof Error?i.message:"Unknown error"),process.exit(v.GENERAL_ERROR)}}),Hi=new eo("status").description("Check status of a sound effects generation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet","human").action(async(t,o)=>{let e=o.format==="human"?Qt("Checking status...").start():null;try{let n=await Et(t);e?.stop(),Zt(n,o.format)}catch(n){e?.stop(),c(n instanceof Error?n.message:"Unknown error"),process.exit(v.GENERAL_ERROR)}}),jn=new eo("sfx").description("Sound effects generation commands").addCommand(Ki).addCommand(Hi);var zi="0.1.
|
|
2787
|
+
Video Projects:`),console.log("-".repeat(50));for(let e of o)console.log(` ${e}`),console.log(` ${ht(e)}`);console.log()}),Vi=new se("inject").description("Inject thumbnail into video (first frame + file icon)").requiredOption("-i, --video <path>","Input video file").requiredOption("-t, --thumbnail <path>","Thumbnail image").option("-o, --output <path>","Output video (default: video-with-thumb.mp4)").option("-f, --format <format>","Output format: human, json, quiet","human").action(async t=>{let o=t.format,e=o==="human"?ze("Injecting thumbnail...").start():null;try{let n=Ye(t.video),r=Ye(t.thumbnail),i=t.output?Ye(t.output):n.replace(/\.mp4$/,"-with-thumb.mp4");await zt(n),await zt(r);let a=$i;if(a)try{await zt(a)}catch{a=null}if(!a)try{a=je("which ffmpeg",{encoding:"utf8"}).trim()}catch{throw new Error("ffmpeg not found. Install ffmpeg or ffmpeg-static.")}let s=Si(a,["-i",n],{encoding:"utf8"});if(s.error)throw new Error(`Failed to probe video: ${s.error.message}`);let d=(s.stderr??"").match(/(\d{2,5})x(\d{2,5})/);if(!d)throw new Error("Could not detect video dimensions");let[,u,p]=d;e&&(e.text="Creating thumbnail frame...");let k="/tmp/cc-thumb-frame.mp4";je(`${a} -y -loop 1 -i "${r}" -vf "scale=${u}:${p}:force_original_aspect_ratio=decrease,pad=${u}:${p}:(ow-iw)/2:(oh-ih)/2,setsar=1" -t 0.033 -r 30 -c:v libx264 -pix_fmt yuv420p "${k}"`,{stdio:"pipe"}),e&&(e.text="Concatenating with video...");let y="/tmp/cc-concat-video.mp4";if(je(`${a} -y -i "${k}" -i "${n}" -filter_complex "[0:v][1:v]concat=n=2:v=1:a=0[v]" -map "[v]" -map 1:a -c:v libx264 -preset ultrafast -crf 18 -c:a copy "${y}"`,{stdio:"pipe"}),e&&(e.text="Adding file icon thumbnail..."),je(`${a} -y -i "${y}" -i "${r}" -map 0 -map 1 -c copy -c:v:1 png -disposition:v:1 attached_pic "${i}"`,{stdio:"pipe"}),await Xt(k,{force:!0}),await Xt(y,{force:!0}),e?.stop(),o==="json"){V({success:!0,output:i});return}if(o==="quiet"){console.log(i);return}g(`Thumbnail injected: ${i}`)}catch(n){e?.stop(),c(n instanceof Error?n.message:"Unknown error"),process.exit(v.GENERAL_ERROR)}}),Bi=new se("thumbnail").description("Thumbnail operations").addCommand(Vi),Dn=new se("video").description("Video generation commands").addCommand(Mi).addCommand(Li).addCommand(qi).addCommand(Bi);import{Command as Gi}from"commander";import _i from"ora";import{writeFile as Wi}from"fs/promises";var Ln=new Gi("scrape").description("Extract content from a URL").argument("<url>","URL to scrape").option("-o, --output <path>","Save content to file").option("-f, --format <format>","Output format: human, json, quiet","human").action(async(t,o)=>{let e=o.format,n=e==="human"?_i("Scraping URL...").start():null;try{let r=await No(t);n?.stop(),r.success||(c(r.error||"Failed to scrape URL"),process.exit(v.GENERAL_ERROR));let i=r.data;if(o.output&&(await Wi(o.output,i.content,"utf-8"),e==="human"&&g(`Content saved to: ${o.output}`)),e==="json"){V(i);return}if(e==="quiet"){console.log(i.content);return}i.title&&(console.log(),console.log(`Title: ${i.title}`)),i.metadata?.description&&console.log(`Description: ${i.metadata.description}`),console.log(`URL: ${i.url}`),console.log(`Tokens: ~${i.metadata?.tokenUsage?.toLocaleString()||"unknown"}`),i.warning&&R(i.warning),o.output||(console.log(),console.log("--- Content ---"),console.log(i.content)),i.cost&&i.cost>0&&l(`Cost: $${i.cost.toFixed(6)}`)}catch(r){n?.stop(),c(r instanceof Error?r.message:"Unknown error"),process.exit(v.GENERAL_ERROR)}});import{Command as eo}from"commander";import Qt from"ora";import{writeFile as Nn}from"fs/promises";function Zt(t,o){if(o==="json"){V(t);return}if(o==="quiet"){t.audioUrl?console.log(t.audioUrl):t.requestId?console.log(t.requestId):console.log(t.id);return}l(`Request ID: ${t.requestId||t.id}`),l(`Status: ${t.status}`),t.duration&&l(`Duration: ${t.duration}s`),t.audioUrl&&g(`Audio URL: ${t.audioUrl}`),t.cost!==void 0&&l(`Cost: $${t.cost.toFixed(4)}`),t.error&&c(`Error: ${t.error}`)}async function Ji(t,o){if(t.startsWith("data:")){let r=t.match(/^data:[^;]+;base64,(.+)$/);if(!r)throw new Error("Invalid data URL format");let i=Buffer.from(r[1],"base64");await Nn(o,i);return}let e=await fetch(t);if(!e.ok)throw new Error(`Failed to download: ${e.status}`);let n=await e.arrayBuffer();await Nn(o,Buffer.from(n))}var Ki=new eo("generate").description("Generate sound effects from a text prompt").requiredOption("-t, --text <text>","Sound effect description (e.g., 'thunder rumbling, rain on window')").option("-d, --duration <seconds>","Duration in seconds (0.5-30)").option("-p, --provider <provider>","Provider (elevenlabs)","elevenlabs").option("--prompt-influence <value>","How closely to follow prompt (0-1)","0.3").option("-l, --loop","Generate seamless looping audio",!1).option("--format <format>","Audio format: mp3, wav, ogg","mp3").option("-o, --output <path>","Output file path").option("--no-wait","Do not wait for completion").option("-f, --output-format <format>","Output format: human, json, quiet","human").action(async t=>{let o;t.duration&&(o=parseFloat(t.duration),(isNaN(o)||o<.5||o>30)&&(c("Duration must be between 0.5 and 30 seconds"),process.exit(v.INVALID_INPUT)));let e;t.promptInfluence&&(e=parseFloat(t.promptInfluence),(isNaN(e)||e<0||e>1)&&(c("Prompt influence must be between 0 and 1"),process.exit(v.INVALID_INPUT)));let n=t.outputFormat,r=n==="human"?Qt("Generating sound effects...").start():null;try{let i=await jo({text:t.text,duration:o,options:{provider:t.provider,promptInfluence:e,loop:t.loop,format:t.format}});if(!t.wait){r?.stop(),Zt(i,n);return}let a=i;if(i.status!=="completed"&&i.status!=="failed"){let s=i.requestId||i.id;r&&(r.text=`Processing (ID: ${s})...`),a=await de(()=>Et(s),60,2e3)}if(r?.stop(),a.status==="failed"&&(c(a.error||"Sound effects generation failed"),process.exit(v.GENERAL_ERROR)),Zt(a,n),t.output&&a.audioUrl){let s=n==="human"?Qt("Downloading...").start():null;try{await Ji(a.audioUrl,t.output),s?.stop(),n==="human"&&g(`Saved to: ${t.output}`)}catch(d){s?.stop(),R(`Failed to download: ${d instanceof Error?d.message:"Unknown error"}`)}}}catch(i){r?.stop(),c(i instanceof Error?i.message:"Unknown error"),process.exit(v.GENERAL_ERROR)}}),Hi=new eo("status").description("Check status of a sound effects generation request").argument("<id>","Request ID").option("-f, --format <format>","Output format: human, json, quiet","human").action(async(t,o)=>{let e=o.format==="human"?Qt("Checking status...").start():null;try{let n=await Et(t);e?.stop(),Zt(n,o.format)}catch(n){e?.stop(),c(n instanceof Error?n.message:"Unknown error"),process.exit(v.GENERAL_ERROR)}}),jn=new eo("sfx").description("Sound effects generation commands").addCommand(Ki).addCommand(Hi);var zi="0.1.28",U=new Yi,ce=m.commands[0];U.name(ce).description(m.description).version(zi,"-v, --version","Show version number").option("--debug","Enable debug logging").option("--no-color","Disable colored output").configureOutput({outputError:(t,o)=>{o(Z.red(t))}});U.addCommand(Ko);U.addCommand(Ho);U.addCommand(zo);U.addCommand(en);U.addCommand(tn);U.addCommand(on);U.addCommand(nn);U.addCommand(an);U.addCommand(cn);U.addCommand(dn);U.addCommand(pn);U.addCommand(fn);U.addCommand(De);U.addCommand(kn);U.addCommand(In);U.addCommand(Rn);U.addCommand(Pn);U.addCommand(Dn);U.addCommand(Ln);U.addCommand(jn);var Mn=un();Mn.commands.length>0&&U.addCommand(Mn);U.on("command:*",t=>{console.error(Z.red(`Error: Unknown command '${t[0]}'`)),console.error(),console.error(`Run '${ce} --help' to see available commands.`),process.exit(1)});U.addHelpText("after",`
|
|
2788
2788
|
${Z.bold("Examples:")}
|
|
2789
2789
|
${Z.gray("# Log in (opens browser)")}
|
|
2790
2790
|
$ ${ce} login
|