@shumai-one/shumai-transcode 0.4.1 → 0.4.2
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.
|
@@ -1300,7 +1300,7 @@ model RecentFileItem {
|
|
|
1300
1300
|
`,V).length:B,O?(H===null?0:H.length)+U.length:0,O?U.length+B:0);return C<j},parse:function(Z,X,z,V){let{bom:H,comment_no_infix:U,delimiter_auto:O,encoding:R,from_line:B,ltrim:C,max_record_size:j,raw:A,relax_quotes:F,rtrim:y,skip_empty_lines:b,to:m,to_line:q}=this.options,{comment:c,escape:t,quote:L0,record_delimiter:x0}=this.options,{bomSkipped:W$,delimiterDiscovered:Z$,delimiterBufPrevious:c0,rawBuffer:N0,escapeIsQuote:X$}=this.state;if(!Z$&&O){let O0;if(c0===void 0)O0=Z;else if(c0!==void 0&&Z===void 0)O0=c0;else O0=Buffer.concat([c0,Z]);if(Z=void 0,X||O0.length>O.size)this.options.delimiter=[Buffer.from(cZ(O0,this.options.delimiter_auto))],this.state.previousBuf=O0,this.state.delimiterBufPrevious=void 0,this.state.delimiterDiscovered=!0;else{this.state.delimiterBufPrevious=O0;return}}let{previousBuf:n0}=this.state,$0;if(n0===void 0)if(Z===void 0){V();return}else $0=Z;else if(n0!==void 0&&Z===void 0)$0=n0;else $0=Buffer.concat([n0,Z]);if(W$===!1)if(H===!1)this.state.bomSkipped=!0;else if($0.length<3){if(X===!1){this.state.previousBuf=$0;return}}else{for(let O0 in i$)if(i$[O0].compare($0,0,i$[O0].length)===0){let d0=i$[O0].length;this.state.bufBytesStart+=d0,$0=$0.slice(d0);let K$=o$({...this.original_options,encoding:O0});for(let q0 in K$)this.options[q0]=K$[q0];({comment:c,escape:t,quote:L0}=this.options);break}this.state.bomSkipped=!0}let y0=$0.length,i;for(i=0;i<y0;i++){if(this.__needMoreData(i,y0,X))break;if(this.state.wasRowDelimiter===!0)this.info.lines++,this.state.wasRowDelimiter=!1;if(q!==-1&&this.info.lines>q){this.state.stop=!0,V();return}if(this.state.quoting===!1&&x0.length===0){if(this.__autoDiscoverRecordDelimiter($0,i))x0=this.options.record_delimiter}let O0=$0[i];if(A===!0)N0.append(O0);if((O0===jV||O0===LV)&&this.state.wasRowDelimiter===!1)this.state.wasRowDelimiter=!0;if(this.state.escaping===!0)this.state.escaping=!1;else{if(t!==null&&this.state.quoting===!0&&this.__isEscape($0,i,O0)&&i+t.length<y0)if(X$){if(this.__isQuote($0,i+t.length)){this.state.escaping=!0,i+=t.length-1;continue}}else{this.state.escaping=!0,i+=t.length-1;continue}if(this.state.commenting===!1&&this.__isQuote($0,i))if(this.state.quoting===!0){let q0=$0[i+L0.length],s0=y&&this.__isCharTrimable($0,i+L0.length),T0=c!==null&&this.__compareBytes(c,$0,i+L0.length,q0),b0=this.__isDelimiter($0,i+L0.length,q0),Q0=x0.length===0?this.__autoDiscoverRecordDelimiter($0,i+L0.length):this.__isRecordDelimiter(q0,$0,i+L0.length);if(t!==null&&this.__isEscape($0,i,O0)&&this.__isQuote($0,i+t.length))i+=t.length-1;else if(!q0||b0||Q0||T0||s0){this.state.quoting=!1,this.state.wasQuoting=!0,i+=L0.length-1;continue}else if(F===!1){let Q$=this.__error(new M0("CSV_INVALID_CLOSING_QUOTE",["Invalid Closing Quote:",`got "${String.fromCharCode(q0)}"`,`at line ${this.info.lines}`,"instead of delimiter, record delimiter, trimable character","(if activated) or comment"],this.options,this.__infoField()));if(Q$!==void 0)return Q$}else this.state.quoting=!1,this.state.wasQuoting=!0,this.state.field.prepend(L0),i+=L0.length-1}else if(this.state.field.length!==0){if(F===!1){let q0=this.__infoField(),s0=Object.keys(i$).map((b0)=>i$[b0].equals(this.state.field.toString())?b0:!1).filter(Boolean)[0],T0=this.__error(new M0("INVALID_OPENING_QUOTE",["Invalid Opening Quote:",`a quote is found on field ${JSON.stringify(q0.column)} at line ${q0.lines}, value is ${JSON.stringify(this.state.field.toString(R))}`,s0?`(${s0} bom)`:void 0],this.options,q0,{field:this.state.field}));if(T0!==void 0)return T0}}else{this.state.quoting=!0,i+=L0.length-1;continue}if(this.state.quoting===!1){let q0=this.__isRecordDelimiter(O0,$0,i);if(q0!==0){if(this.state.commenting&&this.state.wasQuoting===!1&&this.state.record.length===0&&this.state.field.length===0)this.info.comment_lines++;else{if(this.state.enabled===!1&&this.info.lines+(this.state.wasRowDelimiter===!0?1:0)>=B){this.state.enabled=!0,this.__resetField(),this.__resetRecord(),i+=q0-1;continue}if(b===!0&&this.state.wasQuoting===!1&&this.state.record.length===0&&this.state.field.length===0){this.info.empty_lines++,i+=q0-1;continue}this.info.bytes=this.state.bufBytesStart+i;let b0=this.__onField();if(b0!==void 0)return b0;this.info.bytes=this.state.bufBytesStart+i+q0;let Q0=this.__onRecord(z);if(Q0!==void 0)return Q0;if(m!==-1&&this.info.records>=m){this.state.stop=!0,V();return}}this.state.commenting=!1,i+=q0-1;continue}if(this.state.commenting)continue;if(c!==null&&(U===!1||this.state.record.length===0&&this.state.field.length===0)){if(this.__compareBytes(c,$0,i,O0)!==0){this.state.commenting=!0;continue}}let s0=this.__isDelimiter($0,i,O0);if(s0!==0){this.info.bytes=this.state.bufBytesStart+i;let T0=this.__onField();if(T0!==void 0)return T0;i+=s0-1;continue}}}if(this.state.commenting===!1){if(j!==0&&this.state.record_length+this.state.field.length>j)return this.__error(new M0("CSV_MAX_RECORD_SIZE",["Max Record Size:","record exceed the maximum number of tolerated bytes",`of ${j}`,`at line ${this.info.lines}`],this.options,this.__infoField()))}let d0=C===!1||this.state.quoting===!0||this.state.field.length!==0||!this.__isCharTrimable($0,i),K$=y===!1||this.state.wasQuoting===!1;if(d0===!0&&K$===!0)this.state.field.append(O0);else if(y===!0&&!this.__isCharTrimable($0,i))return this.__error(new M0("CSV_NON_TRIMABLE_CHAR_AFTER_CLOSING_QUOTE",["Invalid Closing Quote:","found non trimable byte after quote",`at line ${this.info.lines}`],this.options,this.__infoField()));else{if(d0===!1)i+=this.__isCharTrimable($0,i)-1;continue}}if(X===!0){if(this.state.quoting===!0){let O0=this.__error(new M0("CSV_QUOTE_NOT_CLOSED",["Quote Not Closed:",`the parsing is finished with an opening quote at line ${this.info.lines}`],this.options,this.__infoField()));if(O0!==void 0)return O0}else if(this.state.wasQuoting===!0||this.state.record.length!==0||this.state.field.length!==0){this.info.bytes=this.state.bufBytesStart+i;let O0=this.__onField();if(O0!==void 0)return O0;let d0=this.__onRecord(z);if(d0!==void 0)return d0}else if(this.state.wasRowDelimiter===!0)this.info.empty_lines++;else if(this.state.commenting===!0)this.info.comment_lines++}else this.state.bufBytesStart+=i,this.state.previousBuf=$0.slice(i);if(this.state.wasRowDelimiter===!0)this.info.lines++,this.state.wasRowDelimiter=!1},__onRecord:function(Z){let{columns:X,group_columns_by_name:z,encoding:V,info:H,from:U,relax_column_count:O,relax_column_count_less:R,relax_column_count_more:B,raw:C,skip_records_with_empty_values:j}=this.options,{enabled:A,record:F}=this.state;if(A===!1)return this.__resetRecord();let y=F.length;if(X===!0){if(j===!0&&nZ(F)){this.__resetRecord();return}return this.__firstLineToColumns(F)}if(X===!1&&this.info.records===0)this.state.expectedRecordLength=y;if(y!==this.state.expectedRecordLength){let b=X===!1?new M0("CSV_RECORD_INCONSISTENT_FIELDS_LENGTH",["Invalid Record Length:",`expect ${this.state.expectedRecordLength},`,`got ${y} on line ${this.info.lines}`],this.options,this.__infoField(),{record:F}):new M0("CSV_RECORD_INCONSISTENT_COLUMNS",["Invalid Record Length:",`columns length is ${X.length},`,`got ${y} on line ${this.info.lines}`],this.options,this.__infoField(),{record:F});if(O===!0||R===!0&&y<this.state.expectedRecordLength||B===!0&&y>this.state.expectedRecordLength)this.info.invalid_field_length++,this.state.error=b;else{let m=this.__error(b);if(m)return m}}if(j===!0&&nZ(F)){this.__resetRecord();return}if(this.state.recordHasError===!0){this.__resetRecord(),this.state.recordHasError=!1;return}if(this.info.records++,U===1||this.info.records>=U){let{objname:b}=this.options;if(X!==!1){let m={};for(let q=0,c=F.length;q<c;q++){if(X[q]===void 0||X[q].disabled)continue;if(z===!0&&m[X[q].name]!==void 0)if(Array.isArray(m[X[q].name]))m[X[q].name]=m[X[q].name].concat(F[q]);else m[X[q].name]=[m[X[q].name],F[q]];else m[X[q].name]=F[q]}if(C===!0||H===!0){let q=Object.assign({record:m},C===!0?{raw:this.state.rawBuffer.toString(V)}:{},H===!0?{info:this.__infoRecord()}:{}),c=this.__push(b===void 0?q:[m[b],q],Z);if(c)return c}else{let q=this.__push(b===void 0?m:[m[b],m],Z);if(q)return q}}else if(C===!0||H===!0){let m=Object.assign({record:F},C===!0?{raw:this.state.rawBuffer.toString(V)}:{},H===!0?{info:this.__infoRecord()}:{}),q=this.__push(b===void 0?m:[F[b],m],Z);if(q)return q}else{let m=this.__push(b===void 0?F:[F[b],F],Z);if(m)return m}}this.__resetRecord()},__firstLineToColumns:function(Z){let{firstLineToHeaders:X}=this.state;try{let z=X===void 0?Z:X.call(null,Z);if(!Array.isArray(z))return this.__error(new M0("CSV_INVALID_COLUMN_MAPPING",["Invalid Column Mapping:","expect an array from column function,",`got ${JSON.stringify(z)}`],this.options,this.__infoField(),{headers:z}));let V=yG(z);this.state.expectedRecordLength=V.length,this.options.columns=V,this.__resetRecord();return}catch(z){return z}},__resetRecord:function(){if(this.options.raw===!0)this.state.rawBuffer.reset();this.state.error=void 0,this.state.record=[],this.state.record_length=0},__onField:function(){let{cast:Z,encoding:X,rtrim:z,max_record_size:V}=this.options,{enabled:H,wasQuoting:U}=this.state;if(H===!1)return this.__resetField();let O=this.state.field.toString(X);if(z===!0&&U===!1)O=O.trimRight();if(Z===!0){let[R,B]=this.__cast(O);if(R!==void 0)return R;O=B}if(this.state.record.push(O),V!==0&&typeof O==="string")this.state.record_length+=O.length;this.__resetField()},__resetField:function(){this.state.field.reset(),this.state.wasQuoting=!1},__push:function(Z,X){let{on_record:z}=this.options;if(z!==void 0){let V=this.__infoRecord();try{Z=z.call(null,Z,V)}catch(H){return H}if(Z===void 0||Z===null)return}this.info.bytes_records+=this.info.bytes,X(Z)},__cast:function(Z){let{columns:X,relax_column_count:z}=this.options;if(Array.isArray(X)===!0&&z&&this.options.columns.length<=this.state.record.length)return[void 0,void 0];if(this.state.castField!==null)try{let H=this.__infoField();return[void 0,this.state.castField.call(null,Z,H)]}catch(H){return[H]}if(this.__isFloat(Z))return[void 0,parseFloat(Z)];else if(this.options.cast_date!==!1){let H=this.__infoField();return[void 0,this.options.cast_date.call(null,Z,H)]}return[void 0,Z]},__compareBytes:function(Z,X,z,V){if(Z[0]!==V)return 0;let H=Z.length;for(let U=1;U<H;U++)if(Z[U]!==X[z+U])return 0;return H},__isCharTrimable:function(Z,X){let{timchars:z,timcharFirstBytes:V}=this.state,H=Z[X];if(H===void 0||V[H]===0)return 0;$:for(let U=0;U<z.length;U++){let O=z[U];for(let R=0;R<O.length;R++)if(O[R]!==Z[X+R])continue $;return O.length}return 0},__isDelimiter:function(Z,X,z){let{delimiter:V,ignore_last_delimiters:H}=this.options;if(H===!0&&this.state.record.length===this.options.columns.length-1)return 0;else if(H!==!1&&typeof H==="number"&&this.state.record.length===H-1)return 0;$:for(let U=0;U<V.length;U++){let O=V[U];if(O[0]===z){for(let R=1;R<O.length;R++)if(O[R]!==Z[X+R])continue $;return O.length}}return 0},__isEscape:function(Z,X,z){let{escape:V}=this.options;if(V===null)return!1;let H=V.length;if(V[0]===z){for(let U=0;U<H;U++)if(V[U]!==Z[X+U])return!1;return!0}return!1},__isFloat:function(Z){return Z-parseFloat(Z)+1>=0},__isQuote:function(Z,X){let{quote:z}=this.options;if(z===null)return!1;let V=z.length;for(let H=0;H<V;H++)if(z[H]!==Z[X+H])return!1;return!0},__isRecordDelimiter:function(Z,X,z){let{record_delimiter:V}=this.options,H=V.length;$:for(let U=0;U<H;U++){let O=V[U],R=O.length;if(O[0]!==Z)continue;for(let B=1;B<R;B++)if(O[B]!==X[z+B])continue $;return O.length}return 0},__autoDiscoverRecordDelimiter:function(Z,X){let{encoding:z}=this.options,V=[Buffer.from(`\r
|
|
1301
1301
|
`,z),Buffer.from(`
|
|
1302
1302
|
`,z),Buffer.from("\r",z)];$:for(let H=0;H<V.length;H++){let U=V[H].length;for(let O=0;O<U;O++)if(V[H][O]!==Z[X+O])continue $;return this.options.record_delimiter.push(V[H]),this.state.recordDelimiterMaxLength=V[H].length,V[H].length}return 0},__error:function(Z){let{encoding:X,raw:z,skip_records_with_error:V}=this.options,H=typeof Z==="string"?Error(Z):Z;if(V){if(this.state.recordHasError=!0,this.options.on_skip!==void 0)try{this.options.on_skip(H,z?this.state.rawBuffer.toString(X):void 0)}catch(U){return U}return}else return H},__infoDataSet:function(){return{...this.info,columns:this.options.columns}},__infoRecord:function(){let{columns:Z,raw:X,encoding:z}=this.options;return{...this.__infoDataSet(),bytes_records:this.info.bytes,error:this.state.error,header:Z===!0,index:this.state.record.length,raw:X?this.state.rawBuffer.toString(z):void 0}},__infoField:function(){let{columns:Z}=this.options,X=Array.isArray(Z),z=this.info.bytes_records;return{...this.__infoRecord(),bytes_records:z,column:X===!0?Z.length>this.state.record.length?Z[this.state.record.length].name:null:this.state.record.length,quoting:this.state.wasQuoting}}}};var dZ=function($,G={}){if(typeof $==="string")$=Buffer.from($);let J=G&&G.objname?Object.create(null):[],Z=bG(G),X=(H)=>{if(Z.options.objname===void 0)J.push(H);else J[H[0]]=H[1]},z=()=>{},V=Z.parse($,!0,X,z);if(V!==void 0)throw V;return J};import*as A0 from"fs";import*as rZ from"os";import*as I0 from"path";import pZ from"pdfkit";import R$ from"sharp";import{promisify as PV}from"util";var IJ={apch:"Apple ProRes 422 High Quality",apcn:"Apple ProRes 422 Standard Definition",apcs:"Apple ProRes 422 LT",apco:"Apple ProRes 422 Proxy",ap4h:"Apple ProRes 4444",jpeg:"JPEG Image","3gvo":"3GPP Video Orientation",a3d1:"Multiview Video Coding",a3d2:"Multiview Video Coding",a3d3:"Multiview Video Coding",a3d4:"Multiview Video Coding",a3ds:"Auro-Cx 3D audio","ac-3":"AC-3 audio","ac-4":"AC-4 audio",alac:"Apple lossless audio codec",alaw:"a-Law",av01:"AV1 video",avc1:"Advanced Video Coding",avc2:"Advanced Video Coding",avc3:"Advanced Video Coding",avc4:"Advanced Video Coding",avcp:"Advanced Video Coding Parameters",dra1:"DRA Audio",drac:"Dirac Video Coder","dts-":"Dependent base layer for DTS layered audio","dts+":"Enhancement layer for DTS layered audio",dtsc:"DTS Coherent Acoustics audio",dtse:"DTS Express low bit rate audio, also known as DTS LBR",dtsh:"DTS-HD High Resolution Audio",dtsl:"DTS-HD Master Audio",dtsx:"DTS:X",dvav:"AVC-based \u201CDolby Vision\u201D",dvhe:"HEVC-based \u201CDolby Vision\u201D","ec-3":"Enhanced AC-3 audio",enca:"Encrypted/Protected audio",encf:"Encrypted/Protected font",encm:"Encrypted/Protected metadata stream",encs:"Encrypted Systems stream",enct:"Encrypted Text",encv:"Encrypted/protected video",fdp:"File delivery hints",fLaC:"Fres Lossless Audio Codec",g719:"ITU-T Recommendation G.719 (2008)",g726:"ITU-T Recommendation G.726 (1990)",hev1:"High Efficiency Video Coding",hvc1:"High Efficiency Video Coding",hvt1:"High Efficiency Video Coding",ixse:"DVB Track Level Index Track",lhe1:"Layered High Efficiency Video Coding",lht1:"Layered High Efficiency Video Coding",lhv1:"Layered High Efficiency Video Coding",m2ts:"MPEG-2 transport stream for DMB",m4ae:"MPEG-4 Audio Enhancement MP4v1/2",mett:"Text timed metadata that is not XML",metx:"XML timed metadata",mha1:"MPEG-H Audio (single stream, uncapsulated)",mha2:"MPEG-H Audio (multi-stream, unencapsulated)",mhm1:"MPEG-H Audio (single stream, MHAS encapsulated)",mhm2:"MPEG-H Audio (multi-stream, MHAS encapsulated)",mjp2:"Motion JPEG 2000",mlix:"DVB Movie level index track",mlpa:"MLP Audio",mp4a:"MPEG-4 Audio",mp4s:"MPEG-4 Systems",mp4v:"MPEG-4 Visual",mvc1:"Multiview coding",mvc2:"Multiview coding",mvc3:"Multiview coding",mvc4:"Multiview coding",mvd1:"Multiview coding",mvd2:"Multiview coding",mvd3:"Multiview coding",mvd4:"Multiview coding",oksd:"OMA Keys",Opus:"Opus audio coding",pm2t:"Protected MPEG-2 Transport",prtp:"Protected RTP Reception",raw:"Uncompressed audio",resv:"Restricted Video",rm2t:"MPEG-2 Transport Reception",rrtp:"RTP reception",rsrp:"SRTP Reception",rtmd:"Real Time Metadata Sample Entry(XAVC Format)",rtp:"RTP Hints",s263:"ITU H.263 video (3GPP format)",samr:"Narrowband AMR voice",sawb:"Wideband AMR voice",sawp:"Extended AMR-WB (AMR-WB+)",sevc:"EVRC Voice",sm2t:"MPEG-2 Transport Server",sqcp:"13K Voice",srtp:"SRTP Hints",ssmv:"SMV Voice",STGS:"Subtitle Sample Entry (HMMP)",stpp:"Subtitles (Timed Text)",svc1:"Scalable Video Coding",svc2:"Scalable Video Coding",svcM:"SVC Metadata",tc64:"64 bit timecode samples",tmcd:"32 bit timecode samples",twos:"Uncompressed 16-bit audio",tx3g:"Timed Text stream",ulaw:"Samples have been compressed using uLaw 2:1.",unid:"Dynamic Range Control (DRC) data",urim:"Binary timed metadata identified by URI","vc-1":"SMPTE VC-1",vp08:"VP8 video",vp09:"VP9 video",wvtt:"WebVTT"};var r0=PV(CV);function oZ(){let $=[...process.env.PDF_CJK_FONT_PATH?[{fontPath:process.env.PDF_CJK_FONT_PATH,fontName:process.env.PDF_CJK_FONT_NAME}]:[],{fontPath:"/System/Library/Fonts/Supplemental/Arial Unicode.ttf"},{fontPath:"/Library/Fonts/Arial Unicode.ttf"},{fontPath:"/System/Library/Fonts/PingFang.ttc",fontName:"PingFangSC-Regular"},{fontPath:"/System/Library/Fonts/STHeiti Light.ttc",fontName:"STHeitiSC-Light"},{fontPath:"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",fontName:"NotoSansCJKsc-Regular"},{fontPath:"/usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc",fontName:"NotoSansCJKsc-Regular"},{fontPath:"/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",fontName:"WenQuanYiZenHei"},{fontPath:"/usr/share/fonts/truetype/arphic/ukai.ttc",fontName:"AR-PL-UKai-CN"},{fontPath:"/usr/share/fonts/noto/NotoSansCJK-Regular.ttc",fontName:"Noto Sans CJK SC"},{fontPath:"/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf"},{fontPath:"/usr/share/fonts/truetype/droid/DroidSansFallback.ttf"},{fontPath:"/usr/share/fonts/google-droid/DroidSansFallback.ttf"},{fontPath:"C:\\Windows\\Fonts\\msyh.ttc",fontName:"MicrosoftYaHei"},{fontPath:"C:\\Windows\\Fonts\\simsun.ttc",fontName:"SimSun"},{fontPath:"C:\\Windows\\Fonts\\simhei.ttf"}];for(let G of $)if(A0.existsSync(G.fontPath))return G;return}function vJ($){try{return dZ($,{skip_empty_lines:!0,relax_column_count:!0,relax_quotes:!0,trim:!0,delimiter_auto:!0})}catch{return $.split(/\r?\n/).filter((G)=>G.trim().length>0).map((G)=>G.split(",").map((J)=>J.trim()))}}var kG={h264_nvenc:{name:"h264_nvenc",presetArgs:["-preset","p4","-rc:v","vbr","-cq:v","26","-b:v","0"]},h264_qsv:{name:"h264_qsv",presetArgs:["-preset","fast","-global_quality","26"]},h264_amf:{name:"h264_amf",presetArgs:["-quality","balanced","-rc","qvbr","-qvbr_quality_level","26"]},h264_videotoolbox:{name:"h264_videotoolbox",presetArgs:["-q:v","74"]},libx264:{name:"libx264",presetArgs:["-preset","fast","-crf","26"]}};function EV($=process.platform){switch($){case"darwin":return["h264_videotoolbox","h264_nvenc","h264_qsv","h264_amf"];case"win32":return["h264_nvenc","h264_qsv","h264_amf"];case"linux":default:return["h264_nvenc","h264_qsv","h264_amf"]}}function AV($,G){let J=Math.max(G||0,$),Z=Math.min(G||$,$),X=Z>0?Z:$;if(X>=2160||J>=3840)return 12000000;if(X>=1080||J>=1920)return 4500000;if(X>=720||J>=1280)return 2500000;if(X>=540||J>=960)return 1200000;if(X>=360||J>=640)return 800000;return 1e5}function FV($,G,J,Z){let X=AV($,G);if(Z){let O;if(typeof Z==="number")O=Z;else{let R=Z.split("/");if(R.length===2)O=parseFloat(R[0])/parseFloat(R[1]);else O=parseFloat(Z)}if(Number.isFinite(O)&&O>0&&O<24){let R=Math.max(0.1,O/24);X=Math.max(50000,Math.round(X*R))}}let z=J&&J>0?Math.min(X,Math.round(J*1.2)):X;z=Math.max(Z?50000:1e5,z);let H=Math.max(50,Math.round(z/1000)),U=H*2;return{maxrate:`${H}k`,bufsize:`${U}k`}}function iZ($){if(typeof $==="string"){if($.toLowerCase().endsWith(".psd"))return!0;if(A0.existsSync($))try{let G=A0.openSync($,"r"),J=Buffer.alloc(4);return A0.readSync(G,J,0,4,0),A0.closeSync(G),J.toString("ascii")==="8BPS"}catch{return!1}return!1}return $.length>=4&&$[0]===56&&$[1]===66&&$[2]===80&&$[3]===83}function qV($,G,J=300,Z=533){if($<=0||G<=0)return{width:J,height:J};let X=Math.min($,G),z=Math.max($,G);if(X<=J&&z<=Z)return{width:$,height:G};let V=J/X;if(Math.round(z*V)>Z)V=Z/z;let U=Math.max(1,Math.round($*V)),O=Math.max(1,Math.round(G*V));return{width:U,height:O}}class sZ{prismaClient;constructor($=v){this.prismaClient=$}async execImageMagick($){try{return await r0("magick",$)}catch(G){if(G?.code==="ENOENT")return await r0("convert",$);throw G}}async execImageMagickIdentify($){let G=`${$}[0]`,J;try{J=(await r0("magick",["identify","-format","%w %h",G])).stdout}catch(V){if(V?.code==="ENOENT")J=(await r0("identify",["-format","%w %h",G])).stdout;else throw V}let Z=J.trim().split(/\s+/),X=parseInt(Z[0],10)||0,z=parseInt(Z[1],10)||0;return{width:X,height:z}}resolveCodecName($){let G=$.mime_codec_string||$.tags?.mime_codec_string;if(G&&typeof G==="string"){let J=G.split(".")[0];if(IJ[J])return IJ[J]}return $.codec_name}safeParseInt($){if($===void 0||$===null)return;let G=typeof $==="string"?parseInt($,10):$;return Number.isFinite(G)?G:void 0}async getVideoInfo($){let{stdout:G}=await r0("ffprobe",["-v","quiet","-print_format","json","-show_format","-show_streams",$]),J=JSON.parse(G),Z=J.streams.find((R)=>R.codec_type==="video"),X=J.streams.find((R)=>R.codec_type==="audio");if(!Z)throw Error("No video stream found");let z=0;if(Z.avg_frame_rate){let R=Z.avg_frame_rate.split("/");if(R.length===2){let B=parseFloat(R[0]),C=parseFloat(R[1]);if(C>0)z=B/C}}if(z===0&&Z.r_frame_rate){let R=Z.r_frame_rate.split("/");if(R.length===2){let B=parseFloat(R[0]),C=parseFloat(R[1]);if(C>0)z=B/C}}let V=parseFloat(J.format.duration),H=0;if(Z.nb_frames)H=parseInt(Z.nb_frames,10);if(!H&&z>0&&!isNaN(V))H=Math.round(V*z);let U=Z.tags?.timecode||J.format?.tags?.timecode,O;if(Z.bit_rate&&parseInt(Z.bit_rate,10)>0)O=parseInt(Z.bit_rate,10);else{let R=Z.tags?.BPS||Z.tags?.["BPS-eng"];if(R&&parseInt(R,10)>0)O=parseInt(R,10);else{let B=Z.tags?.NUMBER_OF_BYTES||Z.tags?.["NUMBER_OF_BYTES-eng"];if(B&&V>0)O=Math.round(parseInt(B,10)*8/V);else{let C=parseFloat(J.format.bit_rate);if(Number.isFinite(C)&&C>0){let j=X?.bit_rate?parseFloat(X.bit_rate):X?128000:0;O=Math.max(1e5,Math.round(C-j))}}}}return{originalWidth:Z.width,originalHeight:Z.height,duration:V,bitRate:parseFloat(J.format.bit_rate),videoBitRate:O,frameRate:z||30,totalFrames:H||0,startTimecode:U,hasAudio:!!X,videoCodec:this.resolveCodecName(Z),audioCodec:X?this.resolveCodecName(X):void 0,audioChannels:X?.channels,audioSampleRate:this.safeParseInt(X?.sample_rate),audioBitDepth:this.safeParseInt(X?.bits_per_raw_sample)??this.safeParseInt(X?.bits_per_sample),mimeType:""}}async getImageInfo($){let G=$,J=null;if($.startsWith("http")){let X=await fetch($);if(!X.ok)throw Error(`Failed to fetch image from ${$}: ${X.statusText}`);G=Buffer.from(await X.arrayBuffer())}if(iZ(G)){let X;if(typeof G==="string")X=G;else J=this.createTempDir("psd-info-"),X=I0.join(J,"input.psd"),A0.writeFileSync(X,G);try{let{width:z,height:V}=await this.execImageMagickIdentify(X);return{originalWidth:z,originalHeight:V,duration:0,bitRate:0,frameRate:0,totalFrames:0,startTimecode:void 0,hasAudio:!1,mimeType:"psd"}}catch(z){console.warn("ImageMagick identify failed for PSD, falling back to sharp:",z)}finally{if(J)this.removeDir(J)}}let Z=await R$(G,{limitInputPixels:!1}).metadata();return{originalWidth:Z.width||0,originalHeight:Z.height||0,duration:0,bitRate:0,frameRate:0,totalFrames:0,startTimecode:void 0,hasAudio:!1,mimeType:Z.format||""}}availableEncodersCache=null;clearEncodersCache(){this.availableEncodersCache=null}async getAvailableEncoders(){if(this.availableEncodersCache)return this.availableEncodersCache;try{let{stdout:$}=await r0("ffmpeg",["-encoders"]),G=new Set,J=$.split(`
|
|
1303
|
-
`);for(let Z of J){let X=Z.match(/^\s*[A-Z.]{6}\s+([a-zA-Z0-9_-]+)/);if(X)G.add(X[1])}return this.availableEncodersCache=G,G}catch($){return console.warn("Failed to probe ffmpeg encoders:",$),new Set}}async selectH264Encoder($,G=process.platform){if($!=="auto")return kG.libx264;let J=await this.getAvailableEncoders(),Z=EV(G);for(let X of Z)if(J.has(X)&&kG[X])return kG[X];return kG.libx264}async transcodeVideo($){let G,J=["-i",$.inputFile];if($.overlayFile)J.push("-i",$.overlayFile),G=`[0:v]scale=${$.width}:${$.height}[vscaled];[vscaled][1:v]overlay=0:0`;else G=`[0:v]scale=w=${$.width}:h=${$.height}:force_original_aspect_ratio=decrease,scale=w='trunc(iw/2)*2':h='trunc(ih/2)*2'`;if($.frameRate)G+=`,fps=${$.frameRate}`;if(G+="[vout]",J.push("-filter_complex",G,"-map","[vout]"),$.frameRate){let X;if(typeof $.frameRate==="number")X=$.frameRate;else{let z=$.frameRate.split("/");if(z.length===2)X=parseFloat(z[0])/parseFloat(z[1]);else X=parseFloat($.frameRate)}if(Number.isFinite(X)&&X>0){let z=Math.max(1,Math.round(X));J.push("-r",X.toString(),"-g",z.toString(),"-force_key_frames","expr:gte(t,n_forced*1)")}}if(!$.disableAudio)J.push("-map","0:a?");let Z=await this.selectH264Encoder($.hardwareAcceleration);if(J.push("-c:v",Z.name),Z.presetArgs.length>0)J.push(...Z.presetArgs);if($.videoBitrate)J.push("-b:v",$.videoBitrate);else{let{maxrate:X,bufsize:z}=FV($.height,$.width,$.sourceVideoBitrate,$.frameRate);J.push("-maxrate",X,"-bufsize",z)}if(J.push("-pix_fmt","yuv420p"),!$.disableAudio)J.push("-c:a","aac","-b:a","128k");J.push("-movflags","+faststart","-max_muxing_queue_size","1024",$.outputFile),await r0("ffmpeg",["-y","-loglevel","warning",...J])}async transcodeImage($,G,J,Z,X=null){let z=typeof X==="object"&&X!==null?X.height??null:X,V=typeof X==="object"&&X!==null?X.isPreview??!1:!1;if(J===480||z===0)V=!0;let H=$;if(typeof $==="string"&&$.startsWith("http")){let C=await fetch($);if(!C.ok)throw Error(`Failed to fetch image from ${$}: ${C.statusText}`);H=Buffer.from(await C.arrayBuffer())}let U=7680,O=J>0?Math.min(J,U):U,R=z&&z>0?Math.min(z,U):U,B=R$(H,{limitInputPixels:!1});if(V)try{let C=await B.metadata();if(C.width&&C.height){let j=J===480?300:J,A=Math.round(j*16/9),F=qV(C.width,C.height,j,A);O=F.width,R=F.height}}catch{}if(O=Math.min(O,U),R=Math.min(R,U),iZ(H)){let C,j=null;if(typeof H==="string")C=H;else j=this.createTempDir("psd-transcode-"),C=I0.join(j,"input.psd"),A0.writeFileSync(C,H);try{let A=R<U?`${O}x${R}>`:`${O}x${U}>`;await this.execImageMagick([`${C}[0]`,"-colorspace","sRGB","-resize",A,"-quality",Z.toString(),G]);return}finally{if(j)this.removeDir(j)}}B.toColorspace("srgb").resize(O,R,{withoutEnlargement:!0,fit:"inside"}),await B.webp({quality:Z}).toFile(G)}async generateSprite($,G,J,Z){let z=`[0:v]fps=${100/Z},scale=w=300:h=-2,tile=10x10[sprite_out];[0:v]scale=-2:300:force_original_aspect_ratio=decrease,select='eq(n\\,0)'[thumb_out]`;await r0("ffmpeg",["-y","-loglevel","warning",...["-i",$,"-filter_complex",z,"-map","[sprite_out]","-frames:v","1","-c:v","libwebp","-q:v","75",G,"-map","[thumb_out]","-c:v","libwebp","-q:v","75","-frames:v","1","-max_muxing_queue_size","1024",J]])}async generatePdfSprite($,G,J){let Z=this.createTempDir("pdf-sprite-");try{let X=I0.join(Z,"page");try{await r0("pdftoppm",["-png","-f","1","-l","100",$,X])}catch(j){let A=j?.code,F=j instanceof Error?j.message:String(j),y=F.toLowerCase();if(A==="ENOENT"||y.includes("enoent")||y.includes("not found")&&y.includes("pdftoppm"))throw Error(`pdftoppm executable not found in $PATH. Please install poppler-utils / poppler. (${F})`,{cause:j});throw j}let z=A0.readdirSync(Z).filter((j)=>j.endsWith(".png"));if(z.length===0)throw Error("pdftoppm produced no image outputs");z.sort((j,A)=>{let F=parseInt(j.replace(/[^0-9]/g,""),10),y=parseInt(A.replace(/[^0-9]/g,""),10);return F-y});let V=z.length,H=I0.join(Z,z[0]),U=await R$(H,{limitInputPixels:!1}).metadata(),O=U.width||800,R=U.height||1000;for(let j=1;j<=100;j++){let A=Math.min(V-1,Math.floor((j-1)*V/100)),F=I0.join(Z,z[A]),y=I0.join(Z,`frame_${j}.png`);if(F!==y)A0.copyFileSync(F,y)}let B=["-i",I0.join(Z,"frame_%d.png"),"-filter_complex","scale=w=300:h=-2,tile=10x10","-frames:v","1","-c:v","libwebp","-q:v","75",G];await r0("ffmpeg",["-y","-loglevel","warning",...B]),await R$(H,{limitInputPixels:!1}).toColorspace("srgb").resize(300,533,{withoutEnlargement:!0,fit:"inside"}).webp({quality:75}).toFile(J);let C=V;try{let{stdout:j}=await r0("pdfinfo",[$]),A=j.match(/Pages:\s+(\d+)/);if(A)C=parseInt(A[1],10)}catch{}return{pageCount:C,originalWidth:O,originalHeight:R}}finally{this.removeDir(Z)}}async getPdfInfo($){let G=this.createTempDir("pdf-info-"),J=800,Z=1000,X=1;try{let z=I0.join(G,"page");await r0("pdftoppm",["-png","-f","1","-l","1",$,z]);let V=A0.readdirSync(G).filter((H)=>H.endsWith(".png"));if(V.length>0){let H=await R$(I0.join(G,V[0]),{limitInputPixels:!1}).metadata();J=H.width||800,Z=H.height||1000}}catch(z){console.warn("pdftoppm not available for PDF dimensions extraction:",z)}try{let{stdout:z}=await r0("pdfinfo",[$]),V=z.match(/Pages:\s+(\d+)/);if(V)X=parseInt(V[1],10)}catch{}finally{this.removeDir(G)}return{originalWidth:J,originalHeight:Z,duration:0,bitRate:0,frameRate:0,totalFrames:X,hasAudio:!1,mimeType:"application/pdf"}}async generatePdfFromText($,G){let J=A0.readFileSync($,"utf-8"),X=/[\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\u4e00-\u9fff\uac00-\ud7af]/.test(J)?oZ():void 0;return new Promise((z,V)=>{let H=new pZ({size:"A4",margin:40,bufferPages:!0}),U=A0.createWriteStream(G);if(H.pipe(U),X)if(X.fontName!==void 0)H.font(X.fontPath,X.fontName);else H.font(X.fontPath);else H.font("Helvetica");H.fontSize(10),H.text(J,{lineGap:3,paragraphGap:4}),H.end(),U.on("finish",()=>z()),U.on("error",(O)=>V(O))})}async generatePdfFromCsv($,G){let J=A0.readFileSync($,"utf-8"),Z=vJ(J),z=/[\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\u4e00-\u9fff\uac00-\ud7af]/.test(J)?oZ():void 0;if(Z.length===0)Z.push(["(Empty CSV)"]);let V=Math.max(...Z.map((U)=>U.length)),H=V>5;return new Promise((U,O)=>{let R=new pZ({size:"A4",layout:H?"landscape":"portrait",margin:30,bufferPages:!0}),B=A0.createWriteStream(G);R.pipe(B);let C=()=>{if(z)if(z.fontName!==void 0)R.font(z.fontPath,z.fontName);else R.font(z.fontPath);else R.font("Helvetica");R.fontSize(9)};C();let j=R.page.width-R.page.margins.left-R.page.margins.right,A=Math.max(40,j/V),F=R.page.margins.left,y=R.page.margins.top,b=20,m=(c,t,L0)=>{if(t)R.rect(F,L0,A*V,b).fill("#e0e0e0"),R.fillColor("#000000");for(let x0=0;x0<V;x0++){let W$=c[x0]||"",Z$=F+x0*A;R.rect(Z$,L0,A,b).stroke("#cccccc"),R.fillColor("#000000").text(W$,Z$+4,L0+5,{width:A-8,height:b-6,ellipsis:!0})}},q=Z[0];m(q,!0,y),y+=b;for(let c=1;c<Z.length;c++){if(y+b>R.page.height-R.page.margins.bottom)R.addPage(),C(),y=R.page.margins.top,m(q,!0,y),y+=b;m(Z[c],!1,y),y+=b}R.end(),B.on("finish",()=>U()),B.on("error",(c)=>O(c))})}async extractAudio($,G,J){await r0("ffmpeg",["-y","-loglevel","warning",...["-i",$,"-vn","-acodec","libmp3lame","-b:a",J,G]])}async getAudioInfo($){let{stdout:G}=await r0("ffprobe",["-v","quiet","-print_format","json","-show_format","-show_streams",$]),J=JSON.parse(G),Z=J.streams.find((z)=>z.codec_type==="audio");if(!Z)throw Error("No audio stream found");let X=parseFloat(J.format.duration);return{originalWidth:0,originalHeight:0,duration:isNaN(X)?0:X,bitRate:parseFloat(J.format.bit_rate)||0,frameRate:0,totalFrames:0,startTimecode:void 0,hasAudio:!0,videoCodec:void 0,audioCodec:this.resolveCodecName(Z),audioChannels:Z?.channels,audioSampleRate:this.safeParseInt(Z?.sample_rate),audioBitDepth:this.safeParseInt(Z?.bits_per_raw_sample)??this.safeParseInt(Z?.bits_per_sample),mimeType:""}}async transcodeAudio($){let G=$.bitrate||"128k",J=["-i",$.inputFile,"-vn","-c:a","aac","-b:a",G,"-ac","2",$.outputFile];await r0("ffmpeg",["-y","-loglevel","warning",...J])}async extractVideoFrames($){if($.isImage){let V=I0.join($.outputDir,"1.webp");return await this.transcodeImage($.inputFile,V,-1,80,$.frameHeight),[V]}let G=await this.getVideoInfo($.inputFile),J=$.numFrames/G.duration,Z=I0.join($.outputDir,"%d.webp"),X=["-i",$.inputFile,"-vf",`fps=${J},scale=-2:${$.frameHeight}`,"-c:v","libwebp","-q:v","80",Z];return await r0("ffmpeg",["-y","-loglevel","warning",...X]),A0.readdirSync($.outputDir).filter((V)=>V.endsWith(".webp")).sort((V,H)=>{let U=parseInt(I0.basename(V,".webp")),O=parseInt(I0.basename(H,".webp"));return U-O}).map((V)=>I0.join($.outputDir,V))}createTempDir($){return A0.mkdtempSync(I0.join(rZ.tmpdir(),$))}removeDir($){A0.rmSync($,{recursive:!0,force:!0})}async createVideoTranscodeTask($,G,J){return this.prismaClient.workflowTask.create({data:{assetId:$,projectId:G,type:B0.transcode_video,status:w0.pending,payload:{projectId:G,transcode:J}}})}async createImageTranscodeTask($,G,J){return this.prismaClient.workflowTask.create({data:{assetId:$,projectId:G,type:B0.transcode_image,status:w0.pending,payload:{projectId:G,transcode:J}}})}async takeScreenshots($){let G=process.env.S3_BUCKET||"shumai",J=this.createTempDir("screenshot-"),Z=I0.join(J,I0.basename($.assetKey));try{await a.downloadToFile(G,$.assetKey,Z);let X=[];if($.count<=1)X=[$.start];else{let U=($.end-$.start)/$.count;X=Array.from({length:$.count},(O,R)=>$.start+R*U)}let z=$.commentTimestamp,V=0.1;if(z!==void 0&&z!==null){if(z>=$.start-V&&z<=$.end+V){let O=0,R=Math.abs(X[0]-z);for(let B=1;B<X.length;B++){let C=Math.abs(X[B]-z);if(C<R)R=C,O=B}X[O]=z}}let H=[];for(let U of X){let O=`shot-${U.toFixed(3)}-${i0()}.webp`,R=I0.join(J,O),B=["-ss",U.toFixed(3),"-i",Z,"-vframes","1","-vf","scale=-2:720","-c:v","libwebp","-q:v","80",R];if(await r0("ffmpeg",["-y","-loglevel","warning",...B]),z!==void 0&&z!==null&&Math.abs(U-z)<0.0001&&$.annotations&&$.annotations.length>0){let F=A0.readFileSync(R),y=await this.overlayAnnotationsOnBuffer(F,$.annotations);A0.writeFileSync(R,y)}let j=`files/${$.assetId}/screenshots/${O}`,A=A0.readFileSync(R);await a.putObject(G,j,A,A.length,"image/webp"),H.push({key:j,timestamp:U})}return H}finally{this.removeDir(J)}}async renderPdfPages($){let G=process.env.S3_BUCKET||"shumai",J=this.createTempDir("pdf-pages-"),Z=I0.join(J,I0.basename($.assetKey));try{await a.downloadToFile(G,$.assetKey,Z);let X=I0.join(J,"page");try{await r0("pdftoppm",["-png","-f",$.start.toString(),"-l",$.end.toString(),Z,X])}catch(U){let O=U?.code,R=U instanceof Error?U.message:String(U),B=R.toLowerCase();if(O==="ENOENT"||B.includes("enoent")||B.includes("not found")&&B.includes("pdftoppm"))throw Error(`pdftoppm executable not found in $PATH. Please install poppler-utils / poppler. (${R})`,{cause:U});throw U}let z=A0.readdirSync(J).filter((U)=>U.endsWith(".png"));if(z.length===0)throw Error("pdftoppm produced no image outputs");z.sort((U,O)=>{let R=parseInt(U.replace(/[^0-9]/g,""),10),B=parseInt(O.replace(/[^0-9]/g,""),10);return R-B});let V=[],H=T$($.assetKey);for(let U=0;U<z.length;U++){let O=$.start+U,R=I0.join(J,z[U]),B=`${H}-page-${O}-${i0()}.webp`,C=await R$(R,{limitInputPixels:!1}).toColorspace("srgb").resize(1920,1080,{fit:"inside",withoutEnlargement:!1}).webp({quality:85}).toBuffer(),j=$.commentTimestamp!==void 0&&$.commentTimestamp!==null?Math.round($.commentTimestamp):null;if(j!==null&&O===j&&$.annotations&&$.annotations.length>0)C=await this.overlayAnnotationsOnBuffer(C,$.annotations);let A=`files/${$.assetId}/pdf_pages/${B}`;await a.putObject(G,A,C,C.length,"image/webp"),V.push({key:A,page:O})}return V}finally{this.removeDir(J)}}async overlayAnnotationsOnBuffer($,G){if(!G||G.length===0)return $;let J=await R$($,{limitInputPixels:!1}).metadata(),Z=J.width||1920,X=J.height||1080,z=SV(Z,X,G);return await R$($,{limitInputPixels:!1}).composite([{input:Buffer.from(z),top:0,left:0}]).toColorspace("srgb").resize(16383,16383,{fit:"inside",withoutEnlargement:!0}).webp({quality:85}).toBuffer()}async overlayAnnotations($){let G=process.env.S3_BUCKET||"shumai",J=`annotation-${i0()}.webp`,Z=this.createTempDir("annotation-"),X=I0.join(Z,I0.basename($.assetKey));try{await a.downloadToFile(G,$.assetKey,X);let z=A0.readFileSync(X),V=await this.overlayAnnotationsOnBuffer(z,$.annotations),H=`files/${$.assetId}/annotations/${J}`;return await a.putObject(G,H,V,V.length,"image/webp"),H}finally{this.removeDir(Z)}}async renderSvgToPng($){return R$(Buffer.from($)).png().toBuffer()}async downscaleImageToPng($,G){let J=await R$($,{limitInputPixels:!1}).resize(G,G,{fit:"inside",withoutEnlargement:!0}).png().toBuffer(),Z=await R$(J).metadata();return{buffer:J,width:Z.width||100,height:Z.height||100}}async compositeOverlayToWebpFile($,G,J,Z,X){await R$($,{limitInputPixels:!1}).toColorspace("srgb").resize(Z,X,{fit:"inside"}).composite([{input:G}]).webp({quality:90}).toFile(J)}}function SV($,G,J){let Z=Math.max(2,Math.round(Math.max($,G)*0.004)),X=[];for(let z of J){let V=z.color||"#ff0000";switch(z.type){case"box":{if(z.points.length<2)continue;let[U,O]=z.points,R=Math.min(U[0],O[0])*$,B=Math.min(U[1],O[1])*G,C=Math.abs(O[0]-U[0])*$,j=Math.abs(O[1]-U[1])*G;X.push(`<rect x="${R}" y="${B}" width="${C}" height="${j}" stroke="${V}" stroke-width="${Z}" fill="none" />`);break}case"line":case"freehand":{if(z.points.length<2)continue;let U=z.points.map(([O,R])=>`${O*$},${R*G}`).join(" ");X.push(`<polyline points="${U}" stroke="${V}" stroke-width="${Z}" stroke-linecap="round" stroke-linejoin="round" fill="none" />`);break}case"arrow":{if(z.points.length<2)continue;let U=z.points.map(([c,t])=>[c*$,t*G]),O=U.map(([c,t])=>`${c},${t}`).join(" ");X.push(`<polyline points="${O}" stroke="${V}" stroke-width="${Z}" stroke-linecap="round" stroke-linejoin="round" fill="none" />`);let R=U[U.length-1],B=U[U.length-2],C=R[0]-B[0],j=R[1]-B[1],A=Math.atan2(j,C),F=Math.max(12,Math.max($,G)*0.015),y=R[0]-F*Math.cos(A-Math.PI/6),b=R[1]-F*Math.sin(A-Math.PI/6),m=R[0]-F*Math.cos(A+Math.PI/6),q=R[1]-F*Math.sin(A+Math.PI/6);X.push(`<polygon points="${R[0]},${R[1]} ${y},${b} ${m},${q}" fill="${V}" />`);break}}}return`<svg width="${$}" height="${G}" viewBox="0 0 ${$} ${G}" xmlns="http://www.w3.org/2000/svg">${X.join(`
|
|
1303
|
+
`);for(let Z of J){let X=Z.match(/^\s*[A-Z.]{6}\s+([a-zA-Z0-9_-]+)/);if(X)G.add(X[1])}return this.availableEncodersCache=G,G}catch($){return console.warn("Failed to probe ffmpeg encoders:",$),new Set}}async selectH264Encoder($,G=process.platform){if($!=="auto")return kG.libx264;let J=await this.getAvailableEncoders(),Z=EV(G);for(let X of Z)if(J.has(X)&&kG[X])return kG[X];return kG.libx264}async transcodeVideo($){let G,J=["-i",$.inputFile];if($.overlayFile)J.push("-i",$.overlayFile),G=`[0:v]scale=${$.width}:${$.height}[vscaled];[vscaled][1:v]overlay=0:0`;else G=`[0:v]scale=w=${$.width}:h=${$.height}:force_original_aspect_ratio=decrease,scale=w='trunc(iw/2)*2':h='trunc(ih/2)*2'`;if($.frameRate)G+=`,fps=${$.frameRate}`;if(G+="[vout]",J.push("-filter_complex",G,"-map","[vout]"),$.frameRate){let X;if(typeof $.frameRate==="number")X=$.frameRate;else{let z=$.frameRate.split("/");if(z.length===2)X=parseFloat(z[0])/parseFloat(z[1]);else X=parseFloat($.frameRate)}if(Number.isFinite(X)&&X>0){let z=Math.max(1,Math.round(X));J.push("-r",X.toString(),"-g",z.toString(),"-force_key_frames","expr:gte(t,n_forced*1)")}}if(!$.disableAudio)J.push("-map","0:a?");let Z=await this.selectH264Encoder($.hardwareAcceleration);if(J.push("-c:v",Z.name),Z.presetArgs.length>0)J.push(...Z.presetArgs);if($.videoBitrate)J.push("-b:v",$.videoBitrate);else{let{maxrate:X,bufsize:z}=FV($.height,$.width,$.sourceVideoBitrate,$.frameRate);J.push("-maxrate",X,"-bufsize",z)}if(J.push("-pix_fmt","yuv420p"),!$.disableAudio)J.push("-c:a","aac","-b:a","128k");J.push("-movflags","+faststart","-max_muxing_queue_size","1024",$.outputFile),await r0("ffmpeg",["-y","-loglevel","warning",...J])}async transcodeImage($,G,J,Z,X=null){let z=typeof X==="object"&&X!==null?X.height??null:X,V=typeof X==="object"&&X!==null?X.isPreview??!1:!1;if(J===480||z===0)V=!0;let H=$;if(typeof $==="string"&&$.startsWith("http")){let C=await fetch($);if(!C.ok)throw Error(`Failed to fetch image from ${$}: ${C.statusText}`);H=Buffer.from(await C.arrayBuffer())}let U=7680,O=J>0?Math.min(J,U):U,R=z&&z>0?Math.min(z,U):U,B=R$(H,{limitInputPixels:!1});if(V)try{let C=await B.metadata();if(C.width&&C.height){let j=J===480?300:J,A=Math.round(j*16/9),F=qV(C.width,C.height,j,A);O=F.width,R=F.height}}catch{}if(O=Math.min(O,U),R=Math.min(R,U),iZ(H)){let C,j=null;if(typeof H==="string")C=H;else j=this.createTempDir("psd-transcode-"),C=I0.join(j,"input.psd"),A0.writeFileSync(C,H);try{let A=R<U?`${O}x${R}>`:`${O}x${U}>`;await this.execImageMagick([`${C}[0]`,"-colorspace","sRGB","-resize",A,"-quality",Z.toString(),G]);return}finally{if(j)this.removeDir(j)}}B.toColorspace("srgb").resize(O,R,{withoutEnlargement:!0,fit:"inside"}),await B.webp({quality:Z}).toFile(G)}async generateSprite($,G,J,Z){let z=`[0:v]fps=${100/Z},scale=w=300:h=-2,tile=10x10[sprite_out];[0:v]scale=-2:300:force_original_aspect_ratio=decrease,select='eq(n\\,0)'[thumb_out]`;await r0("ffmpeg",["-y","-loglevel","warning",...["-i",$,"-filter_complex",z,"-map","[sprite_out]","-frames:v","1","-c:v","libwebp","-q:v","75",G,"-map","[thumb_out]","-c:v","libwebp","-q:v","75","-frames:v","1","-max_muxing_queue_size","1024",J]])}async generatePdfSprite($,G,J){let Z=this.createTempDir("pdf-sprite-");try{let X=I0.join(Z,"page");try{await r0("pdftoppm",["-png","-f","1","-l","100",$,X])}catch(j){let A=j?.code,F=j instanceof Error?j.message:String(j),y=F.toLowerCase();if(A==="ENOENT"||y.includes("enoent")||y.includes("not found")&&y.includes("pdftoppm"))throw Error(`pdftoppm executable not found in $PATH. Please install poppler-utils / poppler. (${F})`,{cause:j});throw j}let z=A0.readdirSync(Z).filter((j)=>j.endsWith(".png"));if(z.length===0)throw Error("pdftoppm produced no image outputs");z.sort((j,A)=>{let F=parseInt(j.replace(/[^0-9]/g,""),10),y=parseInt(A.replace(/[^0-9]/g,""),10);return F-y});let V=z.length,H=I0.join(Z,z[0]),U=await R$(H,{limitInputPixels:!1}).metadata(),O=U.width||800,R=U.height||1000;for(let j=1;j<=100;j++){let A=Math.min(V-1,Math.floor((j-1)*V/100)),F=I0.join(Z,z[A]),y=I0.join(Z,`frame_${j}.png`);if(F!==y)A0.copyFileSync(F,y)}let B=["-i",I0.join(Z,"frame_%d.png"),"-filter_complex","scale=w=300:h=-2,tile=10x10","-frames:v","1","-c:v","libwebp","-q:v","75",G];await r0("ffmpeg",["-y","-loglevel","warning",...B]),await R$(H,{limitInputPixels:!1}).toColorspace("srgb").resize(300,533,{withoutEnlargement:!0,fit:"inside"}).webp({quality:75}).toFile(J);let C=V;try{let{stdout:j}=await r0("pdfinfo",[$]),A=j.match(/Pages:\s+(\d+)/);if(A)C=parseInt(A[1],10)}catch{}return{pageCount:C,originalWidth:O,originalHeight:R}}finally{this.removeDir(Z)}}async getPdfInfo($){let G=this.createTempDir("pdf-info-"),J=800,Z=1000,X=1;try{let z=I0.join(G,"page");await r0("pdftoppm",["-png","-f","1","-l","1",$,z]);let V=A0.readdirSync(G).filter((H)=>H.endsWith(".png"));if(V.length>0){let H=await R$(I0.join(G,V[0]),{limitInputPixels:!1}).metadata();J=H.width||800,Z=H.height||1000}}catch(z){console.warn("pdftoppm not available for PDF dimensions extraction:",z)}try{let{stdout:z}=await r0("pdfinfo",[$]),V=z.match(/Pages:\s+(\d+)/);if(V)X=parseInt(V[1],10)}catch{}finally{this.removeDir(G)}return{originalWidth:J,originalHeight:Z,duration:0,bitRate:0,frameRate:0,totalFrames:X,hasAudio:!1,mimeType:"application/pdf"}}async generatePdfFromText($,G){let J=A0.readFileSync($,"utf-8"),X=/[\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\u4e00-\u9fff\uac00-\ud7af]/.test(J)?oZ():void 0;return new Promise((z,V)=>{let H=new pZ({size:"A4",margin:40,bufferPages:!0}),U=A0.createWriteStream(G);if(H.pipe(U),X)if(X.fontName!==void 0)H.font(X.fontPath,X.fontName);else H.font(X.fontPath);else H.font("Helvetica");H.fontSize(10),H.text(J,{lineGap:3,paragraphGap:4}),H.end(),U.on("finish",()=>z()),U.on("error",(O)=>V(O))})}async generatePdfFromCsv($,G){let J=A0.readFileSync($,"utf-8"),Z=vJ(J),z=/[\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\u4e00-\u9fff\uac00-\ud7af]/.test(J)?oZ():void 0;if(Z.length===0)Z.push(["(Empty CSV)"]);let V=Math.max(...Z.map((U)=>U.length)),H=V>5;return new Promise((U,O)=>{let R=new pZ({size:"A4",layout:H?"landscape":"portrait",margin:30,bufferPages:!0}),B=A0.createWriteStream(G);R.pipe(B);let C=()=>{if(z)if(z.fontName!==void 0)R.font(z.fontPath,z.fontName);else R.font(z.fontPath);else R.font("Helvetica");R.fontSize(9)};C();let j=R.page.width-R.page.margins.left-R.page.margins.right,A=Math.max(40,j/V),F=R.page.margins.left,y=R.page.margins.top,b=20,m=(c,t,L0)=>{if(t)R.rect(F,L0,A*V,b).fill("#e0e0e0"),R.fillColor("#000000");for(let x0=0;x0<V;x0++){let W$=c[x0]||"",Z$=F+x0*A;R.rect(Z$,L0,A,b).stroke("#cccccc"),R.fillColor("#000000").text(W$,Z$+4,L0+5,{width:A-8,height:b-6,ellipsis:!0})}},q=Z[0];m(q,!0,y),y+=b;for(let c=1;c<Z.length;c++){if(y+b>R.page.height-R.page.margins.bottom)R.addPage(),C(),y=R.page.margins.top,m(q,!0,y),y+=b;m(Z[c],!1,y),y+=b}R.end(),B.on("finish",()=>U()),B.on("error",(c)=>O(c))})}async extractAudio($,G,J){await r0("ffmpeg",["-y","-loglevel","warning",...["-i",$,"-vn","-acodec","libmp3lame","-b:a",J,G]])}async getAudioInfo($){let{stdout:G}=await r0("ffprobe",["-v","quiet","-print_format","json","-show_format","-show_streams",$]),J=JSON.parse(G),Z=J.streams.find((z)=>z.codec_type==="audio");if(!Z)throw Error("No audio stream found");let X=parseFloat(J.format.duration);return{originalWidth:0,originalHeight:0,duration:isNaN(X)?0:X,bitRate:parseFloat(J.format.bit_rate)||0,frameRate:0,totalFrames:0,startTimecode:void 0,hasAudio:!0,videoCodec:void 0,audioCodec:this.resolveCodecName(Z),audioChannels:Z?.channels,audioSampleRate:this.safeParseInt(Z?.sample_rate),audioBitDepth:this.safeParseInt(Z?.bits_per_raw_sample)??this.safeParseInt(Z?.bits_per_sample),mimeType:""}}async transcodeAudio($){let G=$.bitrate||"128k",J=["-i",$.inputFile,"-vn","-c:a","aac","-b:a",G,"-ac","2",$.outputFile];await r0("ffmpeg",["-y","-loglevel","warning",...J])}async extractVideoFrames($){if($.isImage){let V=I0.join($.outputDir,"1.webp");return await this.transcodeImage($.inputFile,V,-1,80,$.frameHeight),[V]}let G=await this.getVideoInfo($.inputFile),J=$.numFrames/G.duration,Z=I0.join($.outputDir,"%d.webp"),X=["-i",$.inputFile,"-vf",`fps=${J},scale=-2:${$.frameHeight}`,"-c:v","libwebp","-q:v","80",Z];return await r0("ffmpeg",["-y","-loglevel","warning",...X]),A0.readdirSync($.outputDir).filter((V)=>V.endsWith(".webp")).sort((V,H)=>{let U=parseInt(I0.basename(V,".webp")),O=parseInt(I0.basename(H,".webp"));return U-O}).map((V)=>I0.join($.outputDir,V))}createTempDir($){return A0.mkdtempSync(I0.join(rZ.tmpdir(),$))}removeDir($){A0.rmSync($,{recursive:!0,force:!0})}async createVideoTranscodeTask($,G,J){return this.prismaClient.workflowTask.create({data:{assetId:$,projectId:G,type:B0.transcode_video,status:w0.pending,payload:{projectId:G,transcode:J}}})}async createImageTranscodeTask($,G,J){return this.prismaClient.workflowTask.create({data:{assetId:$,projectId:G,type:B0.transcode_image,status:w0.pending,payload:{projectId:G,transcode:J}}})}async takeScreenshots($){let G=process.env.S3_BUCKET||"shumai",J=this.createTempDir("screenshot-"),Z=I0.join(J,I0.basename($.assetKey));try{await a.downloadToFile(G,$.assetKey,Z);let X=[];if($.count<=1)X=[$.start];else{let U=($.end-$.start)/$.count;X=Array.from({length:$.count},(O,R)=>$.start+R*U)}let z=$.commentTimestamp,V=0.1;if(z!==void 0&&z!==null){if(z>=$.start-V&&z<=$.end+V){let O=0,R=Math.abs(X[0]-z);for(let B=1;B<X.length;B++){let C=Math.abs(X[B]-z);if(C<R)R=C,O=B}X[O]=z}}let H=[];for(let U of X){let O=`shot-${U.toFixed(4)}-${i0()}.webp`,R=I0.join(J,O),B=["-ss",U.toFixed(4),"-i",Z,"-vframes","1","-vf","scale=-2:720","-c:v","libwebp","-q:v","80",R];if(await r0("ffmpeg",["-y","-loglevel","warning",...B]),z!==void 0&&z!==null&&Math.abs(U-z)<=0.001&&$.annotations&&$.annotations.length>0){let F=A0.readFileSync(R),y=await this.overlayAnnotationsOnBuffer(F,$.annotations);A0.writeFileSync(R,y)}let j=`files/${$.assetId}/screenshots/${O}`,A=A0.readFileSync(R);await a.putObject(G,j,A,A.length,"image/webp"),H.push({key:j,timestamp:U})}return H}finally{this.removeDir(J)}}async renderPdfPages($){let G=process.env.S3_BUCKET||"shumai",J=this.createTempDir("pdf-pages-"),Z=I0.join(J,I0.basename($.assetKey));try{await a.downloadToFile(G,$.assetKey,Z);let X=I0.join(J,"page");try{await r0("pdftoppm",["-png","-f",$.start.toString(),"-l",$.end.toString(),Z,X])}catch(U){let O=U?.code,R=U instanceof Error?U.message:String(U),B=R.toLowerCase();if(O==="ENOENT"||B.includes("enoent")||B.includes("not found")&&B.includes("pdftoppm"))throw Error(`pdftoppm executable not found in $PATH. Please install poppler-utils / poppler. (${R})`,{cause:U});throw U}let z=A0.readdirSync(J).filter((U)=>U.endsWith(".png"));if(z.length===0)throw Error("pdftoppm produced no image outputs");z.sort((U,O)=>{let R=parseInt(U.replace(/[^0-9]/g,""),10),B=parseInt(O.replace(/[^0-9]/g,""),10);return R-B});let V=[],H=T$($.assetKey);for(let U=0;U<z.length;U++){let O=$.start+U,R=I0.join(J,z[U]),B=`${H}-page-${O}-${i0()}.webp`,C=await R$(R,{limitInputPixels:!1}).toColorspace("srgb").resize(1920,1080,{fit:"inside",withoutEnlargement:!1}).webp({quality:85}).toBuffer(),j=$.commentTimestamp!==void 0&&$.commentTimestamp!==null?Math.round($.commentTimestamp):null;if(j!==null&&O===j&&$.annotations&&$.annotations.length>0)C=await this.overlayAnnotationsOnBuffer(C,$.annotations);let A=`files/${$.assetId}/pdf_pages/${B}`;await a.putObject(G,A,C,C.length,"image/webp"),V.push({key:A,page:O})}return V}finally{this.removeDir(J)}}async overlayAnnotationsOnBuffer($,G){if(!G||G.length===0)return $;let J=await R$($,{limitInputPixels:!1}).metadata(),Z=J.width||1920,X=J.height||1080,z=SV(Z,X,G);return await R$($,{limitInputPixels:!1}).composite([{input:Buffer.from(z),top:0,left:0}]).toColorspace("srgb").resize(16383,16383,{fit:"inside",withoutEnlargement:!0}).webp({quality:85}).toBuffer()}async overlayAnnotations($){let G=process.env.S3_BUCKET||"shumai",J=`annotation-${i0()}.webp`,Z=this.createTempDir("annotation-"),X=I0.join(Z,I0.basename($.assetKey));try{await a.downloadToFile(G,$.assetKey,X);let z=A0.readFileSync(X),V=await this.overlayAnnotationsOnBuffer(z,$.annotations),H=`files/${$.assetId}/annotations/${J}`;return await a.putObject(G,H,V,V.length,"image/webp"),H}finally{this.removeDir(Z)}}async renderSvgToPng($){return R$(Buffer.from($)).png().toBuffer()}async downscaleImageToPng($,G){let J=await R$($,{limitInputPixels:!1}).resize(G,G,{fit:"inside",withoutEnlargement:!0}).png().toBuffer(),Z=await R$(J).metadata();return{buffer:J,width:Z.width||100,height:Z.height||100}}async compositeOverlayToWebpFile($,G,J,Z,X){await R$($,{limitInputPixels:!1}).toColorspace("srgb").resize(Z,X,{fit:"inside"}).composite([{input:G}]).webp({quality:90}).toFile(J)}}function SV($,G,J){let Z=Math.max(2,Math.round(Math.max($,G)*0.004)),X=[];for(let z of J){let V=z.color||"#ff0000";switch(z.type){case"box":{if(z.points.length<2)continue;let[U,O]=z.points,R=Math.min(U[0],O[0])*$,B=Math.min(U[1],O[1])*G,C=Math.abs(O[0]-U[0])*$,j=Math.abs(O[1]-U[1])*G;X.push(`<rect x="${R}" y="${B}" width="${C}" height="${j}" stroke="${V}" stroke-width="${Z}" fill="none" />`);break}case"line":case"freehand":{if(z.points.length<2)continue;let U=z.points.map(([O,R])=>`${O*$},${R*G}`).join(" ");X.push(`<polyline points="${U}" stroke="${V}" stroke-width="${Z}" stroke-linecap="round" stroke-linejoin="round" fill="none" />`);break}case"arrow":{if(z.points.length<2)continue;let U=z.points.map(([c,t])=>[c*$,t*G]),O=U.map(([c,t])=>`${c},${t}`).join(" ");X.push(`<polyline points="${O}" stroke="${V}" stroke-width="${Z}" stroke-linecap="round" stroke-linejoin="round" fill="none" />`);let R=U[U.length-1],B=U[U.length-2],C=R[0]-B[0],j=R[1]-B[1],A=Math.atan2(j,C),F=Math.max(12,Math.max($,G)*0.015),y=R[0]-F*Math.cos(A-Math.PI/6),b=R[1]-F*Math.sin(A-Math.PI/6),m=R[0]-F*Math.cos(A+Math.PI/6),q=R[1]-F*Math.sin(A+Math.PI/6);X.push(`<polygon points="${R[0]},${R[1]} ${y},${b} ${m},${q}" fill="${V}" />`);break}}}return`<svg width="${$}" height="${G}" viewBox="0 0 ${$} ${G}" xmlns="http://www.w3.org/2000/svg">${X.join(`
|
|
1304
1304
|
`)}</svg>`}var f0=new sZ;var _0=class extends Error{res;status;constructor($=500,G){super(G?.message,{cause:G?.cause});this.res=G?.res,this.status=$}getResponse(){if(this.res)return new Response(this.res.body,{status:this.status,headers:this.res.headers});return new Response(this.message,{status:this.status})}};var w$=WZ(aZ(),1);import{Buffer as hG}from"buffer";function tZ($,G){let J=hG.from(JSON.stringify(G),"utf8"),Z=w$.default.randomBytes(w$.default.secretbox.nonceLength),X=w$.default.secretbox(J,Z,$);return hG.concat([Z,X]).toString("base64url")}function eZ($,G){if(!G)return null;let J=hG.from(G,"base64url");if(J.length<w$.default.secretbox.nonceLength)throw Error("token too short");let Z=J.subarray(0,w$.default.secretbox.nonceLength),X=J.subarray(w$.default.secretbox.nonceLength),z=w$.default.secretbox.open(X,Z,$);if(!z)throw Error("decrypt token failed");let V=hG.from(z).toString("utf8");return JSON.parse(V)}var $X=new Uint8Array([56,156,245,231,254,165,106,231,190,14,106,71,25,159,177,129,204,131,184,148,98,215,176,34,24,166,54,87,222,250,112,233]);function _V($){return tZ($X,$.toString())}function TV($){let G=eZ($X,$);return parseInt(G,10)}async function f$($,G,J){let Z={};if(G)Z.total=await G();let X=J.first||20;if(X<=0||X>200)X=20;let z=0;if(J.after)z=TV(J.after);let V=await $(z,X+1);if(V.length>X)return Z.cursor=_V(z+X),{data:V.slice(0,X),pageInfo:Z};return{data:V,pageInfo:Z}}async function xJ($,{targetIds:G,newTargetId:J,name:Z}){let X=await $.asset.findMany({where:{targetId:{in:G},type:I.symlink},orderBy:{id:"asc"}});if(X.length===0)return;let z=new Set((await $.asset.findMany({where:{targetId:J,type:I.symlink},select:{parentId:!0}})).map((V)=>V.parentId).filter((V)=>!!V));for(let V of X){if(!V.parentId)continue;if(z.has(V.parentId))await $.asset.delete({where:{id:V.id}}),await $.asset.update({where:{id:V.parentId},data:{fileCount:{decrement:1}}});else z.add(V.parentId),await $.asset.update({where:{id:V.id},data:{targetId:J,...Z!==void 0?{name:Z}:{}}})}}function GX($){let G=$.blocks.map((Z)=>{if(Z.type==="text")return`text|x:${Z.x.toFixed(4)}|y:${Z.y.toFixed(4)}|op:${Z.opacity.toFixed(2)}|rot:${Z.rotation.toFixed(2)}|sz:${Z.size.toFixed(4)}|col:${Z.color.toLowerCase()}|txt:${Z.text}`;else return`image|x:${Z.x.toFixed(4)}|y:${Z.y.toFixed(4)}|op:${Z.opacity.toFixed(2)}|rot:${Z.rotation.toFixed(2)}|sz:${Z.size.toFixed(4)}|img:${Z.imageAssetKey}`});G.sort();let J=G.join(";");return Bun.hash(J).toString(16)}class S$ extends Error{constructor($){super($);this.name="ShareLinkNotFoundError",Object.setPrototypeOf(this,S$.prototype)}}class uG extends Error{constructor($){super($);this.name="ShareLinkDisabledError",Object.setPrototypeOf(this,uG.prototype)}}class mG extends Error{constructor($){super($);this.name="ShareLinkExpiredError",Object.setPrototypeOf(this,mG.prototype)}}class lG extends Error{constructor($){super($);this.name="ShareLinkPasswordInvalidError",Object.setPrototypeOf(this,lG.prototype)}}class cG extends Error{constructor($="Watermark transcoding is currently in progress"){super($);this.name="ShareLinkWatermarkProcessingError",Object.setPrototypeOf(this,cG.prototype)}}async function j$($){if(!$)return;if($.startsWith("data:")||$.startsWith("http://")||$.startsWith("https://"))return $;try{let G=process.env.S3_BUCKET||"shumai";return await a.presign(G,$,"GET")}catch(G){console.error(`Failed to presign avatar URL for key ${$}:`,G);return}}class JX{async createShareLink($,G,J){let Z=await v.project.findUnique({where:{id:$},include:{shareRoot:!0}});if(!Z)throw Error("Project not found");if(!Z.shareRootId){let X=await v.asset.create({data:{name:"share_root",type:I.share_root,status:"processed",projectId:$}});Z=await v.project.update({where:{id:$},data:{shareRootId:X.id},include:{shareRoot:!0}})}return await v.$transaction(async(X)=>{let z=await X.asset.create({data:{name:G.name,type:I.share,status:"processed",projectId:$,parentId:Z.shareRootId}}),V=await X.shareLink.create({data:{name:G.name,expireAt:G.expireAt?new Date(G.expireAt):null,password:G.password,isDisabled:G.isDisabled??!1,allowDownload:G.allowDownload??!0,defaultSortOrder:G.defaultSortOrder,viewMode:G.viewMode,projectId:$,rootFolderId:z.id,creatorId:J},include:{creator:!0}});return await this.toShareLinkInfo(V)})}async updateShareLink($,G){let J=await v.shareLink.findUnique({where:{id:$}});if(!J)throw Error("Share link not found");let Z=await v.shareLink.update({where:{id:$},data:{name:G.name,expireAt:G.expireAt!==void 0?G.expireAt?new Date(G.expireAt):null:void 0,password:G.password,isDisabled:G.isDisabled,allowDownload:G.allowDownload,defaultSortOrder:G.defaultSortOrder,viewMode:G.viewMode,fieldVisibility:G.fieldVisibility??void 0},include:{creator:!0}});if(G.name)await v.asset.update({where:{id:J.rootFolderId},data:{name:G.name}});return await this.toShareLinkInfo(Z)}async deleteShareLink($){let G=await v.shareLink.findUnique({where:{id:$}});if(!G)throw Error("Share link not found");await v.$transaction(async(J)=>{await J.shareLink.delete({where:{id:$}}),await J.asset.delete({where:{id:G.rootFolderId}})})}async listProjectShareLinks($){let G={projectId:$.projectId};return f$(async(J,Z)=>{let X=await v.shareLink.findMany({where:G,include:{creator:!0},skip:J,take:Z,orderBy:{createdAt:"desc"}});return await Promise.all(X.map((z)=>this.toShareLinkInfo(z)))},()=>v.shareLink.count({where:G}),$)}async getShareLink($,G=v){let J=await G.shareLink.findUnique({where:{id:$},include:{creator:!0}});if(!J)throw new S$("Share link not found");return await this.toShareLinkInfo(J,G)}async addAssetToShare($,G){let J=await v.shareLink.findUnique({where:{id:$}});if(!J)throw Error("Share link not found");let Z=G.assetIds,X=await v.asset.findMany({where:{parentId:J.rootFolderId,targetId:{in:Z},type:I.symlink},select:{targetId:!0}}),z=new Set(X.map((O)=>O.targetId)),V=Z.filter((O)=>!z.has(O));if(V.length===0)return 0;let H=await v.asset.findMany({where:{id:{in:V}}}),U=new Map(H.map((O)=>[O.id,O]));if(await v.$transaction(async(O)=>{for(let R of V){let B=U.get(R);if(!B)continue;await O.asset.create({data:{name:B.name,type:I.symlink,status:"processed",projectId:J.projectId,parentId:J.rootFolderId,targetId:R}})}await O.asset.update({where:{id:J.rootFolderId},data:{fileCount:{increment:V.length}}})}),J.watermarkConfigId)await v.shareLink.update({where:{id:$},data:{watermarkStatus:"processing"}}),await g$.triggerWatermarkTranscodeForShareLink($,J.watermarkConfigId);return V.length}async removeAssetFromShare($,G){let J=await v.asset.findUnique({where:{id:G}});if(!J||J.type!==I.symlink)throw Error("Symlink not found");let Z=await v.shareLink.findUnique({where:{id:$}});if(!Z||J.parentId!==Z.rootFolderId)throw Error("Asset does not belong to this share link");await v.$transaction(async(X)=>{await X.asset.delete({where:{id:G}}),await X.asset.update({where:{id:Z.rootFolderId},data:{fileCount:{decrement:1}}})})}async verifyPublicAccess($,G){let J=await v.$queryRaw`
|
|
1305
1305
|
WITH RECURSIVE
|
|
1306
1306
|
-- Trace ancestors in the real asset tree
|
|
@@ -1447,7 +1447,7 @@ model RecentFileItem {
|
|
|
1447
1447
|
WHERE asset_id = ${$.assetId}
|
|
1448
1448
|
AND watermark_config_id = ${$.watermarkConfigId}
|
|
1449
1449
|
FOR UPDATE
|
|
1450
|
-
`;if(J.length>0){let Z=J[0];if(Z.status===F$.completed)return{action:"completed",media:Z.media};if(Z.status===F$.failed)return{action:"failed"};return{action:"processing"}}return await G.watermarkFile.create({data:{assetId:$.assetId,watermarkConfigId:$.watermarkConfigId,status:F$.processing}}),{action:"created"}})}async function ZY($){let Z=Date.now();while(Date.now()-Z<600000){let X=await v.watermarkFile.findUnique({where:{assetId_watermarkConfigId:{assetId:$.assetId,watermarkConfigId:$.watermarkConfigId}}});if(X&&X.status!==F$.processing)return{status:X.status,media:X.media};await new Promise((z)=>setTimeout(z,1000))}return{status:F$.failed}}async function XY($){let G=process.env.S3_BUCKET||"shumai",J=await v.watermarkConfig.findUnique({where:{id:$.watermarkConfigId}});if(!J)throw pG.create({message:`Watermark config not found: ${$.watermarkConfigId}`,nonRetryable:!0});let Z=await v.asset.findUnique({where:{id:$.assetId},include:{storageKey:!0,project:{include:{team:!0}}}});if(!Z||!Z.storageKey?.key)throw pG.create({message:`Asset or storage key not found: ${$.assetId}`,nonRetryable:!0});let z=Z.project?.team?.settings?.transcode?.hardwareAcceleration??"off",V=J.config,H=Z.storageKey.key,U=T$(H),O=f0.createTempDir("watermark-"),R=O$.join(O,O$.basename(H));try{await a.downloadToFile(G,H,R);let B=Z.mediaType?.startsWith("video/")||Z.media?.proxyType==="video",C=Z.mediaType?.startsWith("image/")||Z.media?.proxyType==="image",j=1920,A=1080,F=0,y=0,b,m=30,q=0,c="00:00:00:00",t=!1,L0;if(B){let N0=await f0.getVideoInfo(R);j=N0.originalWidth,A=N0.originalHeight,F=N0.duration,y=N0.bitRate,b=N0.videoBitRate,m=N0.frameRate,q=N0.totalFrames,c=N0.startTimecode||"00:00:00:00",t=N0.hasAudio,L0=N0.videoBitRate||N0.bitRate}else if(C){let N0=await f0.getImageInfo(R);j=N0.originalWidth,A=N0.originalHeight}else throw pG.create({message:`Asset ${$.assetId} is neither video nor image`,nonRetryable:!0});let x0=new Map,W$=(V.blocks||[]).filter((N0)=>N0.type==="image");for(let N0 of W$){if(!N0.imageAssetKey)continue;try{let X$=O$.join(O,`block-${i0()}`);await a.downloadToFile(G,N0.imageAssetKey,X$);let n0=u$.readFileSync(X$),$0=await f0.downscaleImageToPng(n0,GY);x0.set(N0.imageAssetKey,{imageAssetKey:N0.imageAssetKey,base64Data:$0.buffer.toString("base64"),mimeType:"image/png",width:$0.width,height:$0.height})}catch(X$){z$.warn({imageAssetKey:N0.imageAssetKey,err:X$},"Failed to load watermark block image")}}let Z$=Z.media,c0={duration:F,filesize:0,frames:q,proxyType:B?"video":"image",imageTranscodes:[],videoTranscodes:[],finishedAt:new Date().toISOString(),metadata:{originalWidth:j,originalHeight:A,duration:F,bitRate:y,videoBitRate:b,frameRate:m,totalFrames:q,startTimecode:c,hasAudio:t,format:{}},original:{key:H,filesizeInBytes:0,codec:""}};if(C){let N0=Z$?.imageTranscodes||[],X$=0;for(let n0=0;n0<N0.length;n0++){let $0=N0[n0],y0=$0.width||j,i=$0.height||A,O0=dJ(V,y0,i,x0),d0=await f0.renderSvgToPng(O0),K$=`${U}-watermark-${$.watermarkConfigId}-${y0}x${i}.webp`,q0=O$.join(O,K$);await f0.compositeOverlayToWebpFile(R,d0,q0,y0,i);let s0=u$.statSync(q0);X$+=s0.size;let T0=O$.posix.join(O$.posix.dirname(H),K$);await a.putObject(G,T0,Bun.file(q0).stream(),s0.size,"image/webp"),c0.imageTranscodes.push({key:T0,width:y0,height:i,quality:$0.quality??90,format:$0.format??"webp"})}c0.filesize=X$}else if(B){let N0=Z$?.videoTranscodes||[],X$=0;for(let n0=0;n0<N0.length;n0++){let $0=N0[n0],y0=$0.width||j,i=$0.height||A,O0=$0.resolution||`${i}p`,d0=dJ(V,y0,i,x0),K$=await f0.renderSvgToPng(d0),q0=O$.join(O,`watermarkOverlay-${n0}.png`);u$.writeFileSync(q0,K$);let s0=`${U}-watermark-${$.watermarkConfigId}-${O0}.mp4`,T0=O$.join(O,s0);await f0.transcodeVideo({inputFile:R,outputFile:T0,width:y0,height:i,disableAudio:!t,overlayFile:q0,hardwareAcceleration:z,sourceVideoBitrate:L0});let b0=u$.statSync(T0);X$+=b0.size;let Q0=O$.posix.join(O$.posix.dirname(H),s0);await a.putObject(G,Q0,Bun.file(T0).stream(),b0.size,"video/mp4"),c0.videoTranscodes.push({key:Q0,width:y0,height:i,resolution:O0})}c0.filesize=X$}return c0}catch(B){throw z$.error({assetId:$.assetId,err:B},"Failed to generate watermark proxy"),pG.create({message:`Failed to generate watermark proxy: ${B instanceof Error?B.message:String(B)}`,nonRetryable:!0,cause:B instanceof Error?B:void 0})}finally{f0.removeDir(O)}}async function QY($){if(await v.watermarkFile.upsert({where:{assetId_watermarkConfigId:{assetId:$.assetId,watermarkConfigId:$.watermarkConfigId}},create:{assetId:$.assetId,watermarkConfigId:$.watermarkConfigId,media:$.mediaInfo??void 0,status:$.status},update:{media:$.mediaInfo??void 0,status:$.status}}),$.shareLinkId)await g$.checkAndUpdateShareLinkStatus($.shareLinkId)}import{ApplicationFailure as zY}from"@temporalio/workflow";async function Y$($){let{getTranscodeWorkerQueueActivity:G,updateTaskStatusActivity:J}=l0(),Z=await r(V$,G);return await r(Z,J,{taskId:$.id,status:"processing"}),Z}async function P$($,G){let{getAssetActivity:J}=l0(),Z=await r($,J,G),X=Z?.storageKey?.key;if(!Z||!X)throw zY.create({message:"Asset not found or has no key",nonRetryable:!0});return{asset:Z,key:X}}async function J$($,G,J){let{updateTaskStatusActivity:Z}=l0();await r($,Z,{taskId:G,status:"completed",...J?{output:J}:{}})}async function H$($,G,J){let{updateTaskStatusActivity:Z}=l0();if($)await r($,Z,{taskId:G,status:"failed",output:{error:J instanceof Error?J.message:String(J)}})}async function s$($,G){if(G&&$){let{cleanupTmpDirActivity:J}=l0();try{await r($,J,{tmpDir:G})}catch(Z){console.error("Failed to cleanup tmp dir:",Z)}}}var VY={"2160p":3840,"1080p":1920,"720p":1280,"540p":960,"360p":640,"180p":320};function DX($,G,J){let Z=VY[$];if(!Z)return[0,0];let X,z;if(G>=J)X=Z,z=Math.round(X*(J/G));else z=Z,X=Math.round(z*(G/J));if(X%2!==0)X++;if(z%2!==0)z++;return[X,z]}var a$=[{name:"2160p",longSide:3840},{name:"1080p",longSide:1920},{name:"720p",longSide:1280},{name:"540p",longSide:960},{name:"360p",longSide:640}];function YY($,G){let J=Math.max($,G),Z=a$.filter((X)=>X.longSide<=J);if(Z.length>0)return Z.sort((X,z)=>z.longSide-X.longSide),Z[0];return a$[a$.length-1]}function jX($,G,J){let Z=["180p"],X=$,z=$;if(z==="single"||z==="disable")X="best_match";else if(z==="full")X="all";let V=YY(G,J);if(X==="best_match")Z.push(V.name);else if(X==="all"){let H=a$.findIndex((U)=>U.name===V.name);if(H!==-1)for(let U=H;U<a$.length;U++)Z.push(a$[U].name)}return Z}async function oG($){let G,J="";try{J=await Y$($);let{updateAssetStatusActivity:Z,getMediaInfoActivity:X,transcodeVideoActivity:z,transcodeAudioActivity:V,transcodeImageActivity:H,generateSpriteActivity:U,updateAssetMediaActivity:O,downloadMediaToTmpActivity:R,createEmbeddingTaskIfEnabledActivity:B,createAutofillTaskIfEnabledActivity:C}=l0();await r(J,Z,{assetId:$.assetId,status:"processing"});let{asset:j,key:A}=await P$(J,$.assetId),F=await r(J,R,{assetKey:A}),{filePath:y}=F;G=F.tmpDir;let b=$.payload?.transcode||{},m=j.mediaType?.startsWith("audio/")?"audio":"video",q=await r(J,X,{filePath:y,assetId:j.id,proxyType:m,mediaType:j.mediaType||""});q.original={key:A,filesizeInBytes:0,codec:""};let c=q.metadata;if(q.proxyType==="video"&&c){let L0=jX(b.videoStrategy||"best_match",c.originalWidth,c.originalHeight);for(let x0 of L0){let[W$,Z$]=DX(x0,c.originalWidth,c.originalHeight),N0=await r(J,z,{assetKey:A,filePath:y,videoSpec:{resolution:x0,width:W$,height:Z$},duration:c.duration,originalFps:c.frameRate,hardwareAcceleration:b.hardwareAcceleration,sourceVideoBitrate:c.videoBitRate||c.bitRate});if(x0==="180p")q.videoPreview=N0;else q.videoTranscodes.push(N0)}}if(q.proxyType==="audio"&&c){let L0=await r(J,V,{assetKey:A,filePath:y});q.videoTranscodes.push(L0)}if(b.thumbnail){let L0=await r(J,H,{assetKey:A,filePath:y,imageSpec:{width:300,height:300,quality:80,format:"webp",isPreview:!0}});q.thumbnail=L0}if(b.sprite||b.poster){let L0=A.lastIndexOf("/"),x0=L0===-1?"":A.substring(0,L0),W$={key:x0?`${x0}/sprite.webp`:"sprite.webp",frames:100,tileX:10,tileY:10},Z$={key:x0?`${x0}/poster.webp`:"poster.webp"},c0=await r(J,U,{assetKey:A,filePath:y,spriteSpec:W$,posterSpec:Z$,mediaInfo:q});q.sprite=c0.sprite,q.poster=c0.poster}await r(J,O,{assetId:j.id,mediaInfo:q}),await r(J,Z,{assetId:j.id,status:"processed"}),await r(J,B,{assetId:j.id,teamId:$.teamId,projectId:$.projectId}),await r(J,C,{assetId:j.id,teamId:$.teamId,projectId:$.projectId}),await J$(J,$.id)}catch(Z){throw console.error(`transcodeVideoWorkflow failed for task ${$.id}:`,Z),await H$(J,$.id,Z),Z}finally{await s$(J,G)}}async function iG($){let G,J="";try{J=await Y$($);let{updateAssetStatusActivity:Z,getMediaInfoActivity:X,transcodeImageActivity:z,updateAssetMediaActivity:V,downloadMediaToTmpActivity:H,createEmbeddingTaskIfEnabledActivity:U,createAutofillTaskIfEnabledActivity:O}=l0();await r(J,Z,{assetId:$.assetId,status:"processing"});let{asset:R,key:B}=await P$(J,$.assetId),C=await r(J,H,{assetKey:B}),{filePath:j}=C;G=C.tmpDir;let A=$.payload?.transcode||{},F=await r(J,X,{filePath:j,assetId:R.id,proxyType:"image",mediaType:R.mediaType||""});F.original={key:B,filesizeInBytes:0,codec:""};let y=F.metadata;if(F.proxyType==="image"&&y){let m={width:y.originalWidth,height:y.originalHeight,quality:90,format:"webp"},q=await r(J,z,{assetKey:B,filePath:j,imageSpec:m});F.imageTranscodes.push(q)}if(A.thumbnail){let m=await r(J,z,{assetKey:B,filePath:j,imageSpec:{width:300,height:300,quality:80,format:"webp",isPreview:!0}});F.thumbnail=m}await r(J,V,{assetId:R.id,mediaInfo:F}),await r(J,Z,{assetId:R.id,status:"processed"}),await r(J,U,{assetId:R.id,teamId:$.teamId,projectId:$.projectId}),await r(J,O,{assetId:R.id,teamId:$.teamId,projectId:$.projectId}),await J$(J,$.id)}catch(Z){throw console.error(`transcodeImageWorkflow failed for task ${$.id}:`,Z),await H$(J,$.id,Z),Z}finally{await s$(J,G)}}async function rG($){let G,J="";try{J=await Y$($);let{updateAssetStatusActivity:Z,getMediaInfoActivity:X,generateSpriteActivity:z,updateAssetMediaActivity:V,downloadMediaToTmpActivity:H,generatePdfProxyActivity:U,createEmbeddingTaskIfEnabledActivity:O,createAutofillTaskIfEnabledActivity:R}=l0();await r(J,Z,{assetId:$.assetId,status:"processing"});let{asset:B,key:C}=await P$(J,$.assetId),j=await r(J,H,{assetKey:C}),A=j.filePath;G=j.tmpDir;let F=await r(J,U,{assetId:B.id,assetKey:C,filePath:A,mediaType:B.mediaType||"",filename:B.name||""});A=F.pdfFilePath;let y=$.payload?.transcode||{},b=await r(J,X,{filePath:A,assetId:B.id,proxyType:"pdf",mediaType:B.mediaType||""});if(b.original={key:C,filesizeInBytes:0,codec:""},b.pdfTranscode={key:F.pdfProxyKey},y.sprite||y.poster){let m=C.lastIndexOf("/"),q=m===-1?"":C.substring(0,m),c={key:q?`${q}/sprite.webp`:"sprite.webp",frames:100,tileX:10,tileY:10},t={key:q?`${q}/poster.webp`:"poster.webp"},L0=await r(J,z,{assetKey:C,filePath:A,spriteSpec:c,posterSpec:t,mediaInfo:b});b.sprite=L0.sprite,b.poster=L0.poster}await r(J,V,{assetId:B.id,mediaInfo:b}),await r(J,Z,{assetId:B.id,status:"processed"}),await r(J,O,{assetId:B.id,teamId:$.teamId,projectId:$.projectId}),await r(J,R,{assetId:B.id,teamId:$.teamId,projectId:$.projectId}),await J$(J,$.id)}catch(Z){throw console.error(`transcodePdfWorkflow failed for task ${$.id}:`,Z),await H$(J,$.id,Z),Z}finally{await s$(J,G)}}import{ApplicationFailure as HY}from"@temporalio/workflow";async function sG($){let G="";try{G=await Y$($);let J=$.payload;if(!J?.pdfPages)throw HY.create({message:"Invalid payload for pdfPages task",nonRetryable:!0});let{asset:Z,key:X}=await P$(G,$.assetId),{renderPdfPagesActivity:z}=l0(),V=Z.media?.pdfTranscode?.key||X,H=await r(G,z,{assetKey:V,assetId:Z.id,start:J.pdfPages.start,end:J.pdfPages.end,commentTimestamp:J.pdfPages.commentTimestamp,annotations:J.pdfPages.annotations});await J$(G,$.id,{pages:H})}catch(J){throw console.error(`renderPdfPagesWorkflow failed for task ${$.id}:`,J),await H$(G,$.id,J),J}}import{ApplicationFailure as UY}from"@temporalio/workflow";async function aG($){let G="";try{G=await Y$($);let J=$.payload;if(!J?.screenshot)throw UY.create({message:"Invalid payload for screenshot task",nonRetryable:!0});let{asset:Z,key:X}=await P$(G,$.assetId),{takeScreenshotsActivity:z}=l0(),V=await r(G,z,{assetKey:X,assetId:Z.id,start:J.screenshot.start,end:J.screenshot.end,count:J.screenshot.count,commentTimestamp:J.screenshot.commentTimestamp,annotations:J.screenshot.annotations});await J$(G,$.id,{screenshots:V})}catch(J){throw console.error(`takeVideoScreenshotsWorkflow failed for task ${$.id}:`,J),await H$(G,$.id,J),J}}import{ApplicationFailure as LX}from"@temporalio/workflow";async function tG($){let G="";try{G=await Y$($);let J=$.payload;if(!J?.imageAnnotation)throw LX.create({message:"Invalid payload for imageAnnotation task",nonRetryable:!0});let{getAssetActivity:Z,overlayAnnotationsActivity:X}=l0(),z=await r(G,Z,$.assetId),V=z?.storageKey?.key;if(z?.media){let U=z.media;if(U.imageTranscodes&&U.imageTranscodes.length>0)V=U.imageTranscodes[0].key||V}if(!z||!V)throw LX.create({message:"Asset not found or has no key",nonRetryable:!0});let H=await r(G,X,{assetKey:V,assetId:z.id,annotations:J.imageAnnotation.annotations});await J$(G,$.id,{key:H})}catch(J){throw console.error(`overlayImageAnnotationWorkflow failed for task ${$.id}:`,J),await H$(G,$.id,J),J}}import{ApplicationFailure as oJ}from"@temporalio/workflow";async function eG($){let G="",J=$.payload?.watermark?.watermarkConfigId,Z=$.payload?.watermark?.shareLinkId;if(!J)throw oJ.create({message:"watermarkConfigId is required in task payload",nonRetryable:!0});try{G=await Y$($);let{initWatermarkFileActivity:X,waitForWatermarkFileActivity:z,transcodeWatermarkMediaActivity:V,completeWatermarkFileActivity:H}=l0(),U=await r(G,X,{assetId:$.assetId,watermarkConfigId:J});if(U.action==="completed"){if(Z)await r(G,H,{assetId:$.assetId,watermarkConfigId:J,status:"completed",shareLinkId:Z});await J$(G,$.id);return}if(U.action==="failed")throw oJ.create({message:"Watermark file generation failed in another task",nonRetryable:!0});if(U.action==="processing"){if((await r(G,z,{assetId:$.assetId,watermarkConfigId:J})).status==="completed"){if(Z)await r(G,H,{assetId:$.assetId,watermarkConfigId:J,status:"completed",shareLinkId:Z});await J$(G,$.id);return}throw oJ.create({message:"Watermark file generation failed in in-flight task",nonRetryable:!0})}let O=await r(G,V,{assetId:$.assetId,watermarkConfigId:J});await r(G,H,{assetId:$.assetId,watermarkConfigId:J,mediaInfo:O,status:"completed",shareLinkId:Z}),await J$(G,$.id)}catch(X){if(G&&J){let{completeWatermarkFileActivity:z}=l0();try{await r(G,z,{assetId:$.assetId,watermarkConfigId:J,status:"failed",shareLinkId:Z})}catch(V){console.error("Failed to update watermark file status to failed:",V)}}throw await H$(G,$.id,X),X}}async function CX($){let G=$.payload;if(G?.watermark||$.type==="transcode_watermark")return eG($);if(G?.pdfPages)return sG($);if(G?.screenshot)return aG($);if(G?.imageAnnotation)return tG($);if($.type==="transcode_image")return iG($);if($.type==="transcode_pdf")return rG($);return oG($)}class dG{db;assetId;teamId;projectId;spec={};constructor($,G,J,Z){this.db=$;this.assetId=G;this.teamId=J;this.projectId=Z}setStrategy($){return this.spec.videoStrategy=$,this}setHardwareAcceleration($){if($)this.spec.hardwareAcceleration=$;return this}withSprite(){return this.spec.sprite=!0,this}withPoster(){return this.spec.poster=!0,this}async submit(){return(await this.db.workflowTask.create({data:{assetId:this.assetId,teamId:this.teamId,projectId:this.projectId,type:B0.transcode_video,status:w0.pending,payload:{projectId:this.projectId,transcode:this.spec}}})).id}}class uJ{db;assetId;teamId;projectId;spec={};constructor($,G,J,Z){this.db=$;this.assetId=G;this.teamId=J;this.projectId=Z}withThumbnail(){return this.spec.thumbnail=!0,this}async submit(){return(await this.db.workflowTask.create({data:{assetId:this.assetId,teamId:this.teamId,projectId:this.projectId,type:B0.transcode_image,status:w0.pending,payload:{projectId:this.projectId,transcode:this.spec}}})).id}}class mJ{db;assetId;teamId;projectId;spec={};constructor($,G,J,Z){this.db=$;this.assetId=G;this.teamId=J;this.projectId=Z}withSprite(){return this.spec.sprite=!0,this}withPoster(){return this.spec.poster=!0,this}async submit(){return(await this.db.workflowTask.create({data:{assetId:this.assetId,teamId:this.teamId,projectId:this.projectId,type:B0.transcode_pdf,status:w0.pending,payload:{projectId:this.projectId,transcode:this.spec}}})).id}}function PX(){q$(B0.transcode,CX),q$(B0.transcode_video,oG),q$(B0.transcode_image,iG),q$(B0.transcode_pdf,rG),q$(B0.transcode_pdf_pages,sG),q$(B0.transcode_screenshot,aG),q$(B0.transcode_image_annotation,tG),q$(B0.transcode_watermark,eG),FJ(nJ),FJ(pJ)}import{spawn as OY}from"child_process";import{existsSync as e$,writeFileSync as TX,readFileSync as RG,unlinkSync as t$,mkdirSync as EX,statSync as AX,createReadStream as WY,openSync as KY}from"fs";import{join as MG}from"path";import{homedir as NY}from"os";var wX=MG(NY(),".shumai"),FX=MG(wX,"pids"),qX=MG(wX,"logs");function $J($){try{return process.kill($,0),!0}catch(G){if(G&&typeof G==="object"&&"code"in G&&G.code==="EPERM")return!0;return!1}}async function SX($,G){if(!e$(G))return console.log(`No running instance of ${$} found.`),!1;let J=parseInt(RG(G,"utf8").trim(),10);if(isNaN(J)){console.log(`Invalid PID found in ${G}. Cleaning up file.`);try{t$(G)}catch{}return!1}let Z=$J(J);if(!Z){console.log(`Process ${J} is not running. Cleaning up PID file.`);try{t$(G)}catch{}return!1}console.log(`Stopping ${$} (PID: ${J})...`);try{process.kill(J,"SIGTERM")}catch(X){return console.error(`Failed to send SIGTERM to process ${J}:`,X),!1}for(let X=0;X<30;X++){if(!$J(J)){Z=!1;break}await new Promise((z)=>setTimeout(z,100))}if(Z){console.log(`Process ${J} did not stop gracefully. Sending SIGKILL...`);try{process.kill(J,"SIGKILL")}catch(X){console.error(`Failed to send SIGKILL to process ${J}:`,X)}}try{t$(G)}catch{}return console.log(`Successfully stopped ${$}.`),!0}function _X($,G,J){if(e$(G)){let V=parseInt(RG(G,"utf8").trim(),10);if(!isNaN(V)&&V!==process.pid)if($J(V))console.error(`${$} is already running (PID: ${V}). Use '${$} stop' or '${$} restart'.`),process.exit(1);else try{t$(G)}catch{}}console.log(`Starting ${$} in background...`);let Z=KY(J,"w"),X=process.argv.slice(1).filter((V)=>V!=="-d"&&V!=="restart"),z=OY(process.argv[0],X,{detached:!0,stdio:["ignore",Z,Z],env:{...process.env,SHUMAI_DAEMONIZED:"true"}});if(z.pid===void 0)console.error(`Failed to spawn background process for ${$}.`),process.exit(1);z.unref(),TX(G,z.pid.toString(),"utf8"),console.log(`\uD83D\uDE80 Started ${$} in background (PID: ${z.pid}).`),console.log(`\uD83D\uDCC4 Logs are being written to ${J}`),process.exit(0)}function RY($,G){if(!e$(G))console.log(`No log file found for ${$}.`),process.exit(0);let X=RG(G,"utf8").split(`
|
|
1450
|
+
`;if(J.length>0){let Z=J[0];if(Z.status===F$.completed)return{action:"completed",media:Z.media};if(Z.status===F$.failed)return{action:"failed"};return{action:"processing"}}return await G.watermarkFile.create({data:{assetId:$.assetId,watermarkConfigId:$.watermarkConfigId,status:F$.processing}}),{action:"created"}})}async function ZY($){let Z=Date.now();while(Date.now()-Z<600000){let X=await v.watermarkFile.findUnique({where:{assetId_watermarkConfigId:{assetId:$.assetId,watermarkConfigId:$.watermarkConfigId}}});if(X&&X.status!==F$.processing)return{status:X.status,media:X.media};await new Promise((z)=>setTimeout(z,1000))}return{status:F$.failed}}async function XY($){let G=process.env.S3_BUCKET||"shumai",J=await v.watermarkConfig.findUnique({where:{id:$.watermarkConfigId}});if(!J)throw pG.create({message:`Watermark config not found: ${$.watermarkConfigId}`,nonRetryable:!0});let Z=await v.asset.findUnique({where:{id:$.assetId},include:{storageKey:!0,project:{include:{team:!0}}}});if(!Z||!Z.storageKey?.key)throw pG.create({message:`Asset or storage key not found: ${$.assetId}`,nonRetryable:!0});let z=Z.project?.team?.settings?.transcode?.hardwareAcceleration??"off",V=J.config,H=Z.storageKey.key,U=T$(H),O=f0.createTempDir("watermark-"),R=O$.join(O,O$.basename(H));try{await a.downloadToFile(G,H,R);let B=Z.mediaType?.startsWith("video/")||Z.media?.proxyType==="video",C=Z.mediaType?.startsWith("image/")||Z.media?.proxyType==="image",j=1920,A=1080,F=0,y=0,b,m=30,q=0,c="00:00:00:00",t=!1,L0;if(B){let N0=await f0.getVideoInfo(R);j=N0.originalWidth,A=N0.originalHeight,F=N0.duration,y=N0.bitRate,b=N0.videoBitRate,m=N0.frameRate,q=N0.totalFrames,c=N0.startTimecode||"00:00:00:00",t=N0.hasAudio,L0=N0.videoBitRate||N0.bitRate}else if(C){let N0=await f0.getImageInfo(R);j=N0.originalWidth,A=N0.originalHeight}else throw pG.create({message:`Asset ${$.assetId} is neither video nor image`,nonRetryable:!0});let x0=new Map,W$=(V.blocks||[]).filter((N0)=>N0.type==="image");for(let N0 of W$){if(!N0.imageAssetKey)continue;try{let X$=O$.join(O,`block-${i0()}`);await a.downloadToFile(G,N0.imageAssetKey,X$);let n0=u$.readFileSync(X$),$0=await f0.downscaleImageToPng(n0,GY);x0.set(N0.imageAssetKey,{imageAssetKey:N0.imageAssetKey,base64Data:$0.buffer.toString("base64"),mimeType:"image/png",width:$0.width,height:$0.height})}catch(X$){z$.warn({imageAssetKey:N0.imageAssetKey,err:X$},"Failed to load watermark block image")}}let Z$=Z.media,c0={duration:F,filesize:0,frames:q,proxyType:B?"video":"image",imageTranscodes:[],videoTranscodes:[],finishedAt:new Date().toISOString(),metadata:{originalWidth:j,originalHeight:A,duration:F,bitRate:y,videoBitRate:b,frameRate:m,totalFrames:q,startTimecode:c,hasAudio:t,format:{}},original:{key:H,filesizeInBytes:0,codec:""}};if(C){let N0=Z$?.imageTranscodes||[],X$=0;for(let n0=0;n0<N0.length;n0++){let $0=N0[n0],y0=$0.width||j,i=$0.height||A,O0=dJ(V,y0,i,x0),d0=await f0.renderSvgToPng(O0),K$=`${U}-watermark-${$.watermarkConfigId}-${y0}x${i}.webp`,q0=O$.join(O,K$);await f0.compositeOverlayToWebpFile(R,d0,q0,y0,i);let s0=u$.statSync(q0);X$+=s0.size;let T0=O$.posix.join(O$.posix.dirname(H),K$);await a.putObject(G,T0,Bun.file(q0).stream(),s0.size,"image/webp"),c0.imageTranscodes.push({key:T0,width:y0,height:i,quality:$0.quality??90,format:$0.format??"webp"})}c0.filesize=X$}else if(B){let N0=Z$?.videoTranscodes||[],X$=0;for(let n0=0;n0<N0.length;n0++){let $0=N0[n0],y0=$0.width||j,i=$0.height||A,O0=$0.resolution||`${i}p`,d0=dJ(V,y0,i,x0),K$=await f0.renderSvgToPng(d0),q0=O$.join(O,`watermarkOverlay-${n0}.png`);u$.writeFileSync(q0,K$);let s0=`${U}-watermark-${$.watermarkConfigId}-${O0}.mp4`,T0=O$.join(O,s0);await f0.transcodeVideo({inputFile:R,outputFile:T0,width:y0,height:i,disableAudio:!t,overlayFile:q0,hardwareAcceleration:z,sourceVideoBitrate:L0});let b0=u$.statSync(T0);X$+=b0.size;let Q0=O$.posix.join(O$.posix.dirname(H),s0);await a.putObject(G,Q0,Bun.file(T0).stream(),b0.size,"video/mp4"),c0.videoTranscodes.push({key:Q0,width:y0,height:i,resolution:O0})}c0.filesize=X$}return c0}catch(B){throw z$.error({assetId:$.assetId,err:B},"Failed to generate watermark proxy"),pG.create({message:`Failed to generate watermark proxy: ${B instanceof Error?B.message:String(B)}`,nonRetryable:!0,cause:B instanceof Error?B:void 0})}finally{f0.removeDir(O)}}async function QY($){if(await v.watermarkFile.upsert({where:{assetId_watermarkConfigId:{assetId:$.assetId,watermarkConfigId:$.watermarkConfigId}},create:{assetId:$.assetId,watermarkConfigId:$.watermarkConfigId,media:$.mediaInfo??void 0,status:$.status},update:{media:$.mediaInfo??void 0,status:$.status}}),$.shareLinkId)await g$.checkAndUpdateShareLinkStatus($.shareLinkId)}import{ApplicationFailure as zY}from"@temporalio/workflow";async function Y$($){let{getTranscodeWorkerQueueActivity:G,updateTaskStatusActivity:J}=l0(),Z=await r(V$,G);return await r(Z,J,{taskId:$.id,status:"processing"}),Z}async function P$($,G){let{getAssetActivity:J}=l0(),Z=await r($,J,G),X=Z?.storageKey?.key;if(!Z||!X)throw zY.create({message:"Asset not found or has no key",nonRetryable:!0});return{asset:Z,key:X}}async function J$($,G,J){let{updateTaskStatusActivity:Z}=l0();await r($,Z,{taskId:G,status:"completed",...J?{output:J}:{}})}async function H$($,G,J){let{updateTaskStatusActivity:Z}=l0();if($)await r($,Z,{taskId:G,status:"failed",output:{error:J instanceof Error?J.message:String(J)}})}async function s$($,G){if(G&&$){let{cleanupTmpDirActivity:J}=l0();try{await r($,J,{tmpDir:G})}catch(Z){console.error("Failed to cleanup tmp dir:",Z)}}}var VY={"2160p":3840,"1080p":1920,"720p":1280,"540p":960,"360p":640,"180p":320};function DX($,G,J){let Z=VY[$];if(!Z)return[0,0];let X,z;if(G>=J)X=Z,z=Math.round(X*(J/G));else z=Z,X=Math.round(z*(G/J));if(X%2!==0)X++;if(z%2!==0)z++;return[X,z]}var a$=[{name:"2160p",longSide:3840},{name:"1080p",longSide:1920},{name:"720p",longSide:1280},{name:"540p",longSide:960},{name:"360p",longSide:640}];function YY($,G){let J=Math.max($,G),Z=a$.filter((X)=>X.longSide<=J);if(Z.length>0)return Z.sort((X,z)=>z.longSide-X.longSide),Z[0];return a$[a$.length-1]}function jX($,G,J){let Z=["180p"],X=$,z=$;if(z==="single"||z==="disable")X="best_match";else if(z==="full")X="all";let V=YY(G,J);if(X==="best_match")Z.push(V.name);else if(X==="all"){let H=a$.findIndex((U)=>U.name===V.name);if(H!==-1)for(let U=H;U<a$.length;U++)Z.push(a$[U].name)}return Z}async function oG($){let G,J="";try{J=await Y$($);let{updateAssetStatusActivity:Z,getMediaInfoActivity:X,transcodeVideoActivity:z,transcodeAudioActivity:V,transcodeImageActivity:H,generateSpriteActivity:U,updateAssetMediaActivity:O,downloadMediaToTmpActivity:R,createEmbeddingTaskIfEnabledActivity:B,createAutofillTaskIfEnabledActivity:C}=l0();await r(J,Z,{assetId:$.assetId,status:"processing"});let{asset:j,key:A}=await P$(J,$.assetId),F=await r(J,R,{assetKey:A}),{filePath:y}=F;G=F.tmpDir;let b=$.payload?.transcode||{},m=j.mediaType?.startsWith("audio/")?"audio":"video",q=await r(J,X,{filePath:y,assetId:j.id,proxyType:m,mediaType:j.mediaType||""});q.original={key:A,filesizeInBytes:0,codec:""};let c=q.metadata;if(q.proxyType==="video"&&c){let L0=jX(b.videoStrategy||"best_match",c.originalWidth,c.originalHeight);for(let x0 of L0){let[W$,Z$]=DX(x0,c.originalWidth,c.originalHeight),N0=await r(J,z,{assetKey:A,filePath:y,videoSpec:{resolution:x0,width:W$,height:Z$},duration:c.duration,originalFps:c.frameRate,hardwareAcceleration:b.hardwareAcceleration,sourceVideoBitrate:c.videoBitRate||c.bitRate});if(x0==="180p")q.videoPreview=N0;else q.videoTranscodes.push(N0)}}if(q.proxyType==="audio"&&c){let L0=await r(J,V,{assetKey:A,filePath:y});q.videoTranscodes.push(L0)}if(b.thumbnail){let L0=await r(J,H,{assetKey:A,filePath:y,imageSpec:{width:300,height:300,quality:80,format:"webp",isPreview:!0}});q.thumbnail=L0}if(b.sprite||b.poster){let L0=A.lastIndexOf("/"),x0=L0===-1?"":A.substring(0,L0),W$={key:x0?`${x0}/sprite.webp`:"sprite.webp",frames:100,tileX:10,tileY:10},Z$={key:x0?`${x0}/poster.webp`:"poster.webp"},c0=await r(J,U,{assetKey:A,filePath:y,spriteSpec:W$,posterSpec:Z$,mediaInfo:q});q.sprite=c0.sprite,q.poster=c0.poster}await r(J,O,{assetId:j.id,mediaInfo:q}),await r(J,Z,{assetId:j.id,status:"processed"}),await r(J,B,{assetId:j.id,teamId:$.teamId,projectId:$.projectId}),await r(J,C,{assetId:j.id,teamId:$.teamId,projectId:$.projectId}),await J$(J,$.id)}catch(Z){throw console.error(`transcodeVideoWorkflow failed for task ${$.id}:`,Z),await H$(J,$.id,Z),Z}finally{await s$(J,G)}}async function iG($){let G,J="";try{J=await Y$($);let{updateAssetStatusActivity:Z,getMediaInfoActivity:X,transcodeImageActivity:z,updateAssetMediaActivity:V,downloadMediaToTmpActivity:H,createEmbeddingTaskIfEnabledActivity:U,createAutofillTaskIfEnabledActivity:O}=l0();await r(J,Z,{assetId:$.assetId,status:"processing"});let{asset:R,key:B}=await P$(J,$.assetId),C=await r(J,H,{assetKey:B}),{filePath:j}=C;G=C.tmpDir;let A=$.payload?.transcode||{},F=await r(J,X,{filePath:j,assetId:R.id,proxyType:"image",mediaType:R.mediaType||""});F.original={key:B,filesizeInBytes:0,codec:""};let y=F.metadata;if(F.proxyType==="image"&&y){let m={width:y.originalWidth,height:y.originalHeight,quality:90,format:"webp"},q=await r(J,z,{assetKey:B,filePath:j,imageSpec:m});F.imageTranscodes.push(q)}if(A.thumbnail){let m=await r(J,z,{assetKey:B,filePath:j,imageSpec:{width:300,height:300,quality:80,format:"webp",isPreview:!0}});F.thumbnail=m}await r(J,V,{assetId:R.id,mediaInfo:F}),await r(J,Z,{assetId:R.id,status:"processed"}),await r(J,U,{assetId:R.id,teamId:$.teamId,projectId:$.projectId}),await r(J,O,{assetId:R.id,teamId:$.teamId,projectId:$.projectId}),await J$(J,$.id)}catch(Z){throw console.error(`transcodeImageWorkflow failed for task ${$.id}:`,Z),await H$(J,$.id,Z),Z}finally{await s$(J,G)}}async function rG($){let G,J="";try{J=await Y$($);let{updateAssetStatusActivity:Z,getMediaInfoActivity:X,generateSpriteActivity:z,updateAssetMediaActivity:V,downloadMediaToTmpActivity:H,generatePdfProxyActivity:U,createEmbeddingTaskIfEnabledActivity:O,createAutofillTaskIfEnabledActivity:R}=l0();await r(J,Z,{assetId:$.assetId,status:"processing"});let{asset:B,key:C}=await P$(J,$.assetId),j=await r(J,H,{assetKey:C}),A=j.filePath;G=j.tmpDir;let F=await r(J,U,{assetId:B.id,assetKey:C,filePath:A,mediaType:B.mediaType||"",filename:B.name||""});A=F.pdfFilePath;let y=$.payload?.transcode||{},b=await r(J,X,{filePath:A,assetId:B.id,proxyType:"pdf",mediaType:B.mediaType||""});if(b.original={key:C,filesizeInBytes:0,codec:""},b.pdfTranscode={key:F.pdfProxyKey},y.sprite||y.poster){let m=C.lastIndexOf("/"),q=m===-1?"":C.substring(0,m),c={key:q?`${q}/sprite.webp`:"sprite.webp",frames:100,tileX:10,tileY:10},t={key:q?`${q}/poster.webp`:"poster.webp"},L0=await r(J,z,{assetKey:C,filePath:A,spriteSpec:c,posterSpec:t,mediaInfo:b});b.sprite=L0.sprite,b.poster=L0.poster}await r(J,V,{assetId:B.id,mediaInfo:b}),await r(J,Z,{assetId:B.id,status:"processed"}),await r(J,O,{assetId:B.id,teamId:$.teamId,projectId:$.projectId}),await r(J,R,{assetId:B.id,teamId:$.teamId,projectId:$.projectId}),await J$(J,$.id)}catch(Z){throw console.error(`transcodePdfWorkflow failed for task ${$.id}:`,Z),await H$(J,$.id,Z),Z}finally{await s$(J,G)}}import{ApplicationFailure as HY}from"@temporalio/workflow";async function sG($){let G="";try{G=await Y$($);let J=$.payload;if(!J?.pdfPages)throw HY.create({message:"Invalid payload for pdfPages task",nonRetryable:!0});let{asset:Z,key:X}=await P$(G,$.assetId),{renderPdfPagesActivity:z}=l0(),V=Z.media?.pdfTranscode?.key||X,H=await r(G,z,{assetKey:V,assetId:Z.id,start:J.pdfPages.start,end:J.pdfPages.end,commentTimestamp:J.pdfPages.commentTimestamp,annotations:J.pdfPages.annotations});await J$(G,$.id,{pages:H})}catch(J){throw console.error(`renderPdfPagesWorkflow failed for task ${$.id}:`,J),await H$(G,$.id,J),J}}import{ApplicationFailure as UY}from"@temporalio/workflow";async function aG($){let G="";try{G=await Y$($);let J=$.payload;if(!J?.screenshot)throw UY.create({message:"Invalid payload for screenshot task",nonRetryable:!0});let{asset:Z,key:X}=await P$(G,$.assetId),z=X;if(Z?.media){let U=Z.media;if(U.videoTranscodes&&U.videoTranscodes.length>0){let O=[...U.videoTranscodes].filter((R)=>R.key).sort((R,B)=>(B.height||0)-(R.height||0));if(O.length>0&&O[0].key)z=O[0].key}}let{takeScreenshotsActivity:V}=l0(),H=await r(G,V,{assetKey:z,assetId:Z.id,start:J.screenshot.start,end:J.screenshot.end,count:J.screenshot.count,commentTimestamp:J.screenshot.commentTimestamp,annotations:J.screenshot.annotations});await J$(G,$.id,{screenshots:H})}catch(J){throw console.error(`takeVideoScreenshotsWorkflow failed for task ${$.id}:`,J),await H$(G,$.id,J),J}}import{ApplicationFailure as LX}from"@temporalio/workflow";async function tG($){let G="";try{G=await Y$($);let J=$.payload;if(!J?.imageAnnotation)throw LX.create({message:"Invalid payload for imageAnnotation task",nonRetryable:!0});let{getAssetActivity:Z,overlayAnnotationsActivity:X}=l0(),z=await r(G,Z,$.assetId),V=z?.storageKey?.key;if(z?.media){let U=z.media;if(U.imageTranscodes&&U.imageTranscodes.length>0)V=U.imageTranscodes[0].key||V}if(!z||!V)throw LX.create({message:"Asset not found or has no key",nonRetryable:!0});let H=await r(G,X,{assetKey:V,assetId:z.id,annotations:J.imageAnnotation.annotations});await J$(G,$.id,{key:H})}catch(J){throw console.error(`overlayImageAnnotationWorkflow failed for task ${$.id}:`,J),await H$(G,$.id,J),J}}import{ApplicationFailure as oJ}from"@temporalio/workflow";async function eG($){let G="",J=$.payload?.watermark?.watermarkConfigId,Z=$.payload?.watermark?.shareLinkId;if(!J)throw oJ.create({message:"watermarkConfigId is required in task payload",nonRetryable:!0});try{G=await Y$($);let{initWatermarkFileActivity:X,waitForWatermarkFileActivity:z,transcodeWatermarkMediaActivity:V,completeWatermarkFileActivity:H}=l0(),U=await r(G,X,{assetId:$.assetId,watermarkConfigId:J});if(U.action==="completed"){if(Z)await r(G,H,{assetId:$.assetId,watermarkConfigId:J,status:"completed",shareLinkId:Z});await J$(G,$.id);return}if(U.action==="failed")throw oJ.create({message:"Watermark file generation failed in another task",nonRetryable:!0});if(U.action==="processing"){if((await r(G,z,{assetId:$.assetId,watermarkConfigId:J})).status==="completed"){if(Z)await r(G,H,{assetId:$.assetId,watermarkConfigId:J,status:"completed",shareLinkId:Z});await J$(G,$.id);return}throw oJ.create({message:"Watermark file generation failed in in-flight task",nonRetryable:!0})}let O=await r(G,V,{assetId:$.assetId,watermarkConfigId:J});await r(G,H,{assetId:$.assetId,watermarkConfigId:J,mediaInfo:O,status:"completed",shareLinkId:Z}),await J$(G,$.id)}catch(X){if(G&&J){let{completeWatermarkFileActivity:z}=l0();try{await r(G,z,{assetId:$.assetId,watermarkConfigId:J,status:"failed",shareLinkId:Z})}catch(V){console.error("Failed to update watermark file status to failed:",V)}}throw await H$(G,$.id,X),X}}async function CX($){let G=$.payload;if(G?.watermark||$.type==="transcode_watermark")return eG($);if(G?.pdfPages)return sG($);if(G?.screenshot)return aG($);if(G?.imageAnnotation)return tG($);if($.type==="transcode_image")return iG($);if($.type==="transcode_pdf")return rG($);return oG($)}class dG{db;assetId;teamId;projectId;spec={};constructor($,G,J,Z){this.db=$;this.assetId=G;this.teamId=J;this.projectId=Z}setStrategy($){return this.spec.videoStrategy=$,this}setHardwareAcceleration($){if($)this.spec.hardwareAcceleration=$;return this}withSprite(){return this.spec.sprite=!0,this}withPoster(){return this.spec.poster=!0,this}async submit(){return(await this.db.workflowTask.create({data:{assetId:this.assetId,teamId:this.teamId,projectId:this.projectId,type:B0.transcode_video,status:w0.pending,payload:{projectId:this.projectId,transcode:this.spec}}})).id}}class uJ{db;assetId;teamId;projectId;spec={};constructor($,G,J,Z){this.db=$;this.assetId=G;this.teamId=J;this.projectId=Z}withThumbnail(){return this.spec.thumbnail=!0,this}async submit(){return(await this.db.workflowTask.create({data:{assetId:this.assetId,teamId:this.teamId,projectId:this.projectId,type:B0.transcode_image,status:w0.pending,payload:{projectId:this.projectId,transcode:this.spec}}})).id}}class mJ{db;assetId;teamId;projectId;spec={};constructor($,G,J,Z){this.db=$;this.assetId=G;this.teamId=J;this.projectId=Z}withSprite(){return this.spec.sprite=!0,this}withPoster(){return this.spec.poster=!0,this}async submit(){return(await this.db.workflowTask.create({data:{assetId:this.assetId,teamId:this.teamId,projectId:this.projectId,type:B0.transcode_pdf,status:w0.pending,payload:{projectId:this.projectId,transcode:this.spec}}})).id}}function PX(){q$(B0.transcode,CX),q$(B0.transcode_video,oG),q$(B0.transcode_image,iG),q$(B0.transcode_pdf,rG),q$(B0.transcode_pdf_pages,sG),q$(B0.transcode_screenshot,aG),q$(B0.transcode_image_annotation,tG),q$(B0.transcode_watermark,eG),FJ(nJ),FJ(pJ)}import{spawn as OY}from"child_process";import{existsSync as e$,writeFileSync as TX,readFileSync as RG,unlinkSync as t$,mkdirSync as EX,statSync as AX,createReadStream as WY,openSync as KY}from"fs";import{join as MG}from"path";import{homedir as NY}from"os";var wX=MG(NY(),".shumai"),FX=MG(wX,"pids"),qX=MG(wX,"logs");function $J($){try{return process.kill($,0),!0}catch(G){if(G&&typeof G==="object"&&"code"in G&&G.code==="EPERM")return!0;return!1}}async function SX($,G){if(!e$(G))return console.log(`No running instance of ${$} found.`),!1;let J=parseInt(RG(G,"utf8").trim(),10);if(isNaN(J)){console.log(`Invalid PID found in ${G}. Cleaning up file.`);try{t$(G)}catch{}return!1}let Z=$J(J);if(!Z){console.log(`Process ${J} is not running. Cleaning up PID file.`);try{t$(G)}catch{}return!1}console.log(`Stopping ${$} (PID: ${J})...`);try{process.kill(J,"SIGTERM")}catch(X){return console.error(`Failed to send SIGTERM to process ${J}:`,X),!1}for(let X=0;X<30;X++){if(!$J(J)){Z=!1;break}await new Promise((z)=>setTimeout(z,100))}if(Z){console.log(`Process ${J} did not stop gracefully. Sending SIGKILL...`);try{process.kill(J,"SIGKILL")}catch(X){console.error(`Failed to send SIGKILL to process ${J}:`,X)}}try{t$(G)}catch{}return console.log(`Successfully stopped ${$}.`),!0}function _X($,G,J){if(e$(G)){let V=parseInt(RG(G,"utf8").trim(),10);if(!isNaN(V)&&V!==process.pid)if($J(V))console.error(`${$} is already running (PID: ${V}). Use '${$} stop' or '${$} restart'.`),process.exit(1);else try{t$(G)}catch{}}console.log(`Starting ${$} in background...`);let Z=KY(J,"w"),X=process.argv.slice(1).filter((V)=>V!=="-d"&&V!=="restart"),z=OY(process.argv[0],X,{detached:!0,stdio:["ignore",Z,Z],env:{...process.env,SHUMAI_DAEMONIZED:"true"}});if(z.pid===void 0)console.error(`Failed to spawn background process for ${$}.`),process.exit(1);z.unref(),TX(G,z.pid.toString(),"utf8"),console.log(`\uD83D\uDE80 Started ${$} in background (PID: ${z.pid}).`),console.log(`\uD83D\uDCC4 Logs are being written to ${J}`),process.exit(0)}function RY($,G){if(!e$(G))console.log(`No log file found for ${$}.`),process.exit(0);let X=RG(G,"utf8").split(`
|
|
1451
1451
|
`).slice(-100).join(`
|
|
1452
1452
|
`);process.stdout.write(X+`
|
|
1453
|
-
`);let z=AX(G).size,V=setInterval(()=>{try{if(e$(G)){let U=AX(G);if(U.size>z)WY(G,{start:z,end:U.size-1}).pipe(process.stdout,{end:!1}),z=U.size;else if(U.size<z)z=U.size}}catch{}},250),H=()=>{clearInterval(V),process.exit(0)};process.on("SIGINT",H),process.on("SIGTERM",H)}async function fX($,G){let J=MG(FX,`${$}.pid`),Z=MG(qX,`${$}.log`);EX(FX,{recursive:!0}),EX(qX,{recursive:!0});let X=process.argv.slice(2),z=X.includes("stop"),V=X.includes("restart"),H=X.includes("logs"),U=X.includes("-d")&&process.env.SHUMAI_DAEMONIZED!=="true";if(z)await SX($,J),process.exit(0);if(V)await SX($,J),await new Promise((B)=>setTimeout(B,500)),_X($,J,Z),process.exit(0);if(H)return RY($,Z),new Promise(()=>{});if(U)_X($,J,Z),process.exit(0);if(e$(J)){let B=parseInt(RG(J,"utf8").trim(),10);if(!isNaN(B)&&B!==process.pid)if($J(B))console.error(`${$} is already running (PID: ${B}). Use '${$} stop' or '${$} restart'.`),process.exit(1);else try{t$(J)}catch{}}TX(J,process.pid.toString(),"utf8");let O=()=>{try{if(e$(J)){let B=RG(J,"utf8").trim();if(parseInt(B,10)===process.pid)t$(J)}}catch{}};process.on("exit",O);let R=(B)=>{if(process.listenerCount(B)===1)process.exit(0)};process.on("SIGINT",()=>R("SIGINT")),process.on("SIGTERM",()=>R("SIGTERM")),await G()}NZ(process.cwd(),!1);if(process.argv.includes("--check"))console.log("\u2705 Transcode worker evaluated successfully!"),process.exit(0);async function MY(){PX(),console.log("\uD83D\uDE80 Starting Transcode Worker...");let $={};{let{default:G}=await import("./chunk-
|
|
1453
|
+
`);let z=AX(G).size,V=setInterval(()=>{try{if(e$(G)){let U=AX(G);if(U.size>z)WY(G,{start:z,end:U.size-1}).pipe(process.stdout,{end:!1}),z=U.size;else if(U.size<z)z=U.size}}catch{}},250),H=()=>{clearInterval(V),process.exit(0)};process.on("SIGINT",H),process.on("SIGTERM",H)}async function fX($,G){let J=MG(FX,`${$}.pid`),Z=MG(qX,`${$}.log`);EX(FX,{recursive:!0}),EX(qX,{recursive:!0});let X=process.argv.slice(2),z=X.includes("stop"),V=X.includes("restart"),H=X.includes("logs"),U=X.includes("-d")&&process.env.SHUMAI_DAEMONIZED!=="true";if(z)await SX($,J),process.exit(0);if(V)await SX($,J),await new Promise((B)=>setTimeout(B,500)),_X($,J,Z),process.exit(0);if(H)return RY($,Z),new Promise(()=>{});if(U)_X($,J,Z),process.exit(0);if(e$(J)){let B=parseInt(RG(J,"utf8").trim(),10);if(!isNaN(B)&&B!==process.pid)if($J(B))console.error(`${$} is already running (PID: ${B}). Use '${$} stop' or '${$} restart'.`),process.exit(1);else try{t$(J)}catch{}}TX(J,process.pid.toString(),"utf8");let O=()=>{try{if(e$(J)){let B=RG(J,"utf8").trim();if(parseInt(B,10)===process.pid)t$(J)}}catch{}};process.on("exit",O);let R=(B)=>{if(process.listenerCount(B)===1)process.exit(0)};process.on("SIGINT",()=>R("SIGINT")),process.on("SIGTERM",()=>R("SIGTERM")),await G()}NZ(process.cwd(),!1);if(process.argv.includes("--check"))console.log("\u2705 Transcode worker evaluated successfully!"),process.exit(0);async function MY(){PX(),console.log("\uD83D\uDE80 Starting Transcode Worker...");let $={};{let{default:G}=await import("./chunk-5zfab4vj.js");$.workflowBundle=G}await qJ.startWorkers(V$,$)}fX("shumai-transcode",MY).catch(($)=>{console.error($),process.exit(1)});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shumai-one/shumai-transcode",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Media transcoding worker for the shumai media workspace",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"zod": "4.4.3"
|
|
28
28
|
},
|
|
29
29
|
"optionalDependencies": {
|
|
30
|
-
"@shumai-one/shumai-transcode-darwin-arm64": "0.4.
|
|
31
|
-
"@shumai-one/shumai-transcode-darwin-x64": "0.4.
|
|
32
|
-
"@shumai-one/shumai-transcode-linux-arm64": "0.4.
|
|
33
|
-
"@shumai-one/shumai-transcode-linux-x64": "0.4.
|
|
34
|
-
"@shumai-one/shumai-transcode-win32-arm64": "0.4.
|
|
35
|
-
"@shumai-one/shumai-transcode-win32-x64": "0.4.
|
|
30
|
+
"@shumai-one/shumai-transcode-darwin-arm64": "0.4.2",
|
|
31
|
+
"@shumai-one/shumai-transcode-darwin-x64": "0.4.2",
|
|
32
|
+
"@shumai-one/shumai-transcode-linux-arm64": "0.4.2",
|
|
33
|
+
"@shumai-one/shumai-transcode-linux-x64": "0.4.2",
|
|
34
|
+
"@shumai-one/shumai-transcode-win32-arm64": "0.4.2",
|
|
35
|
+
"@shumai-one/shumai-transcode-win32-x64": "0.4.2"
|
|
36
36
|
},
|
|
37
37
|
"repository": {
|
|
38
38
|
"type": "git",
|