@bylqwjc/media-editor-server 1.0.15 → 1.0.18

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.
Files changed (40) hide show
  1. package/core/dist/browser.cjs +1 -1
  2. package/core/dist/browser.js +2 -2
  3. package/core/dist/chunk-MGKYVYOH.js +1 -1
  4. package/core/dist/chunk-USY6UDGL.js +1 -1
  5. package/core/dist/chunk-XCBM7P7N.js +1 -1
  6. package/core/dist/engine.cjs +1 -1
  7. package/core/dist/engine.js +1 -1
  8. package/core/dist/filerobot.cjs +1 -1
  9. package/core/dist/filerobot.js +1 -1
  10. package/core/dist/index.cjs +1 -1
  11. package/core/dist/index.js +1 -1
  12. package/core/package.json +1 -1
  13. package/core/zod/index.cjs +1 -1
  14. package/core/zod/index.js +1 -1
  15. package/core/zod/v3/ZodError.cjs +1 -1
  16. package/core/zod/v3/ZodError.js +1 -1
  17. package/core/zod/v3/errors.cjs +1 -1
  18. package/core/zod/v3/errors.js +1 -1
  19. package/core/zod/v3/external.cjs +1 -1
  20. package/core/zod/v3/helpers/errorUtil.cjs +1 -1
  21. package/core/zod/v3/helpers/errorUtil.js +1 -1
  22. package/core/zod/v3/helpers/parseUtil.cjs +1 -1
  23. package/core/zod/v3/helpers/parseUtil.js +1 -1
  24. package/core/zod/v3/helpers/util.cjs +1 -1
  25. package/core/zod/v3/helpers/util.js +1 -1
  26. package/core/zod/v3/index.cjs +1 -1
  27. package/core/zod/v3/index.js +1 -1
  28. package/core/zod/v3/locales/en.cjs +1 -1
  29. package/core/zod/v3/locales/en.js +1 -1
  30. package/core/zod/v3/types.cjs +1 -1
  31. package/core/zod/v3/types.js +1 -1
  32. package/dist/adapters/express.cjs +1 -1
  33. package/dist/adapters/express.d.ts +2 -2
  34. package/dist/adapters/express.js +1 -1
  35. package/dist/adapters/web.cjs +1 -1
  36. package/dist/adapters/web.d.ts +2 -2
  37. package/dist/adapters/web.js +1 -1
  38. package/dist/index.cjs +4 -4
  39. package/dist/index.js +3 -3
  40. package/package.json +1 -1
@@ -1 +1 @@
1
- "use strict";var p=Object.defineProperty,w=Object.getOwnPropertyDescriptor,b=Object.getOwnPropertyNames,v=Object.prototype.hasOwnProperty,O=(e,r)=>{for(var t in r)p(e,t,{get:r[t],enumerable:!0})},P=(e,r,t,a)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of b(r))!v.call(e,o)&&o!==t&&p(e,o,{get:()=>r[o],enumerable:!(a=w(r,o))||a.enumerable});return e},h=e=>P(p({},"__esModule",{value:!0}),e),d={};O(d,{toWebPosterHandler:()=>D,toWebVideoHandler:()=>B}),module.exports=h(d);var g=16;function f(e){return typeof e=="object"&&e!==null&&typeof e.type=="string"&&typeof e.arrayBuffer=="function"}async function c(e){return{type:e.type,bytes:Buffer.from(await e.arrayBuffer())}}function s(e){return e.ok?new Response(new Uint8Array(e.bytes),{status:200,headers:{"Content-Type":e.contentType,"Content-Disposition":`attachment; filename="${e.filename}"`,"Cache-Control":"no-store"}}):new Response(JSON.stringify({error:e.error,message:e.message}),{status:e.status,headers:{"Content-Type":"application/json"}})}function B(e){return async r=>{let t;try{t=await r.formData()}catch{return s({ok:!1,status:400,error:"BAD_REQUEST",message:"\u8BF7\u6C42\u4F53\u89E3\u6790\u5931\u8D25"})}const a=[];for(let n=0;n<g;n++){const i=t.get(`video_${n}`);if(!f(i))break;a.push(await c(i))}const o=[];for(let n=0;n<g;n++){const i=t.get(`audio_${n}`);if(!f(i))break;o.push(await c(i))}const l=t.get("editState"),y=t.get("overlay"),u=f(y)?y:void 0,_=u?Buffer.from(await u.arrayBuffer()):void 0;if(u&&u.type!=="image/png")return s({ok:!1,status:415,error:"BAD_OVERLAY",message:"overlay \u5FC5\u987B\u662F PNG"});const m={videos:a,audios:o,overlay:_,editStateRaw:typeof l=="string"?l:""};return s(await e.handle(m))}}function D(e){return async r=>{let t;try{t=await r.formData()}catch{return s({ok:!1,status:400,error:"BAD_REQUEST",message:"\u8BF7\u6C42\u4F53\u89E3\u6790\u5931\u8D25"})}const a=t.get("file"),o=t.get("time");return!f(a)||typeof o!="string"?s({ok:!1,status:400,error:"BAD_REQUEST",message:"\u7F3A\u5C11 file \u6216 time"}):s(await e.handle(await c(a),Number(o)))}}
1
+ "use strict";var c=Object.defineProperty,w=Object.getOwnPropertyDescriptor,B=Object.getOwnPropertyNames,h=Object.prototype.hasOwnProperty,v=(t,r)=>{for(var e in r)c(t,e,{get:r[e],enumerable:!0})},D=(t,r,e,o)=>{if(r&&typeof r=="object"||typeof r=="function")for(let a of B(r))!h.call(t,a)&&a!==e&&c(t,a,{get:()=>r[a],enumerable:!(o=w(r,a))||o.enumerable});return t},C=t=>D(c({},"__esModule",{value:!0}),t),g={};v(g,{toWebPosterHandler:()=>O,toWebVideoHandler:()=>E}),module.exports=C(g);var m=16;function f(t){return typeof t=="object"&&t!==null&&typeof t.type=="string"&&typeof t.arrayBuffer=="function"}async function y(t){return{type:t.type,bytes:Buffer.from(await t.arrayBuffer())}}function s(t){return t.ok?new Response(new Uint8Array(t.bytes),{status:200,headers:{"Content-Type":t.contentType,"Content-Disposition":`attachment; filename="${t.filename}"`,"Cache-Control":"no-store"}}):new Response(JSON.stringify({error:t.error,message:t.message}),{status:t.status,headers:{"Content-Type":"application/json"}})}function E(t){return async r=>{let e;try{e=await r.formData()}catch{return s({ok:!1,status:400,error:"BAD_REQUEST",message:"\u8BF7\u6C42\u4F53\u89E3\u6790\u5931\u8D25"})}const o=[];for(let n=0;n<m;n++){const u=e.get(`video_${n}`);if(!f(u))break;o.push(await y(u))}const a=[];for(let n=0;n<m;n++){const u=e.get(`audio_${n}`);if(!f(u))break;a.push(await y(u))}const p=e.get("editState"),l=e.get("overlay"),i=f(l)?l:void 0,d=i?Buffer.from(await i.arrayBuffer()):void 0;if(i&&i.type!=="image/png")return s({ok:!1,status:415,error:"BAD_OVERLAY",message:"overlay \u5FC5\u987B\u662F PNG"});const b={videos:o,audios:a,overlay:d,editStateRaw:typeof p=="string"?p:""};return s(await t.handle(b))}}function O(t){return async r=>{let e;try{e=await r.formData()}catch{return s({ok:!1,status:400,error:"BAD_REQUEST",message:"\u8BF7\u6C42\u4F53\u89E3\u6790\u5931\u8D25"})}const o=e.get("file"),a=e.get("time");return!f(o)||typeof a!="string"?s({ok:!1,status:400,error:"BAD_REQUEST",message:"\u7F3A\u5C11 file \u6216 time"}):s(await t.handle(await y(o),Number(a)))}}
@@ -3,8 +3,8 @@ import { P as PosterHandler, V as VideoExportHandler } from '../handler-DL4Inp7o
3
3
  /**
4
4
  * Web 标准适配器(Next.js App Router 路由 / 任何接收 Request 返回 Response 的运行时)。
5
5
  * 用法(Next):
6
- * import { createVideoExportHandler } from '@media-editor/server';
7
- * import { toWebVideoHandler } from '@media-editor/server/web';
6
+ * import { createVideoExportHandler } from '@bylqwjc/media-editor-server';
7
+ * import { toWebVideoHandler } from '@bylqwjc/media-editor-server/web';
8
8
  * export const runtime = 'nodejs'; export const maxDuration = 300;
9
9
  * export const POST = toWebVideoHandler(createVideoExportHandler());
10
10
  */
@@ -1 +1 @@
1
- var y=16;function s(e){return typeof e=="object"&&e!==null&&typeof e.type=="string"&&typeof e.arrayBuffer=="function"}async function c(e){return{type:e.type,bytes:Buffer.from(await e.arrayBuffer())}}function a(e){return e.ok?new Response(new Uint8Array(e.bytes),{status:200,headers:{"Content-Type":e.contentType,"Content-Disposition":`attachment; filename="${e.filename}"`,"Cache-Control":"no-store"}}):new Response(JSON.stringify({error:e.error,message:e.message}),{status:e.status,headers:{"Content-Type":"application/json"}})}function C(e){return async l=>{let t;try{t=await l.formData()}catch{return a({ok:!1,status:400,error:"BAD_REQUEST",message:"\u8BF7\u6C42\u4F53\u89E3\u6790\u5931\u8D25"})}const n=[];for(let r=0;r<y;r++){const o=t.get(`video_${r}`);if(!s(o))break;n.push(await c(o))}const i=[];for(let r=0;r<y;r++){const o=t.get(`audio_${r}`);if(!s(o))break;i.push(await c(o))}const p=t.get("editState"),g=t.get("overlay"),m=t.get("videoCover"),f=s(g)?g:void 0,u=s(m)?m:void 0,v=f?Buffer.from(await f.arrayBuffer()):void 0,B=u?Buffer.from(await u.arrayBuffer()):void 0,d=[];for(let r=0;r<y;r++){const o=t.get(`textOverlay_${r}`);if(!s(o))break;if(o.type!=="image/png")return a({ok:!1,status:415,error:"BAD_OVERLAY",message:"textOverlay \u5FC5\u987B\u662F PNG"});d.push(Buffer.from(await o.arrayBuffer()))}if(f&&f.type!=="image/png")return a({ok:!1,status:415,error:"BAD_OVERLAY",message:"overlay \u5FC5\u987B\u662F PNG"});if(u&&!/^image\/(?:png|jpe?g)$/.test(u.type))return a({ok:!1,status:415,error:"BAD_COVER",message:"videoCover \u5FC5\u987B\u662F PNG \u6216 JPG"});const w={videos:n,audios:i,overlay:v,videoCover:B,textOverlays:d,editStateRaw:typeof p=="string"?p:""};return a(await e.handle(w))}}function F(e){return async l=>{let t;try{t=await l.formData()}catch{return a({ok:!1,status:400,error:"BAD_REQUEST",message:"\u8BF7\u6C42\u4F53\u89E3\u6790\u5931\u8D25"})}const n=t.get("file"),i=t.get("time");return!s(n)||typeof i!="string"?a({ok:!1,status:400,error:"BAD_REQUEST",message:"\u7F3A\u5C11 file \u6216 time"}):a(await e.handle(await c(n),Number(i)))}}export{F as toWebPosterHandler,C as toWebVideoHandler};
1
+ var g=16;function s(e){return typeof e=="object"&&e!==null&&typeof e.type=="string"&&typeof e.arrayBuffer=="function"}async function p(e){return{type:e.type,bytes:Buffer.from(await e.arrayBuffer())}}function o(e){return e.ok?new Response(new Uint8Array(e.bytes),{status:200,headers:{"Content-Type":e.contentType,"Content-Disposition":`attachment; filename="${e.filename}"`,"Cache-Control":"no-store"}}):new Response(JSON.stringify({error:e.error,message:e.message}),{status:e.status,headers:{"Content-Type":"application/json"}})}function C(e){return async y=>{let t;try{t=await y.formData()}catch{return o({ok:!1,status:400,error:"BAD_REQUEST",message:"\u8BF7\u6C42\u4F53\u89E3\u6790\u5931\u8D25"})}const u=[];for(let r=0;r<g;r++){const a=t.get(`video_${r}`);if(!s(a))break;u.push(await p(a))}const n=[];for(let r=0;r<g;r++){const a=t.get(`audio_${r}`);if(!s(a))break;n.push(await p(a))}const c=t.get("editState"),l=t.get("overlay"),m=t.get("videoCover"),i=s(l)?l:void 0,f=s(m)?m:void 0,B=i?Buffer.from(await i.arrayBuffer()):void 0,v=f?Buffer.from(await f.arrayBuffer()):void 0,d=[];for(let r=0;r<g;r++){const a=t.get(`textOverlay_${r}`);if(!s(a))break;if(a.type!=="image/png")return o({ok:!1,status:415,error:"BAD_OVERLAY",message:"textOverlay \u5FC5\u987B\u662F PNG"});d.push(Buffer.from(await a.arrayBuffer()))}if(i&&i.type!=="image/png")return o({ok:!1,status:415,error:"BAD_OVERLAY",message:"overlay \u5FC5\u987B\u662F PNG"});if(f&&!/^image\/(?:png|jpe?g)$/.test(f.type))return o({ok:!1,status:415,error:"BAD_COVER",message:"videoCover \u5FC5\u987B\u662F PNG \u6216 JPG"});const w={videos:u,audios:n,overlay:B,videoCover:v,textOverlays:d,editStateRaw:typeof c=="string"?c:""};return o(await e.handle(w))}}function F(e){return async y=>{let t;try{t=await y.formData()}catch{return o({ok:!1,status:400,error:"BAD_REQUEST",message:"\u8BF7\u6C42\u4F53\u89E3\u6790\u5931\u8D25"})}const u=t.get("file"),n=t.get("time");return!s(u)||typeof n!="string"?o({ok:!1,status:400,error:"BAD_REQUEST",message:"\u7F3A\u5C11 file \u6216 time"}):o(await e.handle(await p(u),Number(n)))}}export{F as toWebPosterHandler,C as toWebVideoHandler};
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var N=Object.create;var I=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var z=Object.getPrototypeOf,J=Object.prototype.hasOwnProperty;var K=(e,t,r,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of U(t))!J.call(e,o)&&o!==r&&I(e,o,{get:()=>t[o],enumerable:!(i=G(t,o))||i.enumerable});return e};var W=(e,t,r)=>(r=e!=null?N(z(e)):{},K(t||!e||!e.__esModule?I(r,"default",{value:e,enumerable:!0}):r,e));var Q=Object.create,P=Object.defineProperty,X=Object.getOwnPropertyDescriptor,Z=Object.getOwnPropertyNames,ee=Object.getPrototypeOf,te=Object.prototype.hasOwnProperty,ue=(e,t)=>{for(var r in t)P(e,r,{get:t[r],enumerable:!0})},L=(e,t,r,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Z(t))!te.call(e,o)&&o!==r&&P(e,o,{get:()=>t[o],enumerable:!(i=X(t,o))||i.enumerable});return e},re=(e,t,r)=>(r=e!=null?Q(ee(e)):{},L(t||!e||!e.__esModule?P(r,"default",{value:e,enumerable:!0}):r,e)),oe=e=>L(P({},"__esModule",{value:!0}),e),R={};ue(R,{DEFAULT_LIMITS:()=>H,composeVideo:()=>fe,createPosterHandler:()=>he,createVideoExportHandler:()=>ve,extractAudio:()=>pe,probeHasAudio:()=>$,probeVideoDuration:()=>M,runVideoEdit:()=>V}),module.exports=oe(R);var ie=require("../core/dist/index.cjs"),k=require("../core/dist/index.cjs"),S=re(require("ffmpeg-static"),1),T=require("child_process"),m=require("fs/promises"),ne=require("fs"),ae=require("os"),d=require("path"),se={};async function ce(){const e=[];S.default&&typeof S.default=="string"&&e.push(S.default);try{const{createRequire:t}=await import("module"),i=t(se.url).resolve("ffmpeg-static/package.json"),o=i.substring(0,i.lastIndexOf("/"));e.push((0,d.join)(o,"ffmpeg"))}catch{}e.push((0,d.join)(process.cwd(),"node_modules","ffmpeg-static","ffmpeg"),(0,d.join)(process.cwd(),"node_modules",".pnpm","ffmpeg-static@5.3.0","node_modules","ffmpeg-static","ffmpeg"));for(const t of e)if(t&&!t.startsWith("/ROOT/"))try{return await(0,m.access)(t,ne.constants.X_OK),t}catch{}return null}var b;async function O(){return b!==void 0||(b=await ce(),b||console.warn("[ffmpeg-runner] ffmpeg-static \u4E8C\u8FDB\u5236\u672A\u627E\u5230 (\u5C1D\u8BD5\u4E86\u591A\u4E2A fallback \u8DEF\u5F84)")),b}async function x({args:e,timeoutMs:t=18e4}){const r=await O();if(!r)throw new Error("ffmpeg-static \u4E8C\u8FDB\u5236\u7F3A\u5931 \u2014 \u8BF7\u68C0\u67E5 node_modules/ffmpeg-static/ffmpeg \u662F\u5426\u5B58\u5728");return console.log("[ffmpeg-runner] args:",JSON.stringify(e)),new Promise((i,o)=>{const s=(0,T.spawn)(r,e,{stdio:["ignore","pipe","pipe"]});let n="",f=!1;const a=setTimeout(()=>{f=!0,s.kill("SIGKILL"),o(new Error(`ffmpeg \u8D85\u65F6 (${t}ms)`))},t);s.stderr.on("data",u=>{n+=u.toString(),n.length>8192&&(n=n.slice(-8192))}),s.on("close",u=>{if(clearTimeout(a),f)return;const p=n.slice(-2500);console.log(`[ffmpeg-runner] exit=${u}, stderr tail:
2
- ${p}
3
- ---end---`),u===0?i():o(new Error(`ffmpeg \u9000\u51FA\u7801 ${u}: ${p.slice(-800)}`))}),s.on("error",u=>{clearTimeout(a),o(u)})})}async function B(e){const t=await(0,m.mkdtemp)((0,d.join)((0,ae.tmpdir)(),"vtrans-"));try{return await e(t)}finally{(0,m.rm)(t,{recursive:!0,force:!0}).catch(()=>{})}}async function $(e){const t=await O();return t?B(async r=>{const i=(0,d.join)(r,"probe.mp4");return await(0,m.writeFile)(i,e),new Promise(o=>{const s=(0,T.spawn)(t,["-hide_banner","-i",i],{stdio:["ignore","ignore","pipe"]});let n="";const f=setTimeout(()=>{s.kill("SIGKILL"),o(!1)},15e3);s.stderr.on("data",a=>{n+=a.toString(),n.length>16384&&(n=n.slice(-16384))}),s.on("close",()=>{clearTimeout(f),o(/Stream #[^\n]*Audio:/.test(n))}),s.on("error",()=>{clearTimeout(f),o(!1)})})}):!1}async function pe(e){return B(async t=>{const r=(0,d.join)(t,"in.mp4"),i=(0,d.join)(t,"audio.mp3");return await(0,m.writeFile)(r,e),await x({args:["-y","-i",r,"-vn","-acodec","libmp3lame","-ar","16000","-ac","1","-b:a","64k",i],timeoutMs:6e4}),(0,m.readFile)(i)})}var le=["Fontsize=14","PrimaryColour=&H00FFFFFF","OutlineColour=&H00000000","BackColour=&H80000000","BorderStyle=1","Outline=2","Shadow=0","Alignment=2","MarginV=80","Bold=1"].join(",");async function fe(e){const r=(await M(e.videoBytes)).durationSeconds;return B(async i=>{const o=(0,d.join)(i,"in.mp4"),s=(0,d.join)(i,"out.mp4");await(0,m.writeFile)(o,e.videoBytes);const n=["-i",o];let f=-1,a=-1;if(e.newAudioBytes){const g=(0,d.join)(i,"new.mp3");await(0,m.writeFile)(g,e.newAudioBytes),f=(n.length-0)/2,n.push("-i",g)}if(e.bgmAudioBytes){const g=(0,d.join)(i,"bgm.mp3");await(0,m.writeFile)(g,e.bgmAudioBytes),a=n.length/2,n.push("-i",g)}const u=e.srtContent&&e.srtContent.trim().length>0;let p=null;u&&(p=(0,d.join)(i,"subs.srt"),await(0,m.writeFile)(p,e.srtContent));const v=e.bgmVolume??.18;console.log(`[ffmpeg-runner] composeVideo: video=${e.videoBytes.length}B (${r.toFixed(2)}s), newAudio=${e.newAudioBytes?.length??0}B, bgm=${e.bgmAudioBytes?.length??0}B@${v}, srt=${e.srtContent?.length??0}chars`);const y=le.replace(/,/g,"\\,"),h=[];let _,D=!1;u&&p?(h.push(`[0:v]subtitles=${p}:force_style=${y}[v]`),_="[v]",D=!0):_="0:v:0";const A=[];f>=0&&A.push({idx:f,isBgm:!1}),a>=0&&A.push({idx:a,isBgm:!0});let c=null;if(A.length===1)c=`${A[0].idx}:a:0`;else if(A.length>=2){const g=[];for(const w of A)w.isBgm?(h.push(`[${w.idx}:a]volume=${v}[bgm]`),g.push("[bgm]")):g.push(`[${w.idx}:a]`);h.push(`${g.join("")}amix=inputs=${g.length}:duration=first:dropout_transition=0[a]`),c="[a]"}const F=["-y",...n];h.length>0&&F.push("-filter_complex",h.join(";")),F.push("-map",_),c&&F.push("-map",c),D?F.push("-c:v","libx264","-preset","fast","-crf","22","-pix_fmt","yuv420p"):F.push("-c:v","copy"),F.push("-c:a","aac","-b:a","128k","-ar","44100","-ac","2","-movflags","+faststart","-t",r.toFixed(3)),F.push(s),await x({args:F,timeoutMs:18e4});const C=c?await O():null;if(C)try{const g=await new Promise(w=>{const E=(0,T.spawn)(C,["-i",s],{stdio:["ignore","pipe","pipe"]});let j="";E.stderr.on("data",Y=>j+=Y.toString()),E.on("close",()=>w(j))});if(!/Audio:/.test(g))throw console.error(`[ffmpeg-runner] \u4EA7\u7269\u7F3A\u5C11\u97F3\u8F68,ffmpeg \u6D41\u6982\u89C8:
4
- `,g.slice(-2e3)),new Error("\u5408\u6210\u5931\u8D25: \u8F93\u51FA mp4 \u7F3A\u5C11\u97F3\u8F68 (\u68C0\u67E5 filter_complex \u8BED\u6CD5)");console.log("[ffmpeg-runner] composeVideo \u5B8C\u6210,\u5DF2\u542B\u97F3\u89C6\u9891\u53CC\u6D41")}catch(g){if(g instanceof Error&&g.message.includes("\u5408\u6210\u5931\u8D25"))throw g}return(0,m.readFile)(s)})}async function M(e){return B(async t=>{const r=(0,d.join)(t,"in.mp4");await(0,m.writeFile)(r,e);const i=await O();if(!i)throw new Error("ffmpeg-static \u4E8C\u8FDB\u5236\u7F3A\u5931");return new Promise((o,s)=>{const n=(0,T.spawn)(i,["-i",r],{stdio:["ignore","pipe","pipe"]});let f="";n.stderr.on("data",a=>f+=a.toString()),n.on("close",()=>{const a=f.match(/Duration:\s*(\d+):(\d+):(\d+(?:\.\d+)?)/);if(!a)return s(new Error("\u65E0\u6CD5\u89E3\u6790\u89C6\u9891\u65F6\u957F"));const u=parseInt(a[1]),p=parseInt(a[2]),v=parseFloat(a[3]);o({durationSeconds:u*3600+p*60+v})}),n.on("error",s)})})}async function V(e,t,r="mp4",i=[],o=24e4){return B(async s=>{const n=(0,d.join)(s,"input.mp4"),f=(0,d.join)(s,`output.${r}`);await(0,m.writeFile)(n,e);const a={};for(const u of i){const p=u.name.replace(/[^a-zA-Z0-9._-]/g,"_"),v=(0,d.join)(s,p);await(0,m.writeFile)(v,u.bytes),a[u.name]=v}return await x({args:t(n,f,a),timeoutMs:o}),(0,m.readFile)(f)})}function de(e){const t=String(e??"").toLowerCase();return t==="mp4"||t==="mov"}function me(e,t,r){return["-y","-loop","1","-t","0.04","-i",t,"-i",e,"-filter_complex","[0:v][1:v]scale2ref=w=main_w:h=main_h[vcover][vmainref];[vcover]setsar=1,fps=30,format=yuv420p[vcoverf];[vmainref]setpts=PTS-STARTPTS,fps=30,format=yuv420p[vmain];[vcoverf][vmain]concat=n=2:v=1:a=0[v]","-map","[v]","-map","1:a?","-c:v","libx264","-preset","fast","-crf","18","-pix_fmt","yuv420p","-c:a","copy","-movflags","+faststart",r]}async function ge(e,t,r="mp4",i=[],o,s=24e4){return B(async n=>{const f=(0,d.join)(n,"input.mp4"),a=(0,d.join)(n,`output.${r}`),u=(0,d.join)(n,"video-cover.png"),p=(0,d.join)(n,`output-with-cover.${r}`);await(0,m.writeFile)(f,e);const v={};for(const y of i){const h=y.name.replace(/[^a-zA-Z0-9._-]/g,"_"),_=(0,d.join)(n,h);await(0,m.writeFile)(_,y.bytes),v[y.name]=_}return await x({args:t(f,a,v),timeoutMs:s}),!de(r)||!o?.length?(0,m.readFile)(a):(await(0,m.writeFile)(u,o),await x({args:me(a,u,p),timeoutMs:s}),(0,m.readFile)(p))})}var H={maxVideos:6,maxAudios:3,maxVideoBytes:100*1024*1024,maxTotalVideoBytes:300*1024*1024,maxAudioBytes:30*1024*1024,maxOverlayBytes:20*1024*1024},l=(e,t,r)=>({ok:!1,status:e,error:t,message:r});function q(e){return e.startsWith("video/")?"mp4":e.includes("mpeg")||e.includes("mp3")?"mp3":e.includes("wav")?"wav":e.includes("aac")?"aac":e.includes("ogg")?"ogg":e.includes("mp4")||e.includes("m4a")?"m4a":e.includes("flac")?"flac":"bin"}function Fe(e){if(!e?.poster?.useAsVideoCover)return;const r=(typeof e.poster.preview=="string"?e.poster.preview:"").match(/^data:image\/(?:png|jpe?g);base64,([a-z0-9+/=]+)$/i);if(r)return Buffer.from(r[1],"base64")}function ve(e){const t={...H,...e?.limits};return{async handle(r){const{videos:i,audios:o,overlay:s,videoCover:n,editStateRaw:f}=r;if(i.length>t.maxVideos)return l(413,"TOO_MANY",`\u89C6\u9891\u6570\u8D85\u8FC7 ${t.maxVideos}`);for(let u=0;u<i.length;u++){if(!/^video\//.test(i[u].type))return l(415,"BAD_TYPE",`video_${u} \u4E0D\u662F\u89C6\u9891\u6587\u4EF6`);if(i[u].bytes.length>t.maxVideoBytes)return l(413,"TOO_LARGE",`\u89C6\u9891 ${u+1} \u8D85\u8FC7 100MB`)}if(!i.length)return l(400,"BAD_REQUEST","\u7F3A\u5C11\u89C6\u9891\u6587\u4EF6(video_0)");if(i.reduce((u,p)=>u+p.bytes.length,0)>t.maxTotalVideoBytes)return l(413,"TOO_LARGE","\u89C6\u9891\u603B\u5927\u5C0F\u8D85\u8FC7 300MB,\u8BF7\u51CF\u5C11\u7D20\u6750\u6216\u538B\u7F29");if(o.length>t.maxAudios)return l(413,"TOO_MANY",`\u97F3\u9891\u6570\u8D85\u8FC7 ${t.maxAudios}`);for(let u=0;u<o.length;u++){const p=/^audio\//.test(o[u].type),v=/^video\//.test(o[u].type);if(!p&&!v)return l(415,"BAD_TYPE",`audio_${u} \u4E0D\u662F\u97F3\u9891\u6216\u89C6\u9891\u6587\u4EF6`);if(o[u].bytes.length>(v?t.maxVideoBytes:t.maxAudioBytes))return l(413,"TOO_LARGE",`\u97F3\u9891 ${u+1} \u8D85\u8FC7 ${v?"100MB":"30MB"}`)}if(typeof f!="string")return l(400,"BAD_REQUEST","\u7F3A\u5C11 editState");if(s&&s.length>t.maxOverlayBytes)return l(413,"OVERLAY_TOO_LARGE","overlay \u8FC7\u5927");if(n&&n.length>t.maxOverlayBytes)return l(413,"COVER_TOO_LARGE","videoCover \u8FC7\u5927");let a;try{a=ie.VideoEditState.parse(JSON.parse(f))}catch{return l(400,"BAD_STATE","\u7F16\u8F91\u53C2\u6570\u4E0D\u5408\u6CD5")}if(a.clips.some(u=>u.srcIdx>=i.length))return l(400,"BAD_STATE","clips.srcIdx \u8D85\u51FA\u4E0A\u4F20\u89C6\u9891\u6570");if((a.audioClips??[]).some(u=>u.srcIdx>=o.length))return l(400,"BAD_STATE","audioClips.srcIdx \u8D85\u51FA\u4E0A\u4F20\u97F3\u9891\u6570");try{const u=i.map(c=>c.bytes),p=o.map(c=>c.bytes),v=[...new Set((a.audioClips??[]).map(c=>c.srcIdx))];for(const c of v)if(/^video\//.test(o[c].type)&&!await $(p[c]))return l(400,"BAD_TYPE",`\u97F3\u9891 ${c+1} \u662F\u89C6\u9891\u6587\u4EF6\u4F46\u6CA1\u6709\u97F3\u8F68,\u65E0\u6CD5\u63D0\u53D6\u58F0\u97F3`);const y=i.map(()=>!1);if(a.keepAudio){const c=[...new Set(a.clips.map(F=>F.srcIdx))];await Promise.all(c.map(async F=>{y[F]=await $(u[F])})),!y.some(Boolean)&&!(a.audioClips??[]).length&&(a={...a,keepAudio:!1})}const h=[];for(let c=1;c<u.length;c++)h.push({name:`video_${c}.mp4`,bytes:u[c]});p.forEach((c,F)=>h.push({name:`audio_${F}.${q(o[F].type)}`,bytes:c})),s&&h.push({name:"overlay.png",bytes:s});const _=n?.length?n:Fe(a),D=(c,F,C)=>{const g={videoPaths:[c,...u.slice(1).map((w,E)=>C[`video_${E+1}.mp4`])],videoHasAudio:y,audioPaths:p.map((w,E)=>C[`audio_${E}.${q(o[E].type)}`]),overlayPath:s?C["overlay.png"]:void 0};return(0,k.buildFfmpegArgs)(a,g,F)};return{ok:!0,bytes:_==null?await V(u[0],D,"mp4",h,28e4):await ge(u[0],D,"mp4",h,_,28e4),contentType:"video/mp4",filename:"edited.mp4"}}catch(u){return(u.message??"").includes("\u4E8C\u8FDB\u5236\u7F3A\u5931")?l(503,"SERVER_NOT_READY","\u670D\u52A1\u7AEF\u7F16\u7801\u7EC4\u4EF6\u672A\u5C31\u7EEA\uFF08ffmpeg \u7F3A\u5931\uFF09\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458"):l(502,"ENCODE_FAILED","\u89C6\u9891\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u6216\u6362\u66F4\u77ED\u7684\u89C6\u9891")}}}}function he(e){const t=e?.maxBytes??104857600;return{async handle(r,i){if(!/^video\//.test(r.type))return l(415,"BAD_TYPE","\u53EA\u652F\u6301\u89C6\u9891\u6587\u4EF6");if(r.bytes.length>t)return l(413,"TOO_LARGE","\u6587\u4EF6\u8D85\u8FC7 100MB");if(!isFinite(i)||i<0)return l(400,"BAD_TIME","time \u53C2\u6570\u4E0D\u5408\u6CD5");try{return{ok:!0,bytes:await V(r.bytes,(s,n)=>(0,k.buildPosterArgs)(s,i,n),"jpg"),contentType:"image/jpeg",filename:"poster.jpg"}}catch(o){return(o.message??"").includes("\u4E8C\u8FDB\u5236\u7F3A\u5931")?l(503,"SERVER_NOT_READY","\u670D\u52A1\u7AEF\u7F16\u7801\u7EC4\u4EF6\u672A\u5C31\u7EEA\uFF08ffmpeg \u7F3A\u5931\uFF09\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458"):l(502,"EXTRACT_FAILED","\u5C01\u9762\u62BD\u53D6\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5")}}}}
1
+ "use strict";var z=Object.create;var V=Object.defineProperty;var K=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var J=Object.getPrototypeOf,Q=Object.prototype.hasOwnProperty;var W=(e,t,u,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of U(t))!Q.call(e,r)&&r!==u&&V(e,r,{get:()=>t[r],enumerable:!(n=K(t,r))||n.enumerable});return e};var X=(e,t,u)=>(u=e!=null?z(J(e)):{},W(t||!e||!e.__esModule?V(u,"default",{value:e,enumerable:!0}):u,e));var Z=Object.create,M=Object.defineProperty,ee=Object.getOwnPropertyDescriptor,te=Object.getOwnPropertyNames,ue=Object.getPrototypeOf,re=Object.prototype.hasOwnProperty,oe=(e,t,u,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of te(t))!re.call(e,r)&&r!==u&&M(e,r,{get:()=>t[r],enumerable:!(n=ee(t,r))||n.enumerable});return e},ke=(e,t,u)=>(u=e!=null?Z(ue(e)):{},oe(t||!e||!e.__esModule?M(u,"default",{value:e,enumerable:!0}):u,e)),ne=Object.create,R=Object.defineProperty,ie=Object.getOwnPropertyDescriptor,ae=Object.getOwnPropertyNames,se=Object.getPrototypeOf,ce=Object.prototype.hasOwnProperty,le=(e,t,u,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ae(t))!ce.call(e,r)&&r!==u&&R(e,r,{get:()=>t[r],enumerable:!(n=ie(t,r))||n.enumerable});return e},Ne=(e,t,u)=>(u=e!=null?ne(se(e)):{},le(t||!e||!e.__esModule?R(u,"default",{value:e,enumerable:!0}):u,e)),pe=Object.create,I=Object.defineProperty,me=Object.getOwnPropertyDescriptor,fe=Object.getOwnPropertyNames,de=Object.getPrototypeOf,ge=Object.prototype.hasOwnProperty,ye=(e,t,u,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of fe(t))!ge.call(e,r)&&r!==u&&I(e,r,{get:()=>t[r],enumerable:!(n=me(t,r))||n.enumerable});return e},qe=(e,t,u)=>(u=e!=null?pe(de(e)):{},ye(t||!e||!e.__esModule?I(u,"default",{value:e,enumerable:!0}):u,e)),Fe=Object.create,D=Object.defineProperty,we=Object.getOwnPropertyDescriptor,ve=Object.getOwnPropertyNames,Ae=Object.getPrototypeOf,he=Object.prototype.hasOwnProperty,Ee=(e,t)=>{for(var u in t)D(e,u,{get:t[u],enumerable:!0})},L=(e,t,u,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ve(t))!he.call(e,r)&&r!==u&&D(e,r,{get:()=>t[r],enumerable:!(n=we(t,r))||n.enumerable});return e},be=(e,t,u)=>(u=e!=null?Fe(Ae(e)):{},L(t||!e||!e.__esModule?D(u,"default",{value:e,enumerable:!0}):u,e)),Ce=e=>L(D({},"__esModule",{value:!0}),e),k={};Ee(k,{DEFAULT_LIMITS:()=>Y,composeVideo:()=>Pe,createPosterHandler:()=>Ie,createVideoExportHandler:()=>Re,extractAudio:()=>xe,probeHasAudio:()=>P,probeVideoDuration:()=>q,runVideoEdit:()=>$}),module.exports=Ce(k);var Oe=require("../core/dist/index.cjs"),N=require("../core/dist/index.cjs"),T=be(require("ffmpeg-static"),1),_=require("child_process"),d=require("fs/promises"),Be=require("fs"),De=require("os"),m=require("path"),_e={};async function je(){const e=[];T.default&&typeof T.default=="string"&&e.push(T.default);try{const{createRequire:t}=await import("module"),u=t(_e.url).resolve("ffmpeg-static/package.json"),n=u.substring(0,u.lastIndexOf("/"));e.push((0,m.join)(n,"ffmpeg"))}catch{}e.push((0,m.join)(process.cwd(),"node_modules","ffmpeg-static","ffmpeg"),(0,m.join)(process.cwd(),"node_modules",".pnpm","ffmpeg-static@5.3.0","node_modules","ffmpeg-static","ffmpeg"));for(const t of e)if(t&&!t.startsWith("/ROOT/"))try{return await(0,d.access)(t,Be.constants.X_OK),t}catch{}return null}var j;async function x(){return j!==void 0||(j=await je(),j||console.warn("[ffmpeg-runner] ffmpeg-static \u4E8C\u8FDB\u5236\u672A\u627E\u5230 (\u5C1D\u8BD5\u4E86\u591A\u4E2A fallback \u8DEF\u5F84)")),j}async function B({args:e,timeoutMs:t=18e4}){const u=await x();if(!u)throw new Error("ffmpeg-static \u4E8C\u8FDB\u5236\u7F3A\u5931 \u2014 \u8BF7\u68C0\u67E5 node_modules/ffmpeg-static/ffmpeg \u662F\u5426\u5B58\u5728");return console.log("[ffmpeg-runner] args:",JSON.stringify(e)),new Promise((n,r)=>{const i=(0,_.spawn)(u,e,{stdio:["ignore","pipe","pipe"]});let a="",p=!1;const s=setTimeout(()=>{p=!0,i.kill("SIGKILL"),r(new Error(`ffmpeg \u8D85\u65F6 (${t}ms)`))},t);i.stderr.on("data",o=>{a+=o.toString(),a.length>8192&&(a=a.slice(-8192))}),i.on("close",o=>{if(clearTimeout(s),p)return;const f=a.slice(-2500);console.log(`[ffmpeg-runner] exit=${o}, stderr tail:
2
+ ${f}
3
+ ---end---`),o===0?n():r(new Error(`ffmpeg \u9000\u51FA\u7801 ${o}: ${f.slice(-800)}`))}),i.on("error",o=>{clearTimeout(s),r(o)})})}async function O(e){const t=await(0,d.mkdtemp)((0,m.join)((0,De.tmpdir)(),"vtrans-"));try{return await e(t)}finally{(0,d.rm)(t,{recursive:!0,force:!0}).catch(()=>{})}}async function P(e){const t=await x();return t?O(async u=>{const n=(0,m.join)(u,"probe.mp4");return await(0,d.writeFile)(n,e),new Promise(r=>{const i=(0,_.spawn)(t,["-hide_banner","-i",n],{stdio:["ignore","ignore","pipe"]});let a="";const p=setTimeout(()=>{i.kill("SIGKILL"),r(!1)},15e3);i.stderr.on("data",s=>{a+=s.toString(),a.length>16384&&(a=a.slice(-16384))}),i.on("close",()=>{clearTimeout(p),r(/Stream #[^\n]*Audio:/.test(a))}),i.on("error",()=>{clearTimeout(p),r(!1)})})}):!1}async function xe(e){return O(async t=>{const u=(0,m.join)(t,"in.mp4"),n=(0,m.join)(t,"audio.mp3");return await(0,d.writeFile)(u,e),await B({args:["-y","-i",u,"-vn","-acodec","libmp3lame","-ar","16000","-ac","1","-b:a","64k",n],timeoutMs:6e4}),(0,d.readFile)(n)})}var Te=["Fontsize=14","PrimaryColour=&H00FFFFFF","OutlineColour=&H00000000","BackColour=&H80000000","BorderStyle=1","Outline=2","Shadow=0","Alignment=2","MarginV=80","Bold=1"].join(",");async function Pe(e){const t=(await q(e.videoBytes)).durationSeconds;return O(async u=>{const n=(0,m.join)(u,"in.mp4"),r=(0,m.join)(u,"out.mp4");await(0,d.writeFile)(n,e.videoBytes);const i=["-i",n];let a=-1,p=-1;if(e.newAudioBytes){const g=(0,m.join)(u,"new.mp3");await(0,d.writeFile)(g,e.newAudioBytes),a=(i.length-0)/2,i.push("-i",g)}if(e.bgmAudioBytes){const g=(0,m.join)(u,"bgm.mp3");await(0,d.writeFile)(g,e.bgmAudioBytes),p=i.length/2,i.push("-i",g)}const s=e.srtContent&&e.srtContent.trim().length>0;let o=null;s&&(o=(0,m.join)(u,"subs.srt"),await(0,d.writeFile)(o,e.srtContent));const f=e.bgmVolume??.18;console.log(`[ffmpeg-runner] composeVideo: video=${e.videoBytes.length}B (${t.toFixed(2)}s), newAudio=${e.newAudioBytes?.length??0}B, bgm=${e.bgmAudioBytes?.length??0}B@${f}, srt=${e.srtContent?.length??0}chars`);const F=Te.replace(/,/g,"\\,"),w=[];let v,h=!1;s&&o?(w.push(`[0:v]subtitles=${o}:force_style=${F}[v]`),v="[v]",h=!0):v="0:v:0";const A=[];a>=0&&A.push({idx:a,isBgm:!1}),p>=0&&A.push({idx:p,isBgm:!0});let c=null;if(A.length===1)c=`${A[0].idx}:a:0`;else if(A.length>=2){const g=[];for(const E of A)E.isBgm?(w.push(`[${E.idx}:a]volume=${f}[bgm]`),g.push("[bgm]")):g.push(`[${E.idx}:a]`);w.push(`${g.join("")}amix=inputs=${g.length}:duration=first:dropout_transition=0[a]`),c="[a]"}const y=["-y",...i];w.length>0&&y.push("-filter_complex",w.join(";")),y.push("-map",v),c&&y.push("-map",c),h?y.push("-c:v","libx264","-preset","fast","-crf","22","-pix_fmt","yuv420p"):y.push("-c:v","copy"),y.push("-c:a","aac","-b:a","128k","-ar","44100","-ac","2","-movflags","+faststart","-t",t.toFixed(3)),y.push(r),await B({args:y,timeoutMs:18e4});const C=c?await x():null;if(C)try{const g=await new Promise(E=>{const b=(0,_.spawn)(C,["-i",r],{stdio:["ignore","pipe","pipe"]});let S="";b.stderr.on("data",H=>S+=H.toString()),b.on("close",()=>E(S))});if(!/Audio:/.test(g))throw console.error(`[ffmpeg-runner] \u4EA7\u7269\u7F3A\u5C11\u97F3\u8F68,ffmpeg \u6D41\u6982\u89C8:
4
+ `,g.slice(-2e3)),new Error("\u5408\u6210\u5931\u8D25: \u8F93\u51FA mp4 \u7F3A\u5C11\u97F3\u8F68 (\u68C0\u67E5 filter_complex \u8BED\u6CD5)");console.log("[ffmpeg-runner] composeVideo \u5B8C\u6210,\u5DF2\u542B\u97F3\u89C6\u9891\u53CC\u6D41")}catch(g){if(g instanceof Error&&g.message.includes("\u5408\u6210\u5931\u8D25"))throw g}return(0,d.readFile)(r)})}async function q(e){return O(async t=>{const u=(0,m.join)(t,"in.mp4");await(0,d.writeFile)(u,e);const n=await x();if(!n)throw new Error("ffmpeg-static \u4E8C\u8FDB\u5236\u7F3A\u5931");return new Promise((r,i)=>{const a=(0,_.spawn)(n,["-i",u],{stdio:["ignore","pipe","pipe"]});let p="";a.stderr.on("data",s=>p+=s.toString()),a.on("close",()=>{const s=p.match(/Duration:\s*(\d+):(\d+):(\d+(?:\.\d+)?)/);if(!s)return i(new Error("\u65E0\u6CD5\u89E3\u6790\u89C6\u9891\u65F6\u957F"));const o=parseInt(s[1]),f=parseInt(s[2]),F=parseFloat(s[3]);r({durationSeconds:o*3600+f*60+F})}),a.on("error",i)})})}async function $(e,t,u="mp4",n=[],r=24e4){return O(async i=>{const a=(0,m.join)(i,"input.mp4"),p=(0,m.join)(i,`output.${u}`);await(0,d.writeFile)(a,e);const s={};for(const o of n){const f=o.name.replace(/[^a-zA-Z0-9._-]/g,"_"),F=(0,m.join)(i,f);await(0,d.writeFile)(F,o.bytes),s[o.name]=F}return await B({args:t(a,p,s),timeoutMs:r}),(0,d.readFile)(p)})}function $e(e){const t=String(e??"").toLowerCase();return t==="mp4"||t==="mov"}function Se(e,t,u){return["-y","-loop","1","-t","0.04","-i",t,"-i",e,"-filter_complex","[0:v][1:v]scale2ref=w=main_w:h=main_h[vcover][vmainref];[vcover]setsar=1,fps=30,format=yuv420p[vcoverf];[vmainref]setpts=PTS-STARTPTS,fps=30,format=yuv420p[vmain];[vcoverf][vmain]concat=n=2:v=1:a=0[v]","-map","[v]","-map","1:a?","-c:v","libx264","-preset","fast","-crf","18","-pix_fmt","yuv420p","-c:a","copy","-movflags","+faststart",u]}async function Ve(e,t,u="mp4",n=[],r,i=24e4){return O(async a=>{const p=(0,m.join)(a,"input.mp4"),s=(0,m.join)(a,`output.${u}`),o=(0,m.join)(a,"video-cover.png"),f=(0,m.join)(a,`output-with-cover.${u}`);await(0,d.writeFile)(p,e);const F={};for(const w of n){const v=w.name.replace(/[^a-zA-Z0-9._-]/g,"_"),h=(0,m.join)(a,v);await(0,d.writeFile)(h,w.bytes),F[w.name]=h}return await B({args:t(p,s,F),timeoutMs:i}),!$e(u)||!r?.length?(0,d.readFile)(s):(await(0,d.writeFile)(o,r),await B({args:Se(s,o,f),timeoutMs:i}),(0,d.readFile)(f))})}var Y={maxVideos:6,maxAudios:3,maxVideoBytes:100*1024*1024,maxTotalVideoBytes:300*1024*1024,maxAudioBytes:30*1024*1024,maxOverlayBytes:20*1024*1024},l=(e,t,u)=>({ok:!1,status:e,error:t,message:u});function G(e){return e.startsWith("video/")?"mp4":e.includes("mpeg")||e.includes("mp3")?"mp3":e.includes("wav")?"wav":e.includes("aac")?"aac":e.includes("ogg")?"ogg":e.includes("mp4")||e.includes("m4a")?"m4a":e.includes("flac")?"flac":"bin"}function Me(e){if(!e?.poster?.useAsVideoCover)return;const t=(typeof e.poster.preview=="string"?e.poster.preview:"").match(/^data:image\/(?:png|jpe?g);base64,([a-z0-9+/=]+)$/i);if(t)return Buffer.from(t[1],"base64")}function Re(e){const t={...Y,...e?.limits};return{async handle(u){const{videos:n,audios:r,overlay:i,videoCover:a,editStateRaw:p}=u;if(n.length>t.maxVideos)return l(413,"TOO_MANY",`\u89C6\u9891\u6570\u8D85\u8FC7 ${t.maxVideos}`);for(let o=0;o<n.length;o++){if(!/^video\//.test(n[o].type))return l(415,"BAD_TYPE",`video_${o} \u4E0D\u662F\u89C6\u9891\u6587\u4EF6`);if(n[o].bytes.length>t.maxVideoBytes)return l(413,"TOO_LARGE",`\u89C6\u9891 ${o+1} \u8D85\u8FC7 100MB`)}if(!n.length)return l(400,"BAD_REQUEST","\u7F3A\u5C11\u89C6\u9891\u6587\u4EF6(video_0)");if(n.reduce((o,f)=>o+f.bytes.length,0)>t.maxTotalVideoBytes)return l(413,"TOO_LARGE","\u89C6\u9891\u603B\u5927\u5C0F\u8D85\u8FC7 300MB,\u8BF7\u51CF\u5C11\u7D20\u6750\u6216\u538B\u7F29");if(r.length>t.maxAudios)return l(413,"TOO_MANY",`\u97F3\u9891\u6570\u8D85\u8FC7 ${t.maxAudios}`);for(let o=0;o<r.length;o++){const f=/^audio\//.test(r[o].type),F=/^video\//.test(r[o].type);if(!f&&!F)return l(415,"BAD_TYPE",`audio_${o} \u4E0D\u662F\u97F3\u9891\u6216\u89C6\u9891\u6587\u4EF6`);if(r[o].bytes.length>(F?t.maxVideoBytes:t.maxAudioBytes))return l(413,"TOO_LARGE",`\u97F3\u9891 ${o+1} \u8D85\u8FC7 ${F?"100MB":"30MB"}`)}if(typeof p!="string")return l(400,"BAD_REQUEST","\u7F3A\u5C11 editState");if(i&&i.length>t.maxOverlayBytes)return l(413,"OVERLAY_TOO_LARGE","overlay \u8FC7\u5927");if(a&&a.length>t.maxOverlayBytes)return l(413,"COVER_TOO_LARGE","videoCover \u8FC7\u5927");let s;try{s=Oe.VideoEditState.parse(JSON.parse(p))}catch{return l(400,"BAD_STATE","\u7F16\u8F91\u53C2\u6570\u4E0D\u5408\u6CD5")}if(s.clips.some(o=>o.srcIdx>=n.length))return l(400,"BAD_STATE","clips.srcIdx \u8D85\u51FA\u4E0A\u4F20\u89C6\u9891\u6570");if((s.audioClips??[]).some(o=>o.srcIdx>=r.length))return l(400,"BAD_STATE","audioClips.srcIdx \u8D85\u51FA\u4E0A\u4F20\u97F3\u9891\u6570");try{const o=n.map(c=>c.bytes),f=r.map(c=>c.bytes),F=[...new Set((s.audioClips??[]).map(c=>c.srcIdx))];for(const c of F)if(/^video\//.test(r[c].type)&&!await P(f[c]))return l(400,"BAD_TYPE",`\u97F3\u9891 ${c+1} \u662F\u89C6\u9891\u6587\u4EF6\u4F46\u6CA1\u6709\u97F3\u8F68,\u65E0\u6CD5\u63D0\u53D6\u58F0\u97F3`);const w=n.map(()=>!1);if(s.keepAudio){const c=[...new Set(s.clips.map(y=>y.srcIdx))];await Promise.all(c.map(async y=>{w[y]=await P(o[y])})),!w.some(Boolean)&&!(s.audioClips??[]).length&&(s={...s,keepAudio:!1})}const v=[];for(let c=1;c<o.length;c++)v.push({name:`video_${c}.mp4`,bytes:o[c]});f.forEach((c,y)=>v.push({name:`audio_${y}.${G(r[y].type)}`,bytes:c})),i&&v.push({name:"overlay.png",bytes:i});const h=a?.length?a:Me(s),A=(c,y,C)=>{const g={videoPaths:[c,...o.slice(1).map((E,b)=>C[`video_${b+1}.mp4`])],videoHasAudio:w,audioPaths:f.map((E,b)=>C[`audio_${b}.${G(r[b].type)}`]),overlayPath:i?C["overlay.png"]:void 0};return(0,N.buildFfmpegArgs)(s,g,y)};return{ok:!0,bytes:h==null?await $(o[0],A,"mp4",v,28e4):await Ve(o[0],A,"mp4",v,h,28e4),contentType:"video/mp4",filename:"edited.mp4"}}catch(o){return(o.message??"").includes("\u4E8C\u8FDB\u5236\u7F3A\u5931")?l(503,"SERVER_NOT_READY","\u670D\u52A1\u7AEF\u7F16\u7801\u7EC4\u4EF6\u672A\u5C31\u7EEA\uFF08ffmpeg \u7F3A\u5931\uFF09\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458"):l(502,"ENCODE_FAILED","\u89C6\u9891\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u6216\u6362\u66F4\u77ED\u7684\u89C6\u9891")}}}}function Ie(e){const t=e?.maxBytes??104857600;return{async handle(u,n){if(!/^video\//.test(u.type))return l(415,"BAD_TYPE","\u53EA\u652F\u6301\u89C6\u9891\u6587\u4EF6");if(u.bytes.length>t)return l(413,"TOO_LARGE","\u6587\u4EF6\u8D85\u8FC7 100MB");if(!isFinite(n)||n<0)return l(400,"BAD_TIME","time \u53C2\u6570\u4E0D\u5408\u6CD5");try{return{ok:!0,bytes:await $(u.bytes,(r,i)=>(0,N.buildPosterArgs)(r,n,i),"jpg"),contentType:"image/jpeg",filename:"poster.jpg"}}catch(r){return(r.message??"").includes("\u4E8C\u8FDB\u5236\u7F3A\u5931")?l(503,"SERVER_NOT_READY","\u670D\u52A1\u7AEF\u7F16\u7801\u7EC4\u4EF6\u672A\u5C31\u7EEA\uFF08ffmpeg \u7F3A\u5931\uFF09\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458"):l(502,"EXTRACT_FAILED","\u5C01\u9762\u62BD\u53D6\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5")}}}}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import{VideoEditState as M}from"../core/dist/index.js";import{buildFfmpegArgs as G,buildPosterArgs as H}from"../core/dist/index.js";import V from"ffmpeg-static";import{spawn as $}from"child_process";import{writeFile as h,readFile as b,mkdtemp as N,rm as j,access as z}from"fs/promises";import{constants as U}from"fs";import{tmpdir as q}from"os";import{join as d}from"path";async function K(){const e=[];V&&typeof V=="string"&&e.push(V);try{const{createRequire:t}=await import("module"),r=t(import.meta.url).resolve("ffmpeg-static/package.json"),i=r.substring(0,r.lastIndexOf("/"));e.push(d(i,"ffmpeg"))}catch{}e.push(d(process.cwd(),"node_modules","ffmpeg-static","ffmpeg"),d(process.cwd(),"node_modules",".pnpm","ffmpeg-static@5.3.0","node_modules","ffmpeg-static","ffmpeg"));for(const t of e)if(t&&!t.startsWith("/ROOT/"))try{return await z(t,U.X_OK),t}catch{}return null}var T;async function S(){return T!==void 0||(T=await K(),T||console.warn("[ffmpeg-runner] ffmpeg-static \u4E8C\u8FDB\u5236\u672A\u627E\u5230 (\u5C1D\u8BD5\u4E86\u591A\u4E2A fallback \u8DEF\u5F84)")),T}async function P({args:e,timeoutMs:t=18e4}){const o=await S();if(!o)throw new Error("ffmpeg-static \u4E8C\u8FDB\u5236\u7F3A\u5931 \u2014 \u8BF7\u68C0\u67E5 node_modules/ffmpeg-static/ffmpeg \u662F\u5426\u5B58\u5728");return console.log("[ffmpeg-runner] args:",JSON.stringify(e)),new Promise((r,i)=>{const s=$(o,e,{stdio:["ignore","pipe","pipe"]});let n="",l=!1;const f=setTimeout(()=>{l=!0,s.kill("SIGKILL"),i(new Error(`ffmpeg \u8D85\u65F6 (${t}ms)`))},t);s.stderr.on("data",a=>{n+=a.toString(),n.length>8192&&(n=n.slice(-8192))}),s.on("close",a=>{if(clearTimeout(f),l)return;const u=n.slice(-2500);console.log(`[ffmpeg-runner] exit=${a}, stderr tail:
1
+ import{VideoEditState as k}from"../core/dist/index.js";import{buildFfmpegArgs as Y,buildPosterArgs as j}from"../core/dist/index.js";import R from"ffmpeg-static";import{spawn as b}from"child_process";import{writeFile as v,readFile as x,mkdtemp as G,rm as H,access as N}from"fs/promises";import{constants as z}from"fs";import{tmpdir as K}from"os";import{join as d}from"path";async function U(){const t=[];R&&typeof R=="string"&&t.push(R);try{const{createRequire:e}=await import("module"),o=e(import.meta.url).resolve("ffmpeg-static/package.json"),r=o.substring(0,o.lastIndexOf("/"));t.push(d(r,"ffmpeg"))}catch{}t.push(d(process.cwd(),"node_modules","ffmpeg-static","ffmpeg"),d(process.cwd(),"node_modules",".pnpm","ffmpeg-static@5.3.0","node_modules","ffmpeg-static","ffmpeg"));for(const e of t)if(e&&!e.startsWith("/ROOT/"))try{return await N(e,z.X_OK),e}catch{}return null}var $;async function S(){return $!==void 0||($=await U(),$||console.warn("[ffmpeg-runner] ffmpeg-static \u4E8C\u8FDB\u5236\u672A\u627E\u5230 (\u5C1D\u8BD5\u4E86\u591A\u4E2A fallback \u8DEF\u5F84)")),$}async function T({args:t,timeoutMs:e=18e4}){const o=await S();if(!o)throw new Error("ffmpeg-static \u4E8C\u8FDB\u5236\u7F3A\u5931 \u2014 \u8BF7\u68C0\u67E5 node_modules/ffmpeg-static/ffmpeg \u662F\u5426\u5B58\u5728");return console.log("[ffmpeg-runner] args:",JSON.stringify(t)),new Promise((r,s)=>{const a=b(o,t,{stdio:["ignore","pipe","pipe"]});let i="",f=!1;const m=setTimeout(()=>{f=!0,a.kill("SIGKILL"),s(new Error(`ffmpeg \u8D85\u65F6 (${e}ms)`))},e);a.stderr.on("data",n=>{i+=n.toString(),i.length>8192&&(i=i.slice(-8192))}),a.on("close",n=>{if(clearTimeout(m),f)return;const u=i.slice(-2500);console.log(`[ffmpeg-runner] exit=${n}, stderr tail:
2
2
  ${u}
3
- ---end---`),a===0?r():i(new Error(`ffmpeg \u9000\u51FA\u7801 ${a}: ${u.slice(-800)}`))}),s.on("error",a=>{clearTimeout(f),i(a)})})}async function _(e){const t=await N(d(q(),"vtrans-"));try{return await e(t)}finally{j(t,{recursive:!0,force:!0}).catch(()=>{})}}async function R(e){const t=await S();return t?_(async o=>{const r=d(o,"probe.mp4");return await h(r,e),new Promise(i=>{const s=$(t,["-hide_banner","-i",r],{stdio:["ignore","ignore","pipe"]});let n="";const l=setTimeout(()=>{s.kill("SIGKILL"),i(!1)},15e3);s.stderr.on("data",f=>{n+=f.toString(),n.length>16384&&(n=n.slice(-16384))}),s.on("close",()=>{clearTimeout(l),i(/Stream #[^\n]*Audio:/.test(n))}),s.on("error",()=>{clearTimeout(l),i(!1)})})}):!1}async function W(e){return _(async t=>{const o=d(t,"in.mp4"),r=d(t,"audio.mp3");return await h(o,e),await P({args:["-y","-i",o,"-vn","-acodec","libmp3lame","-ar","16000","-ac","1","-b:a","64k",r],timeoutMs:6e4}),b(r)})}var J=["Fontsize=14","PrimaryColour=&H00FFFFFF","OutlineColour=&H00000000","BackColour=&H80000000","BorderStyle=1","Outline=2","Shadow=0","Alignment=2","MarginV=80","Bold=1"].join(",");async function Q(e){const o=(await L(e.videoBytes)).durationSeconds;return _(async r=>{const i=d(r,"in.mp4"),s=d(r,"out.mp4");await h(i,e.videoBytes);const n=["-i",i];let l=-1,f=-1;if(e.newAudioBytes){const c=d(r,"new.mp3");await h(c,e.newAudioBytes),l=(n.length-0)/2,n.push("-i",c)}if(e.bgmAudioBytes){const c=d(r,"bgm.mp3");await h(c,e.bgmAudioBytes),f=n.length/2,n.push("-i",c)}const a=e.srtContent&&e.srtContent.trim().length>0;let u=null;a&&(u=d(r,"subs.srt"),await h(u,e.srtContent));const g=e.bgmVolume??.18;console.log(`[ffmpeg-runner] composeVideo: video=${e.videoBytes.length}B (${o.toFixed(2)}s), newAudio=${e.newAudioBytes?.length??0}B, bgm=${e.bgmAudioBytes?.length??0}B@${g}, srt=${e.srtContent?.length??0}chars`);const y=J.replace(/,/g,"\\,"),v=[];let F,D=!1;a&&u?(v.push(`[0:v]subtitles=${u}:force_style=${y}[v]`),F="[v]",D=!0):F="0:v:0";const E=[];l>=0&&E.push({idx:l,isBgm:!1}),f>=0&&E.push({idx:f,isBgm:!0});let w=null;if(E.length===1)w=`${E[0].idx}:a:0`;else if(E.length>=2){const c=[];for(const A of E)A.isBgm?(v.push(`[${A.idx}:a]volume=${g}[bgm]`),c.push("[bgm]")):c.push(`[${A.idx}:a]`);v.push(`${c.join("")}amix=inputs=${c.length}:duration=first:dropout_transition=0[a]`),w="[a]"}const C=["-y",...n];v.length>0&&C.push("-filter_complex",v.join(";")),C.push("-map",F),w&&C.push("-map",w),D?C.push("-c:v","libx264","-preset","fast","-crf","22","-pix_fmt","yuv420p"):C.push("-c:v","copy"),C.push("-c:a","aac","-b:a","128k","-ar","44100","-ac","2","-movflags","+faststart","-t",o.toFixed(3)),C.push(s),await P({args:C,timeoutMs:18e4});const p=w?await S():null;if(p)try{const c=await new Promise(A=>{const O=$(p,["-i",s],{stdio:["ignore","pipe","pipe"]});let x="";O.stderr.on("data",B=>x+=B.toString()),O.on("close",()=>A(x))});if(!/Audio:/.test(c))throw console.error(`[ffmpeg-runner] \u4EA7\u7269\u7F3A\u5C11\u97F3\u8F68,ffmpeg \u6D41\u6982\u89C8:
4
- `,c.slice(-2e3)),new Error("\u5408\u6210\u5931\u8D25: \u8F93\u51FA mp4 \u7F3A\u5C11\u97F3\u8F68 (\u68C0\u67E5 filter_complex \u8BED\u6CD5)");console.log("[ffmpeg-runner] composeVideo \u5B8C\u6210,\u5DF2\u542B\u97F3\u89C6\u9891\u53CC\u6D41")}catch(c){if(c instanceof Error&&c.message.includes("\u5408\u6210\u5931\u8D25"))throw c}return b(s)})}async function L(e){return _(async t=>{const o=d(t,"in.mp4");await h(o,e);const r=await S();if(!r)throw new Error("ffmpeg-static \u4E8C\u8FDB\u5236\u7F3A\u5931");return new Promise((i,s)=>{const n=$(r,["-i",o],{stdio:["ignore","pipe","pipe"]});let l="";n.stderr.on("data",f=>l+=f.toString()),n.on("close",()=>{const f=l.match(/Duration:\s*(\d+):(\d+):(\d+(?:\.\d+)?)/);if(!f)return s(new Error("\u65E0\u6CD5\u89E3\u6790\u89C6\u9891\u65F6\u957F"));const a=parseInt(f[1]),u=parseInt(f[2]),g=parseFloat(f[3]);i({durationSeconds:a*3600+u*60+g})}),n.on("error",s)})})}async function I(e,t,o="mp4",r=[],i=24e4){return _(async s=>{const n=d(s,"input.mp4"),l=d(s,`output.${o}`);await h(n,e);const f={};for(const a of r){const u=a.name.replace(/[^a-zA-Z0-9._-]/g,"_"),g=d(s,u);await h(g,a.bytes),f[a.name]=g}return await P({args:t(n,l,f),timeoutMs:i}),b(l)})}function X(e){const t=String(e??"").toLowerCase();return t==="mp4"||t==="mov"}function Z(e,t,o){return["-y","-loop","1","-t","0.04","-i",t,"-i",e,"-filter_complex","[0:v][1:v]scale2ref=w=main_w:h=main_h[vcover][vmainref];[vcover]setsar=1,fps=30,format=yuv420p[vcoverf];[vmainref]setpts=PTS-STARTPTS,fps=30,format=yuv420p[vmain];[vcoverf][vmain]concat=n=2:v=1:a=0[v]","-map","[v]","-map","1:a?","-c:v","libx264","-preset","fast","-crf","18","-pix_fmt","yuv420p","-c:a","copy","-movflags","+faststart",o]}async function ee(e,t,o="mp4",r=[],i,s=24e4){return _(async n=>{const l=d(n,"input.mp4"),f=d(n,`output.${o}`),a=d(n,"video-cover.png"),u=d(n,`output-with-cover.${o}`);await h(l,e);const g={};for(const y of r){const v=y.name.replace(/[^a-zA-Z0-9._-]/g,"_"),F=d(n,v);await h(F,y.bytes),g[y.name]=F}return await P({args:t(l,f,g),timeoutMs:s}),!X(o)||!i?.length?b(f):(await h(a,i),await P({args:Z(f,a,u),timeoutMs:s}),b(u))})}var k={maxVideos:6,maxAudios:3,maxVideoBytes:100*1024*1024,maxTotalVideoBytes:300*1024*1024,maxAudioBytes:30*1024*1024,maxOverlayBytes:20*1024*1024},m=(e,t,o)=>({ok:!1,status:e,error:t,message:o});function Y(e){return e.startsWith("video/")?"mp4":e.includes("mpeg")||e.includes("mp3")?"mp3":e.includes("wav")?"wav":e.includes("aac")?"aac":e.includes("ogg")?"ogg":e.includes("mp4")||e.includes("m4a")?"m4a":e.includes("flac")?"flac":"bin"}function te(e){const t=String(e??"mp4").toLowerCase();return t==="mov"||t==="mxf"?t:"mp4"}function ue(e){return e==="mov"?"video/quicktime":e==="mxf"?"application/mxf":"video/mp4"}function re(e){if(!e?.poster?.useAsVideoCover)return;const o=(typeof e.poster.preview=="string"?e.poster.preview:"").match(/^data:image\/(?:png|jpe?g);base64,([a-z0-9+/=]+)$/i);if(o)return Buffer.from(o[1],"base64")}function ne(e){const t={...k,...e?.limits};return{async handle(o){const{videos:r,audios:i,overlay:s,videoCover:n,textOverlays:l=[],editStateRaw:f}=o;if(r.length>t.maxVideos)return m(413,"TOO_MANY",`\u89C6\u9891\u6570\u8D85\u8FC7 ${t.maxVideos}`);for(let u=0;u<r.length;u++){if(!/^video\//.test(r[u].type))return m(415,"BAD_TYPE",`video_${u} \u4E0D\u662F\u89C6\u9891\u6587\u4EF6`);if(r[u].bytes.length>t.maxVideoBytes)return m(413,"TOO_LARGE",`\u89C6\u9891 ${u+1} \u8D85\u8FC7 100MB`)}if(!r.length)return m(400,"BAD_REQUEST","\u7F3A\u5C11\u89C6\u9891\u6587\u4EF6(video_0)");if(r.reduce((u,g)=>u+g.bytes.length,0)>t.maxTotalVideoBytes)return m(413,"TOO_LARGE","\u89C6\u9891\u603B\u5927\u5C0F\u8D85\u8FC7 300MB,\u8BF7\u51CF\u5C11\u7D20\u6750\u6216\u538B\u7F29");if(i.length>t.maxAudios)return m(413,"TOO_MANY",`\u97F3\u9891\u6570\u8D85\u8FC7 ${t.maxAudios}`);for(let u=0;u<i.length;u++){const g=/^audio\//.test(i[u].type),y=/^video\//.test(i[u].type);if(!g&&!y)return m(415,"BAD_TYPE",`audio_${u} \u4E0D\u662F\u97F3\u9891\u6216\u89C6\u9891\u6587\u4EF6`);if(i[u].bytes.length>(y?t.maxVideoBytes:t.maxAudioBytes))return m(413,"TOO_LARGE",`\u97F3\u9891 ${u+1} \u8D85\u8FC7 ${y?"100MB":"30MB"}`)}if(typeof f!="string")return m(400,"BAD_REQUEST","\u7F3A\u5C11 editState");if(s&&s.length>t.maxOverlayBytes)return m(413,"OVERLAY_TOO_LARGE","overlay \u8FC7\u5927");if(n&&n.length>t.maxOverlayBytes)return m(413,"COVER_TOO_LARGE","videoCover \u8FC7\u5927");if(l.some(u=>u.length>t.maxOverlayBytes))return m(413,"OVERLAY_TOO_LARGE","textOverlay \u8FC7\u5927");let a;try{a=M.parse(JSON.parse(f))}catch{return m(400,"BAD_STATE","\u7F16\u8F91\u53C2\u6570\u4E0D\u5408\u6CD5")}if(a.clips.some(u=>u.srcIdx>=r.length))return m(400,"BAD_STATE","clips.srcIdx \u8D85\u51FA\u4E0A\u4F20\u89C6\u9891\u6570");if((a.audioClips??[]).some(u=>u.srcIdx>=i.length))return m(400,"BAD_STATE","audioClips.srcIdx \u8D85\u51FA\u4E0A\u4F20\u97F3\u9891\u6570");try{const u=r.map(p=>p.bytes),g=i.map(p=>p.bytes),y=[...new Set((a.audioClips??[]).map(p=>p.srcIdx))];for(const p of y)if(/^video\//.test(i[p].type)&&!await R(g[p]))return m(400,"BAD_TYPE",`\u97F3\u9891 ${p+1} \u662F\u89C6\u9891\u6587\u4EF6\u4F46\u6CA1\u6709\u97F3\u8F68,\u65E0\u6CD5\u63D0\u53D6\u58F0\u97F3`);const v=r.map(()=>!1);if(a.keepAudio){const p=[...new Set(a.clips.map(c=>c.srcIdx))];await Promise.all(p.map(async c=>{v[c]=await R(u[c])})),!v.some(Boolean)&&!(a.audioClips??[]).length&&(a={...a,keepAudio:!1})}const F=[];for(let p=1;p<u.length;p++)F.push({name:`video_${p}.mp4`,bytes:u[p]});g.forEach((p,c)=>F.push({name:`audio_${c}.${Y(i[c].type)}`,bytes:p})),s&&F.push({name:"overlay.png",bytes:s}),l.forEach((p,c)=>F.push({name:`textOverlay_${c}.png`,bytes:p}));const D=te(a.exportSettings?.format),E=n?.length?n:re(a),w=(p,c,A)=>{const O={videoPaths:[p,...u.slice(1).map((x,B)=>A[`video_${B+1}.mp4`])],videoHasAudio:v,audioPaths:g.map((x,B)=>A[`audio_${B}.${Y(i[B].type)}`]),overlayPath:s?A["overlay.png"]:void 0,textOverlayPaths:l.map((x,B)=>A[`textOverlay_${B}.png`]).filter(Boolean)};return G(a,O,c)};return{ok:!0,bytes:E==null?await I(u[0],w,D,F,28e4):await ee(u[0],w,D,F,E,28e4),contentType:ue(D),filename:`edited.${D}`}}catch(u){return(u.message??"").includes("\u4E8C\u8FDB\u5236\u7F3A\u5931")?m(503,"SERVER_NOT_READY","\u670D\u52A1\u7AEF\u7F16\u7801\u7EC4\u4EF6\u672A\u5C31\u7EEA\uFF08ffmpeg \u7F3A\u5931\uFF09\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458"):m(502,"ENCODE_FAILED","\u89C6\u9891\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u6216\u6362\u66F4\u77ED\u7684\u89C6\u9891")}}}}function oe(e){const t=e?.maxBytes??104857600;return{async handle(o,r){if(!/^video\//.test(o.type))return m(415,"BAD_TYPE","\u53EA\u652F\u6301\u89C6\u9891\u6587\u4EF6");if(o.bytes.length>t)return m(413,"TOO_LARGE","\u6587\u4EF6\u8D85\u8FC7 100MB");if(!isFinite(r)||r<0)return m(400,"BAD_TIME","time \u53C2\u6570\u4E0D\u5408\u6CD5");try{return{ok:!0,bytes:await I(o.bytes,(s,n)=>H(s,r,n),"jpg"),contentType:"image/jpeg",filename:"poster.jpg"}}catch(i){return(i.message??"").includes("\u4E8C\u8FDB\u5236\u7F3A\u5931")?m(503,"SERVER_NOT_READY","\u670D\u52A1\u7AEF\u7F16\u7801\u7EC4\u4EF6\u672A\u5C31\u7EEA\uFF08ffmpeg \u7F3A\u5931\uFF09\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458"):m(502,"EXTRACT_FAILED","\u5C01\u9762\u62BD\u53D6\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5")}}}}export{k as DEFAULT_LIMITS,Q as composeVideo,oe as createPosterHandler,ne as createVideoExportHandler,W as extractAudio,R as probeHasAudio,L as probeVideoDuration,I as runVideoEdit};
3
+ ---end---`),n===0?r():s(new Error(`ffmpeg \u9000\u51FA\u7801 ${n}: ${u.slice(-800)}`))}),a.on("error",n=>{clearTimeout(m),s(n)})})}async function D(t){const e=await G(d(K(),"vtrans-"));try{return await t(e)}finally{H(e,{recursive:!0,force:!0}).catch(()=>{})}}async function V(t){const e=await S();return e?D(async o=>{const r=d(o,"probe.mp4");return await v(r,t),new Promise(s=>{const a=b(e,["-hide_banner","-i",r],{stdio:["ignore","ignore","pipe"]});let i="";const f=setTimeout(()=>{a.kill("SIGKILL"),s(!1)},15e3);a.stderr.on("data",m=>{i+=m.toString(),i.length>16384&&(i=i.slice(-16384))}),a.on("close",()=>{clearTimeout(f),s(/Stream #[^\n]*Audio:/.test(i))}),a.on("error",()=>{clearTimeout(f),s(!1)})})}):!1}async function q(t){return D(async e=>{const o=d(e,"in.mp4"),r=d(e,"audio.mp3");return await v(o,t),await T({args:["-y","-i",o,"-vn","-acodec","libmp3lame","-ar","16000","-ac","1","-b:a","64k",r],timeoutMs:6e4}),x(r)})}var J=["Fontsize=14","PrimaryColour=&H00FFFFFF","OutlineColour=&H00000000","BackColour=&H80000000","BorderStyle=1","Outline=2","Shadow=0","Alignment=2","MarginV=80","Bold=1"].join(",");async function Q(t){const e=(await I(t.videoBytes)).durationSeconds;return D(async o=>{const r=d(o,"in.mp4"),s=d(o,"out.mp4");await v(r,t.videoBytes);const a=["-i",r];let i=-1,f=-1;if(t.newAudioBytes){const c=d(o,"new.mp3");await v(c,t.newAudioBytes),i=(a.length-0)/2,a.push("-i",c)}if(t.bgmAudioBytes){const c=d(o,"bgm.mp3");await v(c,t.bgmAudioBytes),f=a.length/2,a.push("-i",c)}const m=t.srtContent&&t.srtContent.trim().length>0;let n=null;m&&(n=d(o,"subs.srt"),await v(n,t.srtContent));const u=t.bgmVolume??.18;console.log(`[ffmpeg-runner] composeVideo: video=${t.videoBytes.length}B (${e.toFixed(2)}s), newAudio=${t.newAudioBytes?.length??0}B, bgm=${t.bgmAudioBytes?.length??0}B@${u}, srt=${t.srtContent?.length??0}chars`);const g=J.replace(/,/g,"\\,"),F=[];let C,y=!1;m&&n?(F.push(`[0:v]subtitles=${n}:force_style=${g}[v]`),C="[v]",y=!0):C="0:v:0";const A=[];i>=0&&A.push({idx:i,isBgm:!1}),f>=0&&A.push({idx:f,isBgm:!0});let w=null;if(A.length===1)w=`${A[0].idx}:a:0`;else if(A.length>=2){const c=[];for(const h of A)h.isBgm?(F.push(`[${h.idx}:a]volume=${u}[bgm]`),c.push("[bgm]")):c.push(`[${h.idx}:a]`);F.push(`${c.join("")}amix=inputs=${c.length}:duration=first:dropout_transition=0[a]`),w="[a]"}const E=["-y",...a];F.length>0&&E.push("-filter_complex",F.join(";")),E.push("-map",C),w&&E.push("-map",w),y?E.push("-c:v","libx264","-preset","fast","-crf","22","-pix_fmt","yuv420p"):E.push("-c:v","copy"),E.push("-c:a","aac","-b:a","128k","-ar","44100","-ac","2","-movflags","+faststart","-t",e.toFixed(3)),E.push(s),await T({args:E,timeoutMs:18e4});const p=w?await S():null;if(p)try{const c=await new Promise(h=>{const O=b(p,["-i",s],{stdio:["ignore","pipe","pipe"]});let _="";O.stderr.on("data",B=>_+=B.toString()),O.on("close",()=>h(_))});if(!/Audio:/.test(c))throw console.error(`[ffmpeg-runner] \u4EA7\u7269\u7F3A\u5C11\u97F3\u8F68,ffmpeg \u6D41\u6982\u89C8:
4
+ `,c.slice(-2e3)),new Error("\u5408\u6210\u5931\u8D25: \u8F93\u51FA mp4 \u7F3A\u5C11\u97F3\u8F68 (\u68C0\u67E5 filter_complex \u8BED\u6CD5)");console.log("[ffmpeg-runner] composeVideo \u5B8C\u6210,\u5DF2\u542B\u97F3\u89C6\u9891\u53CC\u6D41")}catch(c){if(c instanceof Error&&c.message.includes("\u5408\u6210\u5931\u8D25"))throw c}return x(s)})}async function I(t){return D(async e=>{const o=d(e,"in.mp4");await v(o,t);const r=await S();if(!r)throw new Error("ffmpeg-static \u4E8C\u8FDB\u5236\u7F3A\u5931");return new Promise((s,a)=>{const i=b(r,["-i",o],{stdio:["ignore","pipe","pipe"]});let f="";i.stderr.on("data",m=>f+=m.toString()),i.on("close",()=>{const m=f.match(/Duration:\s*(\d+):(\d+):(\d+(?:\.\d+)?)/);if(!m)return a(new Error("\u65E0\u6CD5\u89E3\u6790\u89C6\u9891\u65F6\u957F"));const n=parseInt(m[1]),u=parseInt(m[2]),g=parseFloat(m[3]);s({durationSeconds:n*3600+u*60+g})}),i.on("error",a)})})}async function L(t,e,o="mp4",r=[],s=24e4){return D(async a=>{const i=d(a,"input.mp4"),f=d(a,`output.${o}`);await v(i,t);const m={};for(const n of r){const u=n.name.replace(/[^a-zA-Z0-9._-]/g,"_"),g=d(a,u);await v(g,n.bytes),m[n.name]=g}return await T({args:e(i,f,m),timeoutMs:s}),x(f)})}function W(t){const e=String(t??"").toLowerCase();return e==="mp4"||e==="mov"}function X(t,e,o){return["-y","-loop","1","-t","0.04","-i",e,"-i",t,"-filter_complex","[0:v][1:v]scale2ref=w=main_w:h=main_h[vcover][vmainref];[vcover]setsar=1,fps=30,format=yuv420p[vcoverf];[vmainref]setpts=PTS-STARTPTS,fps=30,format=yuv420p[vmain];[vcoverf][vmain]concat=n=2:v=1:a=0[v]","-map","[v]","-map","1:a?","-c:v","libx264","-preset","fast","-crf","18","-pix_fmt","yuv420p","-c:a","copy","-movflags","+faststart",o]}async function Z(t,e,o="mp4",r=[],s,a=24e4){return D(async i=>{const f=d(i,"input.mp4"),m=d(i,`output.${o}`),n=d(i,"video-cover.png"),u=d(i,`output-with-cover.${o}`);await v(f,t);const g={};for(const F of r){const C=F.name.replace(/[^a-zA-Z0-9._-]/g,"_"),y=d(i,C);await v(y,F.bytes),g[F.name]=y}return await T({args:e(f,m,g),timeoutMs:a}),!W(o)||!s?.length?x(m):(await v(n,s),await T({args:X(m,n,u),timeoutMs:a}),x(u))})}var P={maxVideos:6,maxAudios:3,maxVideoBytes:100*1024*1024,maxTotalVideoBytes:300*1024*1024,maxAudioBytes:30*1024*1024,maxOverlayBytes:20*1024*1024},l=(t,e,o)=>({ok:!1,status:t,error:e,message:o});function M(t){return t.startsWith("video/")?"mp4":t.includes("mpeg")||t.includes("mp3")?"mp3":t.includes("wav")?"wav":t.includes("aac")?"aac":t.includes("ogg")?"ogg":t.includes("mp4")||t.includes("m4a")?"m4a":t.includes("flac")?"flac":"bin"}function tt(t){const e=String(t??"mp4").toLowerCase();return e==="mov"||e==="mxf"?e:"mp4"}function et(t){return t==="mov"?"video/quicktime":t==="mxf"?"application/mxf":"video/mp4"}function ut(t){if(!t?.poster?.useAsVideoCover)return;const e=(typeof t.poster.preview=="string"?t.poster.preview:"").match(/^data:image\/(?:png|jpe?g);base64,([a-z0-9+/=]+)$/i);if(e)return Buffer.from(e[1],"base64")}function ot(t){const e={...P,...t?.limits};return{async handle(o){const{videos:r,audios:s,overlay:a,videoCover:i,textOverlays:f=[],editStateRaw:m}=o;if(r.length>e.maxVideos)return l(413,"TOO_MANY",`\u89C6\u9891\u6570\u8D85\u8FC7 ${e.maxVideos}`);for(let u=0;u<r.length;u++){if(!/^video\//.test(r[u].type))return l(415,"BAD_TYPE",`video_${u} \u4E0D\u662F\u89C6\u9891\u6587\u4EF6`);if(r[u].bytes.length>e.maxVideoBytes)return l(413,"TOO_LARGE",`\u89C6\u9891 ${u+1} \u8D85\u8FC7 100MB`)}if(!r.length)return l(400,"BAD_REQUEST","\u7F3A\u5C11\u89C6\u9891\u6587\u4EF6(video_0)");if(r.reduce((u,g)=>u+g.bytes.length,0)>e.maxTotalVideoBytes)return l(413,"TOO_LARGE","\u89C6\u9891\u603B\u5927\u5C0F\u8D85\u8FC7 300MB,\u8BF7\u51CF\u5C11\u7D20\u6750\u6216\u538B\u7F29");if(s.length>e.maxAudios)return l(413,"TOO_MANY",`\u97F3\u9891\u6570\u8D85\u8FC7 ${e.maxAudios}`);for(let u=0;u<s.length;u++){const g=/^audio\//.test(s[u].type),F=/^video\//.test(s[u].type);if(!g&&!F)return l(415,"BAD_TYPE",`audio_${u} \u4E0D\u662F\u97F3\u9891\u6216\u89C6\u9891\u6587\u4EF6`);if(s[u].bytes.length>(F?e.maxVideoBytes:e.maxAudioBytes))return l(413,"TOO_LARGE",`\u97F3\u9891 ${u+1} \u8D85\u8FC7 ${F?"100MB":"30MB"}`)}if(typeof m!="string")return l(400,"BAD_REQUEST","\u7F3A\u5C11 editState");if(a&&a.length>e.maxOverlayBytes)return l(413,"OVERLAY_TOO_LARGE","overlay \u8FC7\u5927");if(i&&i.length>e.maxOverlayBytes)return l(413,"COVER_TOO_LARGE","videoCover \u8FC7\u5927");if(f.some(u=>u.length>e.maxOverlayBytes))return l(413,"OVERLAY_TOO_LARGE","textOverlay \u8FC7\u5927");let n;try{n=k.parse(JSON.parse(m))}catch{return l(400,"BAD_STATE","\u7F16\u8F91\u53C2\u6570\u4E0D\u5408\u6CD5")}if(n.clips.some(u=>u.srcIdx>=r.length))return l(400,"BAD_STATE","clips.srcIdx \u8D85\u51FA\u4E0A\u4F20\u89C6\u9891\u6570");if((n.audioClips??[]).some(u=>u.srcIdx>=s.length))return l(400,"BAD_STATE","audioClips.srcIdx \u8D85\u51FA\u4E0A\u4F20\u97F3\u9891\u6570");try{const u=r.map(p=>p.bytes),g=s.map(p=>p.bytes),F=[...new Set((n.audioClips??[]).map(p=>p.srcIdx))];for(const p of F)if(/^video\//.test(s[p].type)&&!await V(g[p]))return l(400,"BAD_TYPE",`\u97F3\u9891 ${p+1} \u662F\u89C6\u9891\u6587\u4EF6\u4F46\u6CA1\u6709\u97F3\u8F68,\u65E0\u6CD5\u63D0\u53D6\u58F0\u97F3`);const C=r.map(()=>!1);if(n.keepAudio){const p=[...new Set(n.clips.map(c=>c.srcIdx))];await Promise.all(p.map(async c=>{C[c]=await V(u[c])})),!C.some(Boolean)&&!(n.audioClips??[]).length&&(n={...n,keepAudio:!1})}const y=[];for(let p=1;p<u.length;p++)y.push({name:`video_${p}.mp4`,bytes:u[p]});g.forEach((p,c)=>y.push({name:`audio_${c}.${M(s[c].type)}`,bytes:p})),a&&y.push({name:"overlay.png",bytes:a}),f.forEach((p,c)=>y.push({name:`textOverlay_${c}.png`,bytes:p}));const A=tt(n.exportSettings?.format),w=i?.length?i:ut(n),E=(p,c,h)=>{const O={videoPaths:[p,...u.slice(1).map((_,B)=>h[`video_${B+1}.mp4`])],videoHasAudio:C,audioPaths:g.map((_,B)=>h[`audio_${B}.${M(s[B].type)}`]),overlayPath:a?h["overlay.png"]:void 0,textOverlayPaths:f.map((_,B)=>h[`textOverlay_${B}.png`]).filter(Boolean)};return Y(n,O,c)};return{ok:!0,bytes:w==null?await L(u[0],E,A,y,28e4):await Z(u[0],E,A,y,w,28e4),contentType:et(A),filename:`edited.${A}`}}catch(u){return(u.message??"").includes("\u4E8C\u8FDB\u5236\u7F3A\u5931")?l(503,"SERVER_NOT_READY","\u670D\u52A1\u7AEF\u7F16\u7801\u7EC4\u4EF6\u672A\u5C31\u7EEA\uFF08ffmpeg \u7F3A\u5931\uFF09\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458"):l(502,"ENCODE_FAILED","\u89C6\u9891\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u6216\u6362\u66F4\u77ED\u7684\u89C6\u9891")}}}}function nt(t){const e=t?.maxBytes??104857600;return{async handle(o,r){if(!/^video\//.test(o.type))return l(415,"BAD_TYPE","\u53EA\u652F\u6301\u89C6\u9891\u6587\u4EF6");if(o.bytes.length>e)return l(413,"TOO_LARGE","\u6587\u4EF6\u8D85\u8FC7 100MB");if(!isFinite(r)||r<0)return l(400,"BAD_TIME","time \u53C2\u6570\u4E0D\u5408\u6CD5");try{return{ok:!0,bytes:await L(o.bytes,(s,a)=>j(s,r,a),"jpg"),contentType:"image/jpeg",filename:"poster.jpg"}}catch(s){return(s.message??"").includes("\u4E8C\u8FDB\u5236\u7F3A\u5931")?l(503,"SERVER_NOT_READY","\u670D\u52A1\u7AEF\u7F16\u7801\u7EC4\u4EF6\u672A\u5C31\u7EEA\uFF08ffmpeg \u7F3A\u5931\uFF09\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458"):l(502,"EXTRACT_FAILED","\u5C01\u9762\u62BD\u53D6\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5")}}}}export{P as DEFAULT_LIMITS,Q as composeVideo,nt as createPosterHandler,ot as createVideoExportHandler,q as extractAudio,V as probeHasAudio,I as probeVideoDuration,L as runVideoEdit};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bylqwjc/media-editor-server",
3
- "version": "1.0.15",
3
+ "version": "1.0.18",
4
4
  "description": "媒体编辑器服务端:框架无关的视频导出/封面处理器 + Web(Next)/Express 适配器(Node + ffmpeg-static)",
5
5
  "type": "module",
6
6
  "license": "MIT",