`).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 WD(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=g("ffmpeg",u);E.on("error",()=>F(!1)),E.on("close",(C)=>F(C===0))})}async function ND(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=g("ffmpeg",F);C.on("error",()=>E(!1)),C.on("close",(A)=>E(A===0))})}async function l(D,u,F){let C=`
${X}`))}})})}import{spawn as aF}from"node:child_process";async function DD(D){return new Promise((u,F)=>{let E=aF("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(`ffprobeerror:${A.message}`))}),E.on("close",(A)=>{if(A!==0){F(Error(`ffprobefailedwithexitcode${A}`));return}try{let B=JSON.parse(C),$=B.streams.find((_)=>_.codec_type==="video"),K=B.streams.find((_)=>_.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[_,G]=$.r_frame_rate.split("/").map(Number);if(_&&G&&G!==0)U=_/G}let Y=parseFloat($.duration||X.duration||"0"),Z=B.streams.find((_)=>_.codec_type==="audio"&&_.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(`Failedtoparseffprobeoutput:${B}`))}})})}function kD(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 QD(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 iF,access as rF,constants as oF}from"node:fs/promises";async function c(D){try{await rF(D,oF.F_OK)}catch{await iF(D,{recursive:!0})}}function D8(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=D8(D,u),A=Math.round(D*u*F*C/1000);if(E&&A>E)A=E;return`${A}k`}var wD=[{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 JD(D,u,F=30,E){let C=[],A=wD.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 u8(D,u,F){return{...D,name:`${D.name}-${u}`,videoBitrate:b(D.width,D.height,u,F),fps:u}}function Ju(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 Ku(D,u=30,F){let E=wD.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 u8(E,u,F)}function F8(D,u,F,E){let C=Ju(D);if(!C)return{error:`Invalidprofileformat:${D}.Useformatlike:360,720@60,1080-60`};let A=Ku(C.resolution,C.fps);if(!A)return{error:`Unknownresolution:${C.resolution}.Available:360,480,720,1080,1440,2160`};if(A.width>u||A.height>F)return{error:`Sourceresolution(${u}x${F})islowerthan${D}(${A.width}x${A.height})`};let B=120,$=C.fps,K;if(C.fps>E)$=Math.min(E,B),K=`Requested${C.fps}FPSin${D},butsourceis${E}FPS.Using${$}FPSinstead`;else if(C.fps>B)$=B,K=`Requested${C.fps}FPSin${D}exceedsmaximum${B}FPS.Using${$}FPSinstead`;return K?{warning:K,adjustedFps:$}:{}}function _D(D,u,F,E,C){let A=[],B=[],$=[];for(let K of D){let X=F8(K,u,F,E);if(X.error){B.push(X.error);continue}if(X.warning)$.push(X.warning);let U=Ju(K);if(!U)continue;let Y=X.adjustedFps!==void 0?X.adjustedFps:U.fps,Z=Ku(U.resolution,Y,C);if(Z)A.push(Z)}return{profiles:A,errors:B,warnings:$}}import{join as m}from"node:path";import{readdir as E8,unlink as Xu,rmdir as C8,writeFile as Yu}from"node:fs/promises";async function Gu(D,u,F="00:00:00"){let E=m(u,"p
`;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+=`
`}return F}async function $8(D,u,F,E,C,A){let B=O(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(`MP4filenotfoundforprofile:${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 TD(K),await J8(u,F,C,A),await Qu(B),$)await _u(B);return await ku(B),B}async function J8(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=O(D,W);await B(J,{recursive:!0})}let X=O(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=O(D,Y),W=O(X,Y);await A(Z,W);continue}for(let Z of K)if(Y.startsWith(`${Z}_`)){let W=O(D,Y),J=O(D,Z,Y);await A(W,J);break}}}async function Iu(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 $8(D,u,F,E,C,B),!U)$=void 0}if(Y)K=await K8(u,F,E,C.length>1,B);return{manifestPath:$,hlsManifestPath:K}}async function K8(D,u,F,E,C){let A=O(D,"master.m3u8"),B=[];for(let U of u){let Y=E?`${U.name}-h264`:U.name,Z=O(D,Y),W=await qu(Z),J=W.filter((x)=>x.endsWith(".m4s")).sort((x,L)=>{let M=parseInt(x.match(/_(\d+)\.m4s$/)?.[1]||"0"),S=parseInt(L.match(/_(\d+)\.m4s$/)?.[1]||"0");return M-S}),_=W.find((x)=>x.endsWith("_.mp4"));if(!_||J.length===0)continue;let G=bD(J,_,F),N=O(Z,"playlist.m3u8");await vD(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=O(D,"audio"),Y=[];try{Y=await qu(U)}catch{Y=[]}if(K=Y.filter((Z)=>Z.endsWith(".m4s")).sort((Z,W)=>{let J=parseInt(Z.match(/_(\d+)\.m4s$/)?.[1]||"0"),_=parseInt(W.match(/_(\d+)\.m4s$/)?.[1]||"0");return J-_}),$=Y.find((Z)=>Z.endsWith("_.mp4")),$&&K.length>0){let Z=bD(K,$,F);await vD(O(U,"playlist.m3u8"),Z,"utf-8")}}let X=zu(B,C&&$!==void 0&&K.length>0);return await vD(A,X,"utf-8"),A}async function PD(D){let{input:u,outputDir:F,segmentDuration:E=2,profiles:C,customProfiles:A,codec:B="auto",format:$="auto",hardwareDecoder:K,hardwareAccelerator:X,quality:U,generateThumbnails:Y=!0,thumbnailConfig:Z={},generatePoster:W=!0,posterTimecode:J="00:00:00",parallel:_=!0,onProgress:G}=D,N=zD("/tmp",`dash-converter-${X8()}`);await c(N);let k=Hu(u,xu(u)),x=zD(F,k);await c(x);let L=zD(x,"conversion.log");jD(L);let{writeFile:M}=await import("node:fs/promises"),S=`===========================================
`,"utf-8")}catch(XD){}try{await Mu(N,{recursive:!0,force:!0})}catch(XD){console.warn(`Warning:Failedtocleanuptempdirectory:${N}`)}}}async function Y8(D,u,F,E,C,A,B,$,K,X,U,Y,Z,W,J,_,G){if(!await r())throw Error("FFmpeg is not installed or not in PATH");if(!await o())throw Error("MP4Box is not installed or not in PATH. Install gpac package.");let N=(z,I,LD,OD)=>{if(G)G({stage:z,percent:I,message:LD,currentProfile:OD})};N("analyzing",0,"Analyzing input video...");let k=await DD(D),x=k.hasAudio,L=K&&K!=="auto"?K:"auto",M=await t(),S=await e(),s=M.some((z)=>z.av1Encoder),XD=B==="h264"||B==="auto",xD=B==="av1"||B==="auto";if(B==="auto"&&!s)xD=!1;let{selected:YD,h264Encoder:jF,av1Encoder:TF,warnings:eD}=G8(M,L,XD,xD);if(eD.length>0)for(let z of eD)console.warn(`⚠️${z}`);let{selected:GD}=U8(S,X||"auto");if(B==="av1"&&!s)console.warn("⚠️ AV1 hardware encoder not detected. AV1 will use CPU encoder (slow).");let P=[];if(XD)P.push("h264");if(xD)P.push("av1");if(P.length===0)P.push("h264");let a=[];if($==="dash"||$==="auto")a.push("dash");if($==="hls"||$==="auto")a.push("hls");if(a.length===0)a.push("dash");let R;if(A&&A.length>0){let z=_D(A,k.width,k.height,k.fps,k.videoBitrate);if(z.errors.length>0){console.warn(`
❌Profileerrors:`);for(let I of z.errors)console.warn(`-${I}`);console.warn("")}if(z.warnings.length>0){console.warn(`
⚠️Profilewarnings:`);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=JD(k.width,k.height,k.fps,k.videoBitrate);if(R.length===0)throw Error("No suitable profiles found for input video resolution");let wF=Hu(D,xu(D)),ZD=zD(u,wF);try{await Mu(ZD,{recursive:!0,force:!0})}catch(z){}await c(ZD);let h=[];if(P.includes("h264")){let z=jF||"libx264",I=Vu(z,"h264");h.push({type:"h264",codec:z,preset:I})}if(P.includes("av1")){let z=TF||"libsvtav1",I=Vu(z,"av1");h.push({type:"av1",codec:z,preset:I})}let yF=h.map((z)=>z.type.toUpperCase()).join(" + "),SF=YD==="cpu"?"CPU":YD.toUpperCase();N("analyzing",20,`Using${yF}encoding(${SF},decoder${GD.toUpperCase()})`,void 0);let bF=YD==="cpu"?2:3,MD=new Map;for(let z=0;z<h.length;z++){let{type:I,codec:LD,preset:OD}=h[z],Cu=z/h.length,hF=1/h.length;N("encoding",25+Cu*40,`Stage1:Encoding${I.toUpperCase()}(${R.length}profiles)...`);let fF=I==="h264"?U?.h264:U?.av1,gF=await Nu(D,F,R,LD,OD,k.duration,E,k.audioBitrate,_,bF,I,fF,void 0,GD==="cpu"?void 0:GD,($D,Bu)=>{let $3=R.findIndex((mF)=>mF.name===$D),Au=25+Cu*40,Zu=Bu/100*(40*hF/R.length);if(N("encoding",Au+Zu,`Encoding${I.toUpperCase()}${$D}...`,`${I}-${$D}`),G)G({stage:"encoding",percent:Au+Zu,currentProfile:`${I}-${$D}`,profilePercent:Bu,message:`Encoding${I.toUpperCase()}${$D}...`})});MD.set(I,gF)}N("encoding",65,"Stage 1 complete: All codecs and profiles encoded"),N("encoding",70,"Stage 2: Creating segments and manifests...");let{manifestPath:vF,hlsManifestPath:PF}=await Iu(MD,ZD,R,E,P,a,x),Du=[];for(let z of MD.values())Du.push(...Array.from(z.values()));N("encoding",80,"Stage 2 complete: All formats packaged");let uu,Fu;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 Uu(D,ZD,k.duration,z);uu=I.spritePath,Fu=I.vttPath,N("thumbnails",90,"Thumbnails generated")}let Eu;if(W)N("thumbnails",92,"Generating poster image..."),Eu=await Gu(D,ZD,J),N("thumbnails",95,"Poster generated");return N("manifest",95,"Finalizing..."),N("complete",100,"Conversion complete!"),{manifestPath:vF,hlsManifestPath:PF,videoPaths:Du,thumbnailSpritePath:uu,thumbnailVttPath:Fu,posterPath:Eu,duration:k.duration,profiles:R,usedNvenc:h.some((z)=>z.codec.includes("nvenc")),selectedAccelerator:YD,selectedDecoder:GD,codecs:P,formats:a}}var uD={nvenc:100,qsv:90,amf:80,vaapi:70,videotoolbox:65,v4l2:60,cpu:1};function G8(D,u,F,E){let C=[],A=new Set(["nvenc","qsv","amf"]),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)=>(uD[k.accelerator]||0)-(uD[N.accelerator]||0))[0],!X&&B.length>0)C.push("Доступен аппаратный ускоритель, но он пока не поддерживается пайплайном, использую CPU");let Y=($.length>0?$:[]).sort((G,N)=>(uD[N.accelerator]||0)-(uD[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?.accelerator},J=E?Z("av1"):{encod
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(`