Files
create-vod/bin/cli.js

86 lines
56 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
import{createRequire as dF}from"node:module";var mF=Object.create;var{getPrototypeOf:cF,defineProperty:Ju,getOwnPropertyNames:lF}=Object;var pF=Object.prototype.hasOwnProperty;var XD=(D,u,F)=>{F=D!=null?mF(cF(D)):{};let E=u||!D||!D.__esModule?Ju(F,"default",{value:D,enumerable:!0}):F;for(let C of lF(D))if(!pF.call(E,C))Ju(E,C,{get:()=>D[C],enumerable:!0});return E};var H=(D,u)=>()=>(u||D((u={exports:{}}).exports,u),u.exports);var n=dF(import.meta.url);var ju=H((D2,Ru)=>{class Lu{constructor(D,u,F){this.etaBufferLength=D||100,this.valueBuffer=[F],this.timeBuffer=[u],this.eta="0"}update(D,u,F){this.valueBuffer.push(u),this.timeBuffer.push(D),this.calculate(F-u)}getTime(){return this.eta}calculate(D){let u=this.valueBuffer.length,F=Math.min(this.etaBufferLength,u),E=this.valueBuffer[u-1]-this.valueBuffer[u-F],C=this.timeBuffer[u-1]-this.timeBuffer[u-F],A=E/C;this.valueBuffer=this.valueBuffer.slice(-this.etaBufferLength),this.timeBuffer=this.timeBuffer.slice(-this.etaBufferLength);let B=Math.ceil(D/A/1000);if(isNaN(B))this.eta="NULL";else if(!isFinite(B))this.eta="INF";else if(B>1e7)this.eta="INF";else if(B<0)this.eta=0;else this.eta=B}}Ru.exports=Lu});var PD=H((u2,wu)=>{var p=n("readline");class Tu{constructor(D){this.stream=D,this.linewrap=!0,this.dy=0}cursorSave(){if(!this.stream.isTTY)return;this.stream.write("\x1B7")}cursorRestore(){if(!this.stream.isTTY)return;this.stream.write("\x1B8")}cursor(D){if(!this.stream.isTTY)return;if(D)this.stream.write("\x1B[?25h");else this.stream.write("\x1B[?25l")}cursorTo(D=null,u=null){if(!this.stream.isTTY)return;p.cursorTo(this.stream,D,u)}cursorRelative(D=null,u=null){if(!this.stream.isTTY)return;this.dy=this.dy+u,p.moveCursor(this.stream,D,u)}cursorRelativeReset(){if(!this.stream.isTTY)return;p.moveCursor(this.stream,0,-this.dy),p.cursorTo(this.stream,0,null),this.dy=0}clearRight(){if(!this.stream.isTTY)return;p.clearLine(this.stream,1)}clearLine(){if(!this.stream.isTTY)return;p.clearLine(this.stream,0)}clearBottom(){if(!this.stream.isTTY)return;p.clearScreenDown(this.stream)}newline(){this.stream.write(`
`),this.dy++}write(D,u=!1){if(this.linewrap===!0&&u===!1)this.stream.write(D.substr(0,this.getWidth()));else this.stream.write(D)}lineWrapping(D){if(!this.stream.isTTY)return;if(this.linewrap=D,D)this.stream.write("\x1B[?7h");else this.stream.write("\x1B[?7l")}isTTY(){return this.stream.isTTY===!0}getWidth(){return this.stream.columns||(this.stream.isTTY?80:200)}}wu.exports=Tu});var Su=H((F2,yu)=>{yu.exports=({onlyFirst:D=!1}={})=>{let u=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"].join("|");return new RegExp(u,D?void 0:"g")}});var vu=H((E2,bu)=>{var U8=Su();bu.exports=(D)=>typeof D==="string"?D.replace(U8(),""):D});var hu=H((C2,hD)=>{var Pu=(D)=>{if(Number.isNaN(D))return!1;if(D>=4352&&(D<=4447||D===9001||D===9002||11904<=D&&D<=12871&&D!==12351||12880<=D&&D<=19903||19968<=D&&D<=42182||43360<=D&&D<=43388||44032<=D&&D<=55203||63744<=D&&D<=64255||65040<=D&&D<=65049||65072<=D&&D<=65131||65281<=D&&D<=65376||65504<=D&&D<=65510||110592<=D&&D<=110593||127488<=D&&D<=127569||131072<=D&&D<=262141))return!0;return!1};hD.exports=Pu;hD.exports.default=Pu});var gu=H((B2,fu)=>{fu.exports=function(){return/\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F|\uD83D\uDC68(?:\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68\uD83C\uDFFB|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|[\u2695\u2696\u2708]\uFE0F|\uD83D[\uDC66\uDC67]|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708])\uFE0F|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C[\uDFFB-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)\uD83C\uDFFB|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB\uDFFC])|\uD83D\uDC69(?:\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD
`).map((C)=>C.trim()).filter(Boolean),F=[],E={cuda:"nvenc",qsv:"qsv",vaapi:"vaapi",videotoolbox:"videotoolbox",v4l2m2m:"v4l2",dxva2:"amf"};for(let C of u){let A=E[C];if(A)F.push({accelerator:A})}return F}async function YD(D){let u=["-v","error","-f","lavfi","-i","testsrc=size=320x240:rate=1","-frames:v","1","-an","-c:v",D,"-f","null","-"];return new Promise((F)=>{let E=f("ffmpeg",u);E.on("error",()=>F(!1)),E.on("close",(C)=>F(C===0))})}async function GD(D,u){let F=["-v","error"];if(D==="nvenc")F.push("-hwaccel","cuda","-hwaccel_output_format","cuda");else if(D==="qsv")F.push("-hwaccel","qsv");else if(D==="vaapi")F.push("-hwaccel","vaapi","-vaapi_device","/dev/dri/renderD128");else if(D==="videotoolbox")F.push("-hwaccel","videotoolbox");else if(D==="v4l2")F.push("-hwaccel","v4l2m2m");else if(D==="amf")return!1;return F.push("-i",u,"-frames:v","1","-f","null","-"),new Promise((E)=>{let C=f("ffmpeg",F);C.on("error",()=>E(!1)),C.on("close",(A)=>E(A===0))})}async function c(D,u,F){let C=`
=== FFmpeg Command [${new Date().toISOString()}] ===
ffmpeg ${D.join(" ")}
`;return await h(C),new Promise((A,B)=>{let $=f("ffmpeg",D),K="";$.stderr.on("data",(X)=>{let U=X.toString();if(K+=U,u&&F){let Y=U.match(/time=(\d{2}):(\d{2}):(\d{2}\.\d{2})/);if(Y){let Z=parseInt(Y[1]),W=parseInt(Y[2]),J=parseFloat(Y[3]),Q=Z*3600+W*60+J,G=Math.min(100,Q/F*100);u(G)}}}),$.on("error",(X)=>{h(`ERROR: ${X.message}
`),B(Error(`FFmpeg error: ${X.message}`))}),$.on("close",(X)=>{if(X===0){let Y=K.split(`
`).filter((Z)=>Z.trim()).slice(-10).join(`
`);h(`SUCCESS: Exit code ${X}
--- Last 10 lines of output ---
${Y}
`),A()}else h(`FAILED: Exit code ${X}
--- Full error output ---
${K}
`),B(Error(`FFmpeg failed with exit code ${X}
${K}`))})})}async function jD(D){let F=`
=== MP4Box Command [${new Date().toISOString()}] ===
MP4Box ${D.join(" ")}
`;return await h(F),new Promise((E,C)=>{let A=f("MP4Box",D),B="",$="";A.stdout.on("data",(K)=>{B+=K.toString()}),A.stderr.on("data",(K)=>{$+=K.toString()}),A.on("error",(K)=>{h(`ERROR: ${K.message}
`),C(Error(`MP4Box error: ${K.message}`))}),A.on("close",(K)=>{if(K===0){let Y=(B||$).split(`
`).filter((Z)=>Z.trim()).slice(-10).join(`
`);h(`SUCCESS: Exit code ${K}
--- Last 10 lines of output ---
${Y}
`),E()}else{let X=$||B;h(`FAILED: Exit code ${K}
--- Full error output ---
${X}
`),C(Error(`MP4Box failed with exit code ${K}
${X}`))}})})}import{spawn as sF}from"node:child_process";async function o(D){return new Promise((u,F)=>{let E=sF("ffprobe",["-v","error","-show_entries","stream=width,height,duration,r_frame_rate,codec_name,codec_type,bit_rate","-show_entries","format=duration","-of","json",D]),C="";E.stdout.on("data",(A)=>{C+=A.toString()}),E.on("error",(A)=>{F(Error(`ffprobe error: ${A.message}`))}),E.on("close",(A)=>{if(A!==0){F(Error(`ffprobe failed with exit code ${A}`));return}try{let B=JSON.parse(C),$=B.streams.find((Q)=>Q.codec_type==="video"),K=B.streams.find((Q)=>Q.codec_type==="audio"),X=B.format;if(!$){F(Error("No video stream found in input file"));return}let U=30;if($.r_frame_rate){let[Q,G]=$.r_frame_rate.split("/").map(Number);if(Q&&G&&G!==0)U=Q/G}let Y=parseFloat($.duration||X.duration||"0"),Z=B.streams.find((Q)=>Q.codec_type==="audio"&&Q.bit_rate),W=Z?.bit_rate?Math.round(parseInt(Z.bit_rate)/1000):void 0,J=$.bit_rate?Math.round(parseInt($.bit_rate)/1000):void 0;u({width:$.width,height:$.height,duration:Y,fps:U,codec:$.codec_name,hasAudio:Boolean(K),audioBitrate:W,videoBitrate:J})}catch(B){F(Error(`Failed to parse ffprobe output: ${B}`))}})})}function UD(D,u=256){if(!D)return`${u}k`;let F=Math.min(D,u);if(F<=64)return"64k";if(F<=96)return"96k";if(F<=128)return"128k";if(F<=192)return"192k";return"256k"}function WD(D){let u=Math.floor(D/3600),F=Math.floor(D%3600/60),E=D%60;return`${String(u).padStart(2,"0")}:${String(F).padStart(2,"0")}:${E.toFixed(3).padStart(6,"0")}`}import{mkdir as aF,access as iF,constants as rF}from"node:fs/promises";async function l(D){try{await iF(D,rF.F_OK)}catch{await aF(D,{recursive:!0})}}function eF(D,u){let F=D*u;if(F<=230400)return 0.08;if(F<=409920)return 0.075;if(F<=921600)return 0.07;if(F<=2073600)return 0.065;if(F<=3686400)return 0.06;return 0.055}function b(D,u,F=30,E){let C=eF(D,u),A=Math.round(D*u*F*C/1000);if(E&&A>E)A=E;return`${A}k`}var TD=[{name:"360p",width:640,height:360,videoBitrate:b(640,360,30),audioBitrate:"192k"},{name:"480p",width:854,height:480,videoBitrate:b(854,480,30),audioBitrate:"192k"},{name:"720p",width:1280,height:720,videoBitrate:b(1280,720,30),audioBitrate:"192k"},{name:"1080p",width:1920,height:1080,videoBitrate:b(1920,1080,30),audioBitrate:"256k"},{name:"1440p",width:2560,height:1440,videoBitrate:b(2560,1440,30),audioBitrate:"256k"},{name:"2160p",width:3840,height:2160,videoBitrate:b(3840,2160,30),audioBitrate:"256k"}];function AD(D,u,F=30,E){let C=[],A=TD.filter((B)=>{return B.width<=D&&B.height<=u});for(let B of A)C.push({...B,videoBitrate:b(B.width,B.height,30,E),fps:30});return C}function D8(D,u,F){return{...D,name:`${D.name}-${u}`,videoBitrate:b(D.width,D.height,u,F),fps:u}}function Ku(D){let F=D.trim().match(/^(\d+)p?(?:[@-](\d+))?$/i);if(!F)return null;let E=F[1]+"p",C=F[2]?parseInt(F[2]):30;return{resolution:E,fps:C}}function Xu(D,u=30,F){let E=TD.find((C)=>C.name===D);if(!E)return null;if(u===30)return{...E,videoBitrate:b(E.width,E.height,30,F),fps:30};return D8(E,u,F)}function u8(D,u,F,E){let C=Ku(D);if(!C)return{error:`Invalid profile format: ${D}. Use format like: 360, 720@60, 1080-60`};let A=Xu(C.resolution,C.fps);if(!A)return{error:`Unknown resolution: ${C.resolution}. Available: 360, 480, 720, 1080, 1440, 2160`};if(A.width>u||A.height>F)return{error:`Source resolution (${u}x${F}) is lower than ${D} (${A.width}x${A.height})`};let B=120,$=C.fps,K;if(C.fps>E)$=Math.min(E,B),K=`Requested ${C.fps} FPS in ${D}, but source is ${E} FPS. Using ${$} FPS instead`;else if(C.fps>B)$=B,K=`Requested ${C.fps} FPS in ${D} exceeds maximum ${B} FPS. Using ${$} FPS instead`;return K?{warning:K,adjustedFps:$}:{}}function ND(D,u,F,E,C){let A=[],B=[],$=[];for(let K of D){let X=u8(K,u,F,E);if(X.error){B.push(X.error);continue}if(X.warning)$.push(X.warning);let U=Ku(K);if(!U)continue;let Y=X.adjustedFps!==void 0?X.adjustedFps:U.fps,Z=Xu(U.resolution,Y,C);if(Z)A.push(Z)}return{profiles:A,errors:B,warnings:$}}import{join as g}from"node:path";import{readdir as F8,unlink as Yu,rmdir as E8,writeFile as Gu}from"node:fs/promises";async function Uu(D,u,F="00:00:00"){let E=g(u,"po
`;for(let $=0;$<D;$++){let K=$*u,X=($+1)*u,U=Math.floor($/C),Z=$%C*F,W=U*E;B+=`${WD(K)} --> ${WD(X)}
`,B+=`${A}#xywh=${Z},${W},${F},${E}
`}return B}import{join as B8}from"node:path";function A8(D,u,F){if(F)if(u==="h264")return 32;else return 42;else if(u==="h264"){if(D<=360)return 25;if(D<=480)return 24;if(D<=720)return 23;if(D<=1080)return 22;if(D<=1440)return 21;return 20}else{if(D<=360)return 40;if(D<=480)return 38;if(D<=720)return 35;if(D<=1080)return 32;if(D<=1440)return 30;return 28}}async function Nu(D,u,F,E,C,A,B,$,K,X,U,Y,Z){let W=B8(u,`video_${K}_${F.name}.mp4`),J=["-y"];if(Y){if(Y==="nvenc")J.push("-hwaccel","cuda","-hwaccel_output_format","cuda");else if(Y==="qsv")J.push("-hwaccel","qsv");else if(Y==="vaapi")J.push("-hwaccel","vaapi");else if(Y==="videotoolbox")J.push("-hwaccel","videotoolbox");else if(Y==="v4l2")J.push("-hwaccel","v4l2")}J.push("-i",D,"-c:v",E);let Q=E.includes("nvenc")||E.includes("qsv")||E.includes("amf")||E.includes("vaapi")||E.includes("videotoolbox")||E.includes("v4l2"),G;if(Q&&X?.cq!==void 0)G=X.cq;else if(!Q&&X?.crf!==void 0)G=X.crf;else G=A8(F.height,K,Q);if(E==="h264_nvenc")J.push("-rc:v","vbr"),J.push("-cq",String(G)),J.push("-preset",C),J.push("-2pass","0");else if(E==="av1_nvenc")J.push("-rc:v","vbr"),J.push("-cq",String(G)),J.push("-preset",C),J.push("-2pass","0");else if(E==="av1_qsv")J.push("-preset",C),J.push("-global_quality",String(G));else if(E==="h264_qsv")J.push("-preset",C),J.push("-global_quality",String(G));else if(E==="av1_amf")J.push("-quality","balanced"),J.push("-rc","cqp"),J.push("-qp_i",String(G)),J.push("-qp_p",String(G));else if(E==="h264_amf")J.push("-quality","balanced"),J.push("-rc","cqp"),J.push("-qp_i",String(G)),J.push("-qp_p",String(G));else if(E==="libsvtav1")J.push("-crf",String(G)),J.push("-preset",C),J.push("-svtav1-params","tune=0:enable-overlays=1");else if(E==="libx264")J.push("-crf",String(G)),J.push("-preset",C);else J.push("-preset",C);let N=K==="av1"?0.6:1,k=Math.round(parseInt(F.videoBitrate)*N*1.5);J.push("-maxrate",`${k}k`),J.push("-bufsize",`${k*2}k`);let x=F.fps||30,O=Math.round(x*B);J.push("-g",String(O),"-keyint_min",String(O),"-sc_threshold","0");let M=[];if(Y==="nvenc")M.push(`scale_cuda=${F.width}:${F.height}`);else M.push(`scale=${F.width}:${F.height}`);if(U){if(U.deinterlace)M.push("yadif");if(U.denoise)M.push("hqdn3d");if(U.customFilters)M.push(...U.customFilters)}J.push("-vf",M.join(","));let S=parseInt(F.audioBitrate)||256,ED=UD($,S);if(J.push("-c:a","aac","-b:a",ED),U?.audioNormalize)J.push("-af","loudnorm");return J.push("-f","mp4",W),await c(J,Z,A),W}async function ku(D,u,F,E,C,A,B,$,K,X,U,Y,Z,W,J){let Q=new Map;if(K&&F.length>1)for(let G=0;G<F.length;G+=X){let N=F.slice(G,G+X),k=N.map((O)=>Nu(D,u,O,E,C,A,B,$,U,Y,Z,W,(M)=>{if(J)J(O.name,M)}));(await Promise.all(k)).forEach((O,M)=>{let S=N[M];Q.set(S.name,O)})}else for(let G of F){let N=await Nu(D,u,G,E,C,A,B,$,U,Y,Z,W,(k)=>{if(J)J(G.name,k)});Q.set(G.name,N)}return Q}import{join as L}from"node:path";import{readdir as Iu,rename as P3,mkdir as h3,writeFile as bD}from"node:fs/promises";import{readFile as wD,writeFile as yD}from"node:fs/promises";async function Qu(D){let u=await wD(D,"utf-8");u=u.replace(/\/\/>/g,"/>"),u=u.replace(/\/\s+\/>/g,"/>"),u=u.replace(/(<Representation[^>]+)\s+\/>/g,"$1/>"),u=u.replace(/<Representation\s+([^>]+)\/>\s*<\/Representation>/g,"<Representation $1/>"),u=u.replace(/<Representation\s+([^>]+)\/>\s*(<AudioChannelConfiguration[^>]*\/>)/g,`<Representation $1>
$2
</Representation>`),u=u.replace(/<Representation\s+([^>]+)>\s*(?=<(?:Representation|\/AdaptationSet))/g,`<Representation $1/>
`),await yD(D,u,"utf-8")}async function _u(D){let u=await wD(D,"utf-8");u=u.replace(/media="\$RepresentationID\$_\$Number\$\.m4s"/g,'media="$RepresentationID$/$RepresentationID$_$Number$.m4s"'),u=u.replace(/initialization="\$RepresentationID\$_\.mp4"/g,'initialization="$RepresentationID$/$RepresentationID$_.mp4"'),await yD(D,u,"utf-8")}async function zu(D){let F=(await wD(D,"utf-8")).split(`
`),E=[],C=0;while(C<F.length){let A=F[C];if(A.includes("<AdaptationSet")&&A.includes("maxWidth")){let B=C,$=[A],K=[],X=[],U=[],Y=!1;C++;while(C<F.length&&!F[C].includes("</AdaptationSet>")){let Z=F[C];if(Z.includes("<SegmentTemplate"))Y=!0;if(Y){if(K.push(Z),Z.includes("</SegmentTemplate>"))Y=!1}else if(Z.includes("<Representation")&&Z.includes("-h264"))X.push(Z);else if(Z.includes("<Representation")&&Z.includes("-av1"))U.push(Z);C++}if(X.length>0&&U.length>0)E.push(A),K.forEach((Z)=>E.push(Z)),X.forEach((Z)=>E.push(Z)),E.push(" </AdaptationSet>"),E.push(A),K.forEach((Z)=>E.push(Z)),U.forEach((Z)=>E.push(Z)),E.push(" </AdaptationSet>");else{E.push(A);for(let Z=B+1;Z<C;Z++)E.push(F[Z]);E.push(F[C])}C++}else E.push(A),C++}await yD(D,E.join(`
`),"utf-8")}function SD(D,u,F){let E=`#EXTM3U
`;E+=`#EXT-X-VERSION:6
`,E+=`#EXT-X-TARGETDURATION:${Math.ceil(F)}
`,E+=`#EXT-X-MEDIA-SEQUENCE:1
`,E+=`#EXT-X-INDEPENDENT-SEGMENTS
`,E+=`#EXT-X-MAP:URI="${u}"
`;for(let C of D)E+=`#EXTINF:${F},
`,E+=`${C}
`;return E+=`#EXT-X-ENDLIST
`,E}function qu(D,u){let F=`#EXTM3U
`;if(F+=`#EXT-X-VERSION:6
`,F+=`#EXT-X-INDEPENDENT-SEGMENTS
`,u)F+=`#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="audio",AUTOSELECT=YES,URI="audio/playlist.m3u8",CHANNELS="2"
`;for(let E of D){let C=u?"avc1.4D4020,mp4a.40.2":"avc1.4D4020";if(F+=`#EXT-X-STREAM-INF:BANDWIDTH=${E.bandwidth},CODECS="${C}",RESOLUTION=${E.resolution},FRAME-RATE=${E.fps}`,u)F+=',AUDIO="audio"';F+=`
`,F+=`${E.path}
`}return F}async function Z8(D,u,F,E,C,A){let B=L(u,"manifest.mpd"),$=C.length>1,K=["-dash",String(E*1000),"-frag",String(E*1000),"-rap","-segment-timeline","-segment-name","$RepresentationID$_$Number$","-out",B],X=!0;for(let[U,Y]of D.entries())for(let Z of F){let W=Y.get(Z.name);if(!W)throw Error(`MP4 file not found for profile: ${Z.name}, codec: ${U}`);let J=$?`${Z.name}-${U}`:Z.name;if(K.push(`${W}#video:id=${J}`),X&&A)K.push(`${W}#audio:id=audio`),X=!1}if(await jD(K),await $8(u,F,C,A),await _u(B),$)await zu(B);return await Qu(B),B}async function $8(D,u,F,E){let{readdir:C,rename:A,mkdir:B}=await import("node:fs/promises"),$=F.length>1,K=[];for(let Y of F)for(let Z of u){let W=$?`${Z.name}-${Y}`:Z.name;K.push(W);let J=L(D,W);await B(J,{recursive:!0})}let X=L(D,"audio");if(E)await B(X,{recursive:!0});let U=await C(D);for(let Y of U){if(Y==="manifest.mpd")continue;if(E&&(Y.startsWith("audio_")||Y==="audio_init.m4s")){let Z=L(D,Y),W=L(X,Y);await A(Z,W);continue}for(let Z of K)if(Y.startsWith(`${Z}_`)){let W=L(D,Y),J=L(D,Z,Y);await A(W,J);break}}}async function Hu(D,u,F,E,C,A,B){let $,K,X=A.length>0,U=A.includes("dash"),Y=A.includes("hls");if(X){if($=await Z8(D,u,F,E,C,B),!U)$=void 0}if(Y)K=await J8(u,F,E,C.length>1,B);return{manifestPath:$,hlsManifestPath:K}}async function J8(D,u,F,E,C){let A=L(D,"master.m3u8"),B=[];for(let U of u){let Y=E?`${U.name}-h264`:U.name,Z=L(D,Y),W=await Iu(Z),J=W.filter((x)=>x.endsWith(".m4s")).sort((x,O)=>{let M=parseInt(x.match(/_(\d+)\.m4s$/)?.[1]||"0"),S=parseInt(O.match(/_(\d+)\.m4s$/)?.[1]||"0");return M-S}),Q=W.find((x)=>x.endsWith("_.mp4"));if(!Q||J.length===0)continue;let G=SD(J,Q,F),N=L(Z,"playlist.m3u8");await bD(N,G,"utf-8");let k=parseInt(U.videoBitrate)*1000;B.push({path:`${Y}/playlist.m3u8`,bandwidth:k,resolution:`${U.width}x${U.height}`,fps:U.fps||30})}let $,K=[];if(C){let U=L(D,"audio"),Y=[];try{Y=await Iu(U)}catch{Y=[]}if(K=Y.filter((Z)=>Z.endsWith(".m4s")).sort((Z,W)=>{let J=parseInt(Z.match(/_(\d+)\.m4s$/)?.[1]||"0"),Q=parseInt(W.match(/_(\d+)\.m4s$/)?.[1]||"0");return J-Q}),$=Y.find((Z)=>Z.endsWith("_.mp4")),$&&K.length>0){let Z=SD(K,$,F);await bD(L(U,"playlist.m3u8"),Z,"utf-8")}}let X=qu(B,C&&$!==void 0&&K.length>0);return await bD(A,X,"utf-8"),A}async function vD(D){let{input:u,outputDir:F,segmentDuration:E=2,profiles:C,customProfiles:A,codec:B=["h264"],formats:$=["dash","hls"],hardwareDecoder:K,hardwareAccelerator:X,quality:U,generateThumbnails:Y=!0,thumbnailConfig:Z={},generatePoster:W=!0,posterTimecode:J="00:00:00",parallel:Q=!0,onProgress:G}=D,N=kD("/tmp",`dash-converter-${K8()}`);await l(N);let k=xu(u,Mu(u)),x=kD(F,k);await l(x);let O=kD(x,"conversion.log");RD(O);let{writeFile:M}=await import("node:fs/promises"),S=`===========================================
DASH Conversion Log
Started: ${new Date().toISOString()}
Input: ${u}
Output: ${x}
Codec: ${Array.isArray(B)?B.join(","):B}
Formats: ${$?.join(",")||"dash,hls"}
===========================================
`;await M(O,S,"utf-8");try{return await X8(u,F,N,E,C,A,B,$,X,K,U,Y,Z,W,J,Q,G)}finally{let{appendFile:ED}=await import("node:fs/promises");try{await ED(O,`
Completed: ${new Date().toISOString()}
`,"utf-8")}catch($D){}try{await Ou(N,{recursive:!0,force:!0})}catch($D){console.warn(`Warning: Failed to cleanup temp directory: ${N}`)}}}async function X8(D,u,F,E,C,A,B,$,K,X,U,Y,Z,W,J,Q,G){if(!await s())throw Error("FFmpeg is not installed or not in PATH");if(!await a())throw Error("MP4Box is not installed or not in PATH. Install gpac package.");let N=(z,I,MD,OD)=>{if(G)G({stage:z,percent:I,message:MD,currentProfile:OD})};N("analyzing",0,"Analyzing input video...");let k=await o(D),x=k.hasAudio,O=K&&K!=="auto"?K:"auto",M=await i(),S=await r(),ED=M.some((z)=>z.av1Encoder),$D=Array.isArray(B)?B:[B],tD=$D.includes("h264"),VD=$D.includes("av1"),{selected:JD,h264Encoder:RF,av1Encoder:jF,warnings:eD}=Y8(M,O,tD,VD);if(eD.length>0)for(let z of eD)console.warn(` ${z}`);let{selected:KD}=G8(S,X||"auto");if(VD&&!ED)console.warn("⚠️ AV1 hardware encoder not detected. AV1 will use CPU encoder (slow).");let v=[];if(tD)v.push("h264");if(VD)v.push("av1");if(v.length===0)v.push("h264");let Du=$&&$.length>0?Array.from(new Set($)):["dash","hls"],R;if(A&&A.length>0){let z=ND(A,k.width,k.height,k.fps,k.videoBitrate);if(z.errors.length>0){console.warn(`
Profile errors:`);for(let I of z.errors)console.warn(` - ${I}`);console.warn("")}if(z.warnings.length>0){console.warn(`
Profile warnings:`);for(let I of z.warnings)console.warn(` - ${I}`);console.warn("")}if(R=z.profiles,R.length===0)throw Error("No valid profiles found in custom list. Check errors above.")}else if(C)R=C;else R=AD(k.width,k.height,k.fps,k.videoBitrate);if(R.length===0)throw Error("No suitable profiles found for input video resolution");let TF=xu(D,Mu(D)),CD=kD(u,TF);try{await Ou(CD,{recursive:!0,force:!0})}catch(z){}await l(CD);let P=[];if(v.includes("h264")){let z=RF||"libx264",I=Vu(z,"h264");P.push({type:"h264",codec:z,preset:I})}if(v.includes("av1")){let z=jF||"libsvtav1",I=Vu(z,"av1");P.push({type:"av1",codec:z,preset:I})}let wF=P.map((z)=>z.type.toUpperCase()).join(" + "),yF=JD==="cpu"?"CPU":JD.toUpperCase();N("analyzing",20,`Using ${wF} encoding (${yF}, decoder ${KD.toUpperCase()})`,void 0);let SF=JD==="cpu"?2:3,xD=new Map;for(let z=0;z<P.length;z++){let{type:I,codec:MD,preset:OD}=P[z],Bu=z/P.length,PF=1/P.length;N("encoding",25+Bu*40,`Stage 1: Encoding ${I.toUpperCase()} (${R.length} profiles)...`);let hF=I==="h264"?U?.h264:U?.av1,fF=await ku(D,F,R,MD,OD,k.duration,E,k.audioBitrate,Q,SF,I,hF,void 0,KD==="cpu"?void 0:KD,(BD,Au)=>{let J3=R.findIndex((gF)=>gF.name===BD),Zu=25+Bu*40,$u=Au/100*(40*PF/R.length);if(N("encoding",Zu+$u,`Encoding ${I.toUpperCase()} ${BD}...`,`${I}-${BD}`),G)G({stage:"encoding",percent:Zu+$u,currentProfile:`${I}-${BD}`,profilePercent:Au,message:`Encoding ${I.toUpperCase()} ${BD}...`})});xD.set(I,fF)}N("encoding",65,"Stage 1 complete: All codecs and profiles encoded"),N("encoding",70,"Stage 2: Creating segments and manifests...");let{manifestPath:bF,hlsManifestPath:vF}=await Hu(xD,CD,R,E,v,Du,x),uu=[];for(let z of xD.values())uu.push(...Array.from(z.values()));N("encoding",80,"Stage 2 complete: All formats packaged");let Fu,Eu;if(Y){N("thumbnails",80,"Generating thumbnail sprites...");let z={width:Z.width||160,height:Z.height||90,interval:Z.interval||1,columns:Z.columns||10},I=await Wu(D,CD,k.duration,z);Fu=I.spritePath,Eu=I.vttPath,N("thumbnails",90,"Thumbnails generated")}let Cu;if(W)N("thumbnails",92,"Generating poster image..."),Cu=await Uu(D,CD,J),N("thumbnails",95,"Poster generated");return N("manifest",95,"Finalizing..."),N("complete",100,"Conversion complete!"),{manifestPath:bF,hlsManifestPath:vF,videoPaths:uu,thumbnailSpritePath:Fu,thumbnailVttPath:Eu,posterPath:Cu,duration:k.duration,profiles:R,usedNvenc:P.some((z)=>z.codec.includes("nvenc")),selectedAccelerator:JD,selectedDecoder:KD,codecs:v,formats:Du}}var t={nvenc:100,qsv:90,amf:80,vaapi:70,videotoolbox:65,v4l2:60,cpu:1};function Y8(D,u,F,E){let C=[],A=new Set(["nvenc","qsv","amf","vaapi","videotoolbox","v4l2"]),B=D.filter((G)=>F&&G.h264Encoder||E&&G.av1Encoder),$=B.filter((G)=>A.has(G.accelerator)),K=(G)=>B.find((N)=>N.accelerator===G);if(u==="cpu")return{selected:"cpu",h264Encoder:void 0,av1Encoder:void 0,warnings:C};let X;if(u!=="auto"){if(!A.has(u))C.push(`Ускоритель "${u}" пока не поддерживается, использую CPU`);else if(X=K(u),!X)throw Error(`Аппаратный ускоритель "${u}" недоступен в системе`)}else if(X=($.length>0?$:[]).sort((N,k)=>(t[k.accelerator]||0)-(t[N.accelerator]||0))[0],!X&&B.length>0)C.push("Доступен аппаратный ускоритель, но он пока не поддерживается пайплайном, использую CPU");let Y=($.length>0?$:[]).sort((G,N)=>(t[N.accelerator]||0)-(t[G.accelerator]||0)),Z=(G)=>{let N=G==="h264"?X?.h264Encoder:X?.av1Encoder;if(N)return{encoder:N,accel:X?.accelerator};let k=Y.find((x)=>G==="h264"?x.h264Encoder:x.av1Encoder);if(k){if(u!=="auto"&&X)C.push(`Выбранный ускоритель "${X.accelerator}" не поддерживает ${G.toUpperCase()}, использую ${k.accelerator}`);return{encoder:G==="h264"?k.h264Encoder:k.av1Encoder,accel:k.accelerator}}if(u!=="auto")C.push(`Ускоритель "${u}" не поддерживает ${G.toUpperCase()}, использую CPU`);return{encoder:void 0,accel:"cpu"}},W=F?Z("h264"):{encoder:void 0,accel:X?.accel
Options:`),console.error(" -r, --resolutions Video resolutions (e.g., 360,480,720 or 720@60,1080@60)"),console.error(" -c, --codec Video codec: av1 or h264 (default: auto = h264 + AV1 if HW)"),console.error(" -f, --format Streaming format: dash or hls (default: auto = dash + hls)"),console.error(" -p, --poster Poster timecode (e.g., 00:00:05 or 10)"),console.error(" -e, --encoder <type> Hardware encoder: auto|nvenc|qsv|amf|vaapi|videotoolbox|v4l2|cpu (default: auto)"),console.error(" -d, --decoder <type> Hardware decoder: auto|nvenc|qsv|amf|vaapi|videotoolbox|v4l2|cpu (default: auto)"),console.error(`
Quality Options (override defaults):`),console.error(" --h264-cq <value> H.264 GPU CQ value (0-51, lower = better, default: auto)"),console.error(" --h264-crf <value> H.264 CPU CRF value (0-51, lower = better, default: auto)"),console.error(" --av1-cq <value> AV1 GPU CQ value (0-51, lower = better, default: auto)"),console.error(" --av1-crf <value> AV1 CPU CRF value (0-63, lower = better, default: auto)"),console.error(`
Examples:`),console.error(" create-vod video.mp4"),console.error(" create-vod video.mp4 ./output"),console.error(" create-vod video.mp4 -r 360,480,720"),console.error(" create-vod video.mp4 -c av1 --av1-cq 40"),console.error(" create-vod video.mp4 -c h264 --h264-cq 30"),console.error(" create-vod video.mp4 -f hls"),console.error(" create-vod video.mp4 -r 720@60,1080@60,2160@60 -c av1 -f dash"),console.error(" create-vod video.mp4 -p 00:00:05"),console.error(" create-vod video.mp4 ./output -r 720,1080 -p 10 --h264-cq 28"),process.exit(1);console.log(`\uD83D\uDD0D Checking system...
`);var zF=await s(),qF=await a(),IF=await i(),l8=await r(),p8=IF.some((D)=>D.av1Encoder),qD={nvenc:100,qsv:90,amf:80,vaapi:70,videotoolbox:65,v4l2:60,cpu:1},d8={nvenc:"h264_nvenc",qsv:"h264_qsv",amf:"h264_amf",vaapi:"h264_vaapi",videotoolbox:"h264_videotoolbox",v4l2:"h264_v4l2m2m",cpu:"libx264"},n8=Array.from(new Set([...IF.map((D)=>D.accelerator),"cpu"])),s8=Array.from(new Set([...l8.map((D)=>D.accelerator),"cpu"]));async function a8(){let D=[];for(let u of n8){if(u==="amf")continue;let F=d8[u]||"libx264";if(await YD(F))D.push(u)}return D}async function i8(){let D=[];for(let u of s8){if(u==="cpu"){D.push("cpu");continue}if(await GD(u,d))D.push(u)}return D}var HF=await a8(),VF=await i8(),uD=HF.slice().sort((D,u)=>(qD[u]||0)-(qD[D]||0))[0],FD=VF.slice().sort((D,u)=>(qD[u]||0)-(qD[D]||0))[0];console.log(`FFmpeg: ${zF?"✅":"❌"}`);console.log(`MP4Box: ${qF?"✅":"❌"}`);var GF=Array.from(new Set(HF.map((D)=>D.toUpperCase()))),UF=Array.from(new Set(VF.map((D)=>D.toUpperCase()))),WF=e?e.toUpperCase():uD&&uD.toUpperCase()||"CPU",xF=GF.length>0?GF:["CPU"],NF=DD?DD.toUpperCase():FD&&FD.toUpperCase()||"CPU",MF=UF.length>0?UF:["CPU"];console.log(`Encoder: ${WF==="AUTO"?uD&&uD.toUpperCase()||"CPU":WF} (${xF.join(", ")})`);console.log(`Decoder: ${NF==="AUTO"?FD&&FD.toUpperCase()||"CPU":NF} (${MF.join(", ")})`);console.log("");if(!zF)console.error("❌ FFmpeg not found. Please install FFmpeg first."),process.exit(1);if(!qF)console.error("❌ MP4Box not found. Please install: sudo pacman -S gpac"),process.exit(1);var oD=zD&&zD.length>0?zD:["h264"],ID=oD.includes("h264"),HD=oD.includes("av1");if(!ID)console.warn("⚠️ H.264 is mandatory for compatibility. Adding H.264."),ID=!0;if(HD&&!p8)console.error("⚠️ AV1 requested but no hardware AV1 encoder found."),console.error(" CPU-based AV1 encoding (libsvtav1) will be VERY slow."),console.error(` Consider using --codec h264 for faster encoding.
`);var r8=!0,o8=!0;console.log(`\uD83D\uDCCA Analyzing video...
`);var V=await o(d),t8=c8(d),e8=(t8.size/1048576).toFixed(2);console.log("\uD83D\uDCF9 Video Information:");console.log(` File: ${d}`);console.log(` Size: ${e8} MB`);console.log(` Resolution: ${V.width}x${V.height}`);console.log(` FPS: ${V.fps.toFixed(2)}`);console.log(` Duration: ${Math.floor(V.duration/60)}m ${Math.floor(V.duration%60)}s`);console.log(` Codec: ${V.codec}`);if(V.videoBitrate)console.log(` Video Bitrate: ${(V.videoBitrate/1000).toFixed(2)} Mbps`);if(V.audioBitrate)console.log(` Audio Bitrate: ${V.audioBitrate} kbps`);var aD=[];if(ZD&&ZD.length>0){let D=ND(ZD,V.width,V.height,V.fps,V.videoBitrate);if(D.errors.length>0)console.error(`
Profile errors:`),D.errors.forEach((u)=>console.error(` - ${u}`)),process.exit(1);if(D.warnings.length>0)console.warn(`
Profile warnings:`),D.warnings.forEach((u)=>console.warn(` - ${u}`));aD=D.profiles.map((u)=>u.name)}else aD=AD(V.width,V.height,V.fps,V.videoBitrate).map((u)=>u.name);var D3=[r8?"DASH (manifest.mpd)":null,o8?"HLS (master.m3u8)":null].filter(Boolean).join(", "),u3=!0,F3=iD||"00:00:00",E3=[ID?"h264":null,HD?"av1":null].filter(Boolean).join(", "),C3=!HD&&oD.includes("av1")?" (AV1 disabled: no HW)":"",OF=uD&&uD.toUpperCase()||"CPU",LF=FD&&FD.toUpperCase()||"CPU",kF=e?e.toUpperCase():OF,QF=DD?DD.toUpperCase():LF,B3=kF==="AUTO"?OF:kF,A3=QF==="AUTO"?LF:QF,Z3=xF.join(", "),$3=MF.join(", ");console.log(`
\uD83D\uDCE6 Parameters:`);console.log(` Input: ${d}`);console.log(` Output: ${_F}`);console.log(` Codec: ${E3}${C3}`);console.log(` Profiles: ${aD.join(", ")}`);console.log(` Manifests: ${D3}`);console.log(` Poster: ${F3} (will be generated)`);console.log(` Thumbnails: ${u3?"yes (with VTT)":"no"}`);console.log(` Encoder: ${B3} (available: ${Z3})`);console.log(` Decoder: ${A3} (available: ${$3})`);var m;if(j!==void 0||T!==void 0||w!==void 0||y!==void 0){if(m={},j!==void 0||T!==void 0){if(m.h264={},j!==void 0)m.h264.cq=j;if(T!==void 0)m.h264.crf=T;console.log(`\uD83C\uDF9A H.264 Quality: ${j!==void 0?`CQ ${j}`:""}${T!==void 0?` CRF ${T}`:""}`)}if(w!==void 0||y!==void 0){if(m.av1={},w!==void 0)m.av1.cq=w;if(y!==void 0)m.av1.crf=y;console.log(`\uD83C\uDF9A AV1 Quality: ${w!==void 0?`CQ ${w}`:""}${y!==void 0?` CRF ${y}`:""}`)}}console.log(`
\uD83D\uDE80 Starting conversion...
`);var _D=new sD.default.MultiBar({format:"{stage} | {bar} | {percentage}% | {name}",barCompleteChar:"█",barIncompleteChar:"░",hideCursor:!0,clearOnComplete:!1,stopOnComplete:!0},sD.default.Presets.shades_classic),dD={},nD=null;try{let D=Date.now(),u=await vD({input:d,outputDir:_F,customProfiles:ZD,posterTimecode:iD,codec:[...ID?["h264"]:[],...HD?["av1"]:[]],segmentDuration:2,hardwareAccelerator:e,hardwareDecoder:DD,quality:m,generateThumbnails:!0,generatePoster:!0,parallel:!0,onProgress:(C)=>{let A=C.stage==="encoding"?"Encoding":C.stage==="thumbnails"?"Thumbnails":C.stage==="manifest"?"Manifest":C.stage==="analyzing"?"Analyzing":"Complete";if(C.stage==="encoding"&&C.currentProfile){if(!dD[C.currentProfile])dD[C.currentProfile]=_D.create(100,0,{stage:"Encode",name:C.currentProfile});let B=C.profilePercent??C.percent;dD[C.currentProfile].update(B,{stage:"Encode",name:C.currentProfile})}if(!nD)nD=_D.create(100,0,{stage:A,name:"Overall"});nD.update(C.percent,{stage:A,name:C.message||"Overall"})}});_D.stop();let E=((Date.now()-D)/1000).toFixed(2);console.log(`
Conversion completed successfully! (${E}s)
`)}catch(D){_D.stop(),console.error(`
Error during conversion:`),console.error(D),process.exit(1)}