
    uiN                        U d dl mZmZmZmZmZ d dlZd dlZd dlZd dl	Z	d dl
Z
d dlZd dlZd dlZd dlmZ d dlmZ d dlmZ  ee      Z ed      Z ed      Z ed      Z ed	      Z ed
      Zh dZej7                  dd       ej7                  dd       ej7                  dd       defdZd@dedefdZdededefdZ dede!fdZ"defdZ#dededefdZ$ G d d      Z% e%d      Z& e'       Z(e'e   e)d <    ejT                         Z+d!Z,d"e-eef   fd#Z.ej_                  d$      d%        Z0ej_                  d&      d'        Z1ej_                  d(      d)        Z2ej_                  d*d+g,      d-        Z3ej_                  d.      d/        Z4ej_                  d0      d1        Z5ej_                  d2      d3        Z6ej_                  d4d+g,      d5        Z7ej_                  d6      d7        Z8ej_                  d8d+g,      d9        Z9ej_                  d:      d;        Z:ed<k(  rejw                  d=d>d?       yy)A    )Flaskrequest	send_filerender_template_stringjsonifyN)datetime)Path)Anyz/var/project/videos/drigez/tmp/thumbsz/var/www/project/cortesz/var/www/project/snapshotsz/tmp/video_queue.json>   .avi.mkv.mov.mp4Tparentsexist_okreturnc                  J    t        j                         j                  d      S )Nseconds)timespec)r   now	isoformat     -/var/project/videos/drige/studio_mobile_v4.pynow_isor      s    <<>##Y#77r   messagestatusc                      t        d| i      |fS )Nerror)r   )r   r   s     r   r   r   !   s    GW%&..r   basepartsc                     | t        | z  j                         }| j                         }t        |      j                  t        |      t        j
                  z         s||k7  rt        d      |S )NCaminho invalido)r	   resolvestr
startswithossep
ValueError)r    r!   	candidatebase_resolveds       r   secure_subpathr,   %   s^    e$--/ILLNMy>$$S%7"&&%@AiS`F`+,,r   valuec                 \    t        | t              r| S t        |       j                         dv S )N>   1onyestrue)
isinstanceboolr%   lower)r-   s    r   
parse_boolr6   -   s*    %u:!;;;r   c                     | j                         sg S t        | j                         D cg c]  }|j                         s|j                  ! c}      S c c}w N)existssortediterdiris_dirname)r    ds     r   list_subdirsr?   3   s;    ;;=	4<<>@aQXXZ166@AA@s   A Arawfallbackc                 `    dj                  d | D              j                         }|xs |d d S )N c              3   J   K   | ]  }|j                         s|d v s|  yw)z._- N)isalnum).0cs     r   	<genexpr>z sanitize_name.<locals>.<genexpr>:   s     CA		qF{aCs   ##x   )joinstrip)r@   rA   cleaneds      r   sanitize_namerM   9   s1    ggCCCIIKGx#&&r   c                   ^    e Zd ZddefdZd Zd Zd Zd Zde	de
e	ef   fd	Zd
 Zde	fdZy)ConversionQueuemax_workersc                 >   t        j                         | _         i | _        i | _        i | _        || _        t        j                         | _        | j                          t        |      D ]1  }t        j                  | j                  d      j                          3 y )NTtargetdaemon)queueQueuejobscompleted_jobsfailed_jobsrP   	threadingLocklock
load_staterangeThreadworkerstart)selfrP   _s      r   __init__zConversionQueue.__init__?   sy    [[]
/1	9;68&NN$	{# 	FADKK=CCE	Fr   c                 H   t         j                         sy 	 t         j                  dd      5 }t        j                  |      }d d d        j                  di       | _        |j                  di       | _        y # 1 sw Y   8xY w# t        $ r i | _        i | _        Y y w xY w)Nrutf-8encoding	completedfailed)	
QUEUE_FILEr9   openjsonloadgetrX   rY   	Exception)rb   fdatas      r   r]   zConversionQueue.load_stateJ   s      "	"w7 $1yy|$"&((;";D#xx"5D$ $  	""$D!D	"s(   B A;6B ;B B B! B!c                    | j                   | j                  d}t        j                  d      }|j	                  dd      5 }t        j                  ||d       d d d        t        j                  |t               y # 1 sw Y   $xY w)N)rj   rk   z.tmpwrg   rh   F)ensure_ascii)	rX   rY   rl   with_suffixrm   rn   dumpr'   replace)rb   payloadtmprr   s       r   
save_statezConversionQueue.save_stateW   sm     $ 3 3t?O?OP$$V,XXcGX, 	6IIgqu5	6


3
#	6 	6s   A>>Bc                     | j                   5  i | _        i | _        | j                          d d d        y # 1 sw Y   y xY wr8   )r\   rX   rY   r|   )rb   s    r   clear_historyzConversionQueue.clear_history^   s8    YY 	"$D!DOO	 	 	s   5>c                    | j                   5  t        | j                  j                               }|D cg c]  }|d   dk(  s| }}|D cg c]  }|d   dk(  s| }}t        | j                  j                               d d d   }t        | j
                  j                               d d d   }||||dcd d d        S c c}w c c}w # 1 sw Y   y xY w)Nr   queued
processing)r   r   rj   rk   )r\   listrW   valuesrX   rY   )rb   rW   jr   r   rj   rk   s          r   get_all_statuszConversionQueue.get_all_statusd   s    YY 			((*+D!%AA8)@aAFA%)IQx[L-H!IJIT00779:4R4@I$**1134TrT:F (& 		 	AI	 	s5   (CCCCCCAC
CCjob_idjob_datac                     | j                   5  t        |      }||d<   d|d<   d|d<   t               |d<   || j                  |<   | j                  j                  |       d d d        |S # 1 sw Y   |S xY w)Nidr   r   r   progress
created_at)r\   dictr   rW   rU   put)rb   r   r   rz   s       r   add_jobzConversionQueue.add_jobr   sw    YY 	#8nG"GDM (GH"#GJ$+IGL! 'DIIfJJNN6"	# 	# s   AA))A3c                    	 | j                   j                         }|y 	 | j                  5  | j                  j                  |      }|s$	 d d d        | j                   j	                          md|d<   d d d        | j                  |       | j                  5  | j                  j                  |d       }|r1d|d<   t               |d<   || j                  |<   | j                          d d d        | j                   j	                          
# 1 sw Y   xY w# 1 sw Y   1xY w# t        $ r}| j                  5  | j                  j                  |d|i      }d|d<   t               |d<   t        |      |d<   || j                  |<   | j                          d d d        n# 1 sw Y   nxY wY d }~d }~ww xY w# | j                   j	                          w xY w)Nr   r   rj   finished_atr   rk   r   )rU   rp   r\   rW   	task_doneprocess_conversionpopr   rX   r|   rq   r%   rY   )rb   r   jobexcs       r   r`   zConversionQueue.worker}   s   ZZ^^%F~'YY 1))--/C 1, 

$$&% %1CM	1
 ''/YY *))--5C(3H-4YM*69++F3)*  

$$&7 
1 1* *  &YY &))--v?C$,CM)0C&#&s8CL/2D$$V,OO%& & && 

$$&s~   D$ DD$ .D3%D$ AD(D$ DD$ D!D$ $	F6-F19AF 	F1 F)	%F1,F9 1F66F9 9Gc                 &   | j                   5  | j                  |   }d d d        t        t        d   |d         }|j	                         st        d      |j                  d      st        nt        t        |d         }|j                  dd       t        |j                  d      xs dd	|d d
        }|| dz  }ddddddt        |d         dt        |d         dt        |      g}g }|j                  d      dk(  r|j                  d       |r"|j                  ddj                  |      g       |j                  g d       |j                  d|j                  d      dk(  rdndg       |j                  d       r|j                  d!       n|j                  g d"       |j                  d#d$t        |      g       t        j                  |t        j                   t        j                   dd%&      }		 	 |	j"                  r|	j"                  j%                         nd}
|
snd'|
v rt'        j(                  d(|
      }|rpt+        |j-                  d%            d)z  }t/        t+        ||d   z  d*z        d*      }| j                   5  || j                  v r|| j                  |   d+<   d d d        |	j1                         \  }}|	j"                  r|	j"                  j3                          |	j4                  r|	j4                  j3                          	 |	j6                  d,k7  r#t9        d-|xs dj;                         d.d         | j                   5  || j                  v r-t        |      | j                  |   d/<   d*| j                  |   d+<   d d d        y # 1 sw Y   xY w# 1 sw Y   xY w# |	j"                  r|	j"                  j3                          |	j4                  r|	j4                  j3                          w w xY w# 1 sw Y   y xY w)0NpastafileArquivo fonte nao encontradopasta_corteTr   custom_namerC   cut_   r   ffmpeg-yz-nostdinz	-progresszpipe:1-ssra   z-tduration-imodetiktokzcrop=ih*(9/16):ih-vf,)z-c:vlibx264z-preset	ultrafastz-crfwhatsapp2822mutez-an)z-c:aaacz-b:a128kz	-movflagsz
+faststart   )stdoutstderrtextbufsizeout_time_mszout_time_ms=(\d+)g    .Ad   r   r   zErro FFmpeg: ioutput_path)r\   rW   r,   	VIDEO_DIRr9   FileNotFoundErrorrp   CUT_DIRmkdirrM   r%   appendextendrJ   
subprocessPopenPIPEr   readlineresearchintgroupmincommunicatecloser   
returncodeRuntimeErrorrK   )rb   r   r   src_filedest_dir	safe_namer   cmd
vf_filtersprocesslinematch	current_sr   rc   r   s                   r   r   z"ConversionQueue.process_conversion   s   YY 	$))F#C	$ ")S\3v;G #$BCC"%''-"87nWVYZgVh>itd3!#''-"8">B$vbqzl@ST	I;d!33 GJ M
 
776?h&12JJsxx
345

>?

FCGGFOz$ADtLM776?JJuJJ67

Ks;/?@A""????
	'4;NNw~~..0 D(II&:DAE$'A$7+$E	#&sIJ,G3+N'OQT#U!YY I%2@H		& 1* =I   ++-IAv~~$$&~~$$&""/C/C/Ede/L.MNOOYY 	4"36{3C		&!-003		&!*-	4 	4W	$ 	$|I I
 ~~$$&~~$$& 	4 	4s=   N BN5 !N)0N5 <PN&)N2.N5 5APPN)   )__name__
__module____qualname__r   rd   r]   r|   r~   r   r%   r   r
   r   r`   r   r   r   r   rO   rO   >   sR    	FC 	F"$	c 	T#s(^ 	'<O4 O4r   rO   r   )rP   thumb_generation_guarda  
<!DOCTYPE html>
<html lang="pt-br">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>Studio Mobile V4</title>
  <style>
    body { font-family: sans-serif; max-width: 900px; margin: 20px auto; padding: 0 12px; }
    .row { display: flex; gap: 8px; margin-bottom: 10px; flex-wrap: wrap; }
    input, select, button { padding: 8px; }
    #queueList div { border: 1px solid #ddd; padding: 6px; margin-bottom: 6px; }
  </style>
</head>
<body>
  <h2>Studio Mobile V4</h2>
  <div class="row">
    <select id="pasta">{% for p in pastas %}<option value="{{p}}">{{p}}</option>{% endfor %}</select>
    <select id="videoSelect"></select>
  </div>
  <div class="row">
    <input id="start" type="number" min="0" value="0" />
    <input id="duration" type="number" min="1" value="30" />
    <input id="customName" type="text" placeholder="Nome do corte" />
  </div>
  <div class="row">
    <select id="mode">
      <option value="normal">normal</option>
      <option value="tiktok">tiktok</option>
      <option value="whatsapp">whatsapp</option>
    </select>
    <label><input id="mute" type="checkbox" /> sem audio</label>
    <select id="pastaCorte"><option value="">Raiz</option>{% for pc in pastas_corte %}<option value="{{pc}}">{{pc}}</option>{% endfor %}</select>
    <button onclick="addQueue()">Adicionar fila</button>
  </div>
  <h3>Fila</h3>
  <div id="queueList"></div>
<script>
async function loadVideos() {
  const pasta = document.getElementById('pasta').value;
  const res = await fetch(`/videos_list?pasta=${encodeURIComponent(pasta)}`);
  const list = await res.json();
  const sel = document.getElementById('videoSelect');
  sel.innerHTML = list.map(v => `<option value="${v}">${v}</option>`).join('');
}

async function addQueue() {
  const body = {
    pasta: document.getElementById('pasta').value,
    file: document.getElementById('videoSelect').value,
    start: Number(document.getElementById('start').value || 0),
    duration: Number(document.getElementById('duration').value || 30),
    pasta_corte: document.getElementById('pastaCorte').value,
    mode: document.getElementById('mode').value,
    mute: document.getElementById('mute').checked,
    custom_name: document.getElementById('customName').value,
  };
  const res = await fetch('/add_to_queue', {method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(body)});
  if (!res.ok) {
    const e = await res.json();
    alert(e.error || 'erro');
  }
}

setInterval(async () => {
  const res = await fetch('/queue_status');
  if (!res.ok) return;
  const data = await res.json();
  const all = [...data.processing, ...data.queued, ...data.completed, ...data.failed];
  document.getElementById('queueList').innerHTML = all.map(j => `<div>${j.status} - ${j.file || j.id} (${j.progress || 0}%) ${j.status==='completed' ? `<a href="/download_job/${j.id}">download</a>` : ''}</div>`).join('');
}, 1200);

window.onload = loadVideos;
document.getElementById('pasta').addEventListener('change', loadVideos);
</script>
</body>
</html>
rs   c                    h d}|D cg c]	  }|| vs| }}|rt        ddj                  |             t        | d         j                         }t        | d         j                         }|rd|v sd|v rt        d      |st        d	      t	        |      j
                  j                         }|t        vrt        d
      t        | d         }t        | d         }|dk  rt        d      |dk  s|dkD  rt        d      t        | j                  dd            j                         j                         }	|	dvrt        d      t        | j                  dd            j                         }
|
rd|
v sd|
v rt        d      |||||
|	t        | j                  dd            t        | j                  dd            j                         dS c c}w )N>   r   r   ra   r   zCampos obrigatorios ausentes: z, r   r   /\zPasta invalidazArquivo invalidoz!Extensao de arquivo nao permitidara   r   r   zInicio deve ser >= 0i`T  zDuracao invalidar   normal>   r   r   r   zMode invalidor   rC   zDestino invalidor   Fr   )r   r   ra   r   r   r   r   r   )r)   rJ   r%   rK   r	   suffixr5   ALLOWED_VIDEO_EXTfloatrp   r6   )rs   requiredkmissingr   	file_nameextra   r   r   r   s              r   validate_video_payloadr   C  s   5H"4Qatmq4G49$))G:L9MNOOW$$&EDL!'')IC5LDEM)**+,,
y/
 
 
&
&
(C
##<==$w- ET*%&Hqy/001};.+,,txx)*00288:D33))dhh}b1288:K{*dk.A+,, "488FE23488M267==?	 	E 5s
   	GGr   c                  b    t        t              } t        t              }t        t        | |      S )Npastaspastas_corte)r?   r   r   r   TEMPLATEr   s     r   indexr   u  s%    )$F(L!(6UUr   z/videos_listc                     t         j                  j                  d      xs dj                         } | st	        g       S 	 t        t        |       }|j                         r|j                         st	        g       S |j                         D cg c]@  }|j                         s|j                  j                         t        v s5|j                  B }}t	        t!        |            S # t        $ r t	        g       cY S w xY wc c}w )Nr   rC   )r   argsrp   rK   r   r,   r   r)   r9   r<   r;   is_filer   r5   r   r=   r:   )r   dir_pathrr   videoss       r   videos_listr   |  s    \\g&,"335Er{!)U3 ??HOO$5r{ !((*aiikahhnn>NRc>cF  6&>""  r{s$    C( D# DD(C?>C?z/videoc                     t         j                  j                  d      xs dj                         } t         j                  j                  d      xs dj                         }| r|st	        dd      S 	 t        t        | |      }|j                         r|j                         st	        dd      S t        |      S # t        $ r t	        dd      cY S w xY w)	Nr   rC   r   zParametros invalidos  r#   Arquivo nao encontrado  )r   r   rp   rK   r   r,   r   r)   r9   r   r   )r   r   paths      r   video_streamr     s    \\g&,"335E!!&)/R668I	+S11.i	: ;;=-s33T?  .'--.s   4B< <CCz/take_snapshotPOST)methodsc                     t        j                  d      xs i } 	 t        | j                  dd            j	                         }t        | j                  dd            j	                         }t        | j                  dd            }|dk  rt        d      t        t        ||      }|j                         st        d	d
      S dt        t        j                                dt        j                         j                  d d  d}t         |z  }t#        j$                  dddt        |      dt        |      ddddt        |      gt"        j&                  t"        j&                        }|j(                  dk7  rt        dd      S t+        d|d      S # t        $ r}t        t        |      d      cY d }~S d }~ww xY w)NTsilentr   rC   r   timer   ztime invalidor   r   snap_rc      .jpgr   r   r   r   	-frames:vr/   -q:v2)r   r   zFalha ao gerar snapshoti  )successr=   r   )r   get_jsonr%   rp   rK   r   r)   r,   r   r9   r   r   r   uuiduuid4hexSNAPSHOT_DIRr   runDEVNULLr   r   )	rs   r   r   atsrcr=   outprocr   s	            r   take_snapshotr    s   4(.BD$$DHHWb)*002,-335	488FA&'6_--Yy9zz|1377s499;'($**,*:*:2A*>)?tDT!~~BCC %%%%
" ??a2C884677 $SXs##$s+   B)F C F F 	F=F82F=8F=z/thumbsc                     t         j                  j                  d      xs dj                         } t         j                  j                  d      xs dj                         }t         j                  j                  dd      }	 t	        |      dk  sd	kD  rt        d
d      S 	 t        t        ||       j                         st        dd      S t        j                  t        j                  | d|  d       j                  t        z  j                  dd       t         5  t"        v rt%        dd      cd d d        S t"        j'                         d d d        fd}t)        j*                  |d      j-                          t%        dd      S # t
        $ r t        dd      cY S w xY w# t
        $ r t        dd      cY S w xY w# 1 sw Y   zxY w)Nr   rC   r   step60zstep invalidor   
   iX  zstep fora do intervalor#   r   r   r   :Tr   already_running)r   vid_idc                  T   	 t        j                  dddddddt              gd	      j                         } t	        t        |             }t        d
t        |d            D ]\  }d|ddz  }|j                         rt        j                  dddt        |      dt              ddddddt        |      ddg       ^ 	 t        5  t        j                         d d d        y # 1 sw Y   y xY w# t        5  t        j                         d d d        w # 1 sw Y   w xY wxY w)Nffprobez-v0z-show_entrieszformat=durationz-ofzdefault=nw=1:nk=1T)r   r   r   f_05dr   r   r   r   r   r  r/   r  8r   zscale=320:-1z	-loglevelquiet)r   check_outputr%   rK   r   r   r^   maxr9   r
  thumb_generation_lockr   discard)dur_rawr   tr  out_dirr  step_intr  s       r   r`   zgenerate_thumbs.<locals>.worker  s2   )	7 --#%'H	  eg  5>*H1c(A.9 "QsG4 00::< AC#&C#	0 ' 7&..v67 7 7& 7&..v67 7 7s0   C C5 
C))C25D'<D	D'D$ D'rR   ok)r   r   rp   rK   r   r)   r   r,   r   r9   r  uuid5NAMESPACE_URLr  
TMP_THUMBSr   r!  r   r   addrZ   r_   ra   )r   r   r  r`   r%  r  r&  r  s       @@@@r   generate_thumbsr,    s   !!&)/R668I\\g&,"335E<<FD)D+t9 "}3-s33.Yy9 ::<-s33ZZ**ugQyk8*,MNRRF6!GMM$M.	 +++&76JK+ + 	""6*+
*7X F40668df566I  +_c**+  .'--.+ +s6   F' *G /GG'F?>F?GGG&z/thumbs_listc                  b   t         j                  j                  d      xs dj                         } t         j                  j                  d      xs dj                         }t         j                  j                  dd      }	 t	        |      }t        j                  t        j                  |  d| d|       j                  }t        |z  }|j                         st        g       S g }t        |j                               D ]v  }|j                  j!                  d      r|j                  j#                  d	      s:	 t	        |j                  d
d       }|j%                  |d| d|j                   d       x t        |      S # t
        $ r t        g       cY S w xY w# t
        $ r Y w xY w)Nr   rC   r   r  r  r   r  r  r         z/thumb/)secr  )r   r   rp   rK   r   r)   r   r  r(  r)  r  r*  r9   r:   r;   r=   r&   endswithr   )	r   r   r  r&  r  r%  itemsrr   r0  s	            r   thumbs_listr3    st   \\g&,"335E!!&)/R668I<<FD)Dt9 ZZ**ugQyk8*,MNRRF6!G>>r{EGOO%& Gvv  &affoof.E	affQqk"C 	S76(!AFF8)DEFG 5>%  r{  		s$   F ?F"FF"	F.-F.z/thumb/<vid>/<name>c                     	 t        t        | |      }|j	                         r|j                         st        dd      S t        |      S # t        $ r t        dd      cY S w xY w)Nr#   r   zThumb nao encontradar   )r,   r*  r)   r   r9   r   r   )vidr=   r   s      r   serve_thumbr6  8  s_    .j#t4 ;;=+S11T?  .'--.s   A
 
A"!A"z/add_to_queuec                     t        j                  d      } t        | t              st	        dd      S 	 t        |       }t        t        |d   |d         }|j                         r|j                         st	        dd      S 	 t        j                         j                  }t        j!                  ||       t#        d	|i      S # t        $ r}t	        t        |      d      cY d }~S d }~ww xY w)
NTr   zJSON invalidor   r   r   r   r   r   )r   r  r3   r   r   r   r,   r   r9   r   r)   r%   r  r  r  conversion_queuer   r   )rs   	validatedr  r   r   s        r   add_to_queuer:  E  s    4(DdD!_c**$*40	Y	'(:If<MNzz|3;;=7== $1
 ZZ\FVY/D&>""  $SXs##$s   AC 	C,C'!C,'C,z/queue_statusc                  <    t        t        j                               S r8   )r   r8  r   r   r   r   queue_statusr<  X  s    #22455r   z/clear_queuec                  D    t         j                          t        ddi      S )Nr  T)r8  r~   r   r   r   r   clear_queuer>  ]  s    ""$It$%%r   z/download_job/<job_id>c                     t         j                  j                  |       }|st        dd      S t	        |j                  dd            }|j                         st        dd      S t        |d      S )NzJob nao encontrador   r   rC   zArquivo de saida nao encontradoT)as_attachment)r8  rX   rp   r   r	   r9   r   )r   r   r   s      r   download_jobrA  c  se    

)
)
-
-f
5C)3//sww}b12K6<<[55r   __main__z0.0.0.0i  )threaded)r   )<flaskr   r   r   r   r   r   r'   r  rn   r   rZ   rU   r   r   pathlibr	   typingr
   r   appr   r*  r   r	  rl   r   r   r%   r   r   r   r,   r4   r6   r?   rM   rO   r8  setr   __annotations__r[   r!  r   r   r   router   r   r   r  r,  r3  r6  r:  r<  r>  rA  r
  r   r   r   <module>rK     s   L L  	   	      Ho ,-	- 

(
)01)*
4  
    - dT *   4$  /8 8/3 / / s t <c <d <Bt B's 'c 'c '
l4 l4^ #q1 #&5 C (&	( M`-c3h -d 3V V ># #& 8 " fX.&$ /&$R 9K7 K7\ > 8  !	 "	 ?VH-# .#$ ?6 6 >F8,& -&
 #$	6 %	6 zGGItdG+ r   