
    hgT                     t   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Zd dl	Z	d dl
mZ d dlmZ d dlmZ d dlZd dlZd dlZd dlZd dlmZmZ d dlmZ d dlZej4                  j7                         j9                  d      j;                  d      Z ej>                  d	e
      Z dZ!dZ"dZ# ejH                          d6de%de%de%fdZ&d Z'dede%fdZ(de%de%de%fdZ)de%de%de%fdZ*dZ+de%fdZ,de%de%fdZ-d7de%de.d e%fd!Z/d"ej`                  d#e1dej`                  fd$Z2	 d8d%Z3d&e%d'e%d(e%d)e%d*e4f
d+Z5d,e6de%d'e%d(e%d-ee%   d e%fd.Z7e jq                  ejr                  ju                  d/      ejr                  ju                  d0      g1       ejv                  d23      	 	 	 	 d9de%d4e1d e%d-e%fd5              Z<y):    N)SequenceMatcher)Path)List)AudioFileClipVideoFileClip)	YoutubeDLzpyproject.tomlffmpegzsongify-a-video-app)nameimagesuno-data-uploadsz#https://studio-api.staging.suno.com   	file_paths3_file_namereturnc                    t        j                  dt        j                  d      t        j                  d            }d}d| }	 |j	                  | ||       d| }|S # t
        $ r}t        dt        |             d }~ww xY w)	Ns3AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY)aws_access_key_idaws_secret_access_keyr   zstudio/uploads/https://cdn1.suno.ai/zFailed to upload file to S3: )boto3clientosgetenvupload_file	ExceptionRuntimeErrorstr)r   r   	s3_clientbuckets3_keys3_urles          ./Users/jason/Desktop/vidmaker/modal/songify.pyupload_video_to_s3r&   +   s    ))$78 ii(?@I
 !F|n-F	Ei8 )7 E:3q6(CDDEs   A! !	B*BBc                  V    t        j                  d      } | st        d      d|  ddS )N
SUNO_TOKENzSUNO_TOKEN env var missingzBearer zapplication/json)AuthorizationContent-Type)r   r   r   )tokens    r%   _headersr,   @   s2    IIl#E788&ug.@RSS    
audio_pathc                    | j                   dd}t        j                  t         d|t	                     }|j
                  st        d|j                         |j                         }|j                  d      xs |j                  d      }d|v r||d	   }|d   }t        | d
      5 }d| j                   ||j                  dd      fi}t        j                  |||      }d d d        |j
                  s|t        d|j                         |j                  d      }	t        | d
      5 }t        j                  |	|ddi      }d d d        |j
                  st        d|j                         d| j                   |j                  di       j                  dd| d      d}
t        j                  t         d| d|
t	                     }|j
                  st        d|j                         t        j                         }	 t        j                  t         d| t	                     }|j
                  st        d|j                         |j                         }|j                  dd      }|dk(  s|dk(  rn;t        j                         |z
  d kD  rt        d!      t        j                  d"       |dk(  rt        d#|       t        j                  t         d| d$i t	                     }|j
                  st        d%|j                         |j                         }|j                  d&      xs |j                  d      }|st        d'      |S # 1 sw Y   xY w# 1 sw Y   *xY w)(Nz	audio/wav)filenamecontent_typez/api/uploads/audiojsonheaderszUpload reservation failed: id	upload_idfieldsurlrbfiler*   z
audio/mpeg)datafileszFile upload failed: 
upload_url)r;   r4   audiokeyzraw_uploads/.mp3)upload_typeupload_filename
upload_keyz/api/uploads/audio/z/upload-finishzUpload finish failed: r4   Status poll failed: statusunknowncompleteerror   zUpload processing timed out   zUpload processing failed: z/initialize-clipzClip initialization failed: clip_idz'No clip ID returned from initialization)r
   requestspostAPI_BASEr,   okr   textr3   getopenputtimeTimeoutErrorsleep)r.   payloadrupload_datar6   r8   r7   fr<   presigned_urlfinish_payload
poll_startstatus_datarF   	clip_datarL   s                   r%   upload_audiora   G   sD   %??KHG
"45GXZXA448ABB&&(K%E)EI ;% X&*d# 	=q!VZZ-UVE ce<A		= tt!5affX>?? $5*d# 	qA/LA	
 tt!5affX>?? %??!ooh377\)D1
N 	*'	{.A
	A 443AFF8<== J
LLj+I;7
 tt!5affX>??ffh95Z6W#499;#c)<==

1# & 7}EFF 	*'	{2BC
	A 449!&&BCCImmI&=)--*=GDEEN_	= 	=	 	s   ):M",M/"M,/M9r8   out_dirc                 \   t        j                  |      }|j                  dd       t        |dz        }|dddd}t	        |      5 }|j                  | d      }t        t        j                  |j                  |            j                  d            cd d d        S # 1 sw Y   y xY w)NT)parentsexist_okz%(id)s.%(ext)szmp4/best)outtmplformatquietno_warnings)download.mp4)pathlibr   mkdirr   r   extract_infoprepare_filenamewith_suffix)r8   rb   tmplydl_optsydlinfos         r%   download_videoru      s    ll7#GMM$M.w))*D	H 
8	 Qd37<< 4 4T :;GGOPQ Q Qs   	AB""B+
video_pathc                     t        t        j                               }ddd| dddddd	t        | d
| d      g}t        j                  |dt        j
                  t        j
                         t        | d
| d      S )Nr	   z-yz-iz-ac1z-ar16000z-c:a	pcm_s16le/z.wavT)checkstdoutstderr)r   uuiduuid4
subprocessrunPIPEr   )rv   rb   r5   cmds       r%   extract_audior      s    	TZZ\	BwiqD!"C NN3d:??:??S7)1RD%&&r-   2   rL   c                 r   t        j                          }d}|sCt        j                  t         d|  dt	                     j                         }	 |d   r|S 	 |sC|rt        y # t        $ rH}t        |       t        j                  d       t        j                          |z
  t        kD  }Y d }~Xd }~ww xY w)NF	/api/gen/z/aligned_lyrics/v2/rD   aligned_lyrics      ?)rU   rM   rR   rO   r,   r3   r   printrW   TIMEOUTrV   )rL   timer
is_timeoutlyricsr$   s        r%   
get_lyricsr      s    IIKEJ!j	'*=>


$& 		9&' ( "  	  	9!HJJsO))+-8J	9s   A% %	B6.>B11B6style_genrec                     i ddddddddddd	d
dd
dddddddddddddddddd}| j                         j                         }||v r||   S d|  d|  dS )z
    Generate detailed tags that explicitly mention vocals and describe the style

    Args:
        style_genre: Basic genre like "drum and bass", "house music", etc.

    Returns:
        Detailed tag description mentioning vocals
    zdrum and bassa	  This drum n bass cover launches straight into rapid-fire percussion and a driving bassline and clear vocals from the first second. Syncopated synth stabs and crisp hi-hats layer with energetic vocals, while doubled harmonies and subtle FX sweeps keep momentum high.zdrum n basszhouse musica  This house music cover features a four-on-the-floor beat with clear vocals prominently mixed. Deep basslines and warm synth pads support the vocal performance, while classic house piano stabs and filtered sweeps create movement. The vocals remain crisp and upfront throughout.housedubstepa  This dubstep cover opens with clear vocals over sparse atmospherics before the massive sub-bass drops. Syncopated rhythms and wobbling basslines frame the vocal performance, while glitchy effects and dramatic builds maintain energy. The vocals cut through the heavy bass with clarity.jazza  This smooth jazz cover features clear vocals supported by warm piano chords and walking basslines. Brushed drums and subtle horn sections complement the vocal melody, while sophisticated harmonies add depth. The intimate vocal delivery remains the centerpiece throughout.zsmooth jazzlofia  This lofi cover wraps the clear vocals in warm vinyl crackle and nostalgic atmospherics. Mellow hip-hop beats and dusty piano samples support the vocal performance, while subtle pitch variations add character. The vocals remain intelligible through the cozy production.z
lofi beatszchill lofi beats
orchestrala  This orchestral cover features clear vocals supported by sweeping string sections and dramatic brass. Timpani rolls and woodwind flourishes punctuate the vocal phrases, while the full orchestra swells during emotional peaks. The vocals soar above the symphonic arrangement.zepic orchestrala  This epic orchestral cover features clear vocals supported by sweeping string sections and dramatic brass. Timpani rolls and woodwind flourishes punctuate the vocal phrases, while the full orchestra swells during emotional peaks. The vocals soar above the symphonic arrangement.	classicala  This classical cover presents clear vocals with refined orchestral accompaniment. Elegant string arrangements and delicate woodwinds support the vocal line, while dynamic contrasts highlight the emotional content. The vocals maintain prominence throughout the sophisticated arrangement.zclassical symphonya'  This classical symphony cover presents clear vocals with refined orchestral accompaniment. Elegant string arrangements and delicate woodwinds support the vocal line, while dynamic contrasts highlight the emotional content. The vocals maintain prominence throughout the sophisticated arrangement.zheavy metala  This heavy metal cover features powerful vocals over crushing guitar riffs and thunderous drums. Palm-muted chugs and soaring lead guitars frame the vocal performance, while double-bass drumming drives the intensity. The vocals cut through the wall of sound with commanding presence.metalzThis z cover features clear and prominent vocals throughout. The instrumental arrangement supports and enhances the vocal performance while maintaining the characteristic elements of zV. The vocals remain crisp and intelligible, perfectly balanced with the backing track.)lowerstrip)r   genre_descriptionsstyle_lowers      r%   generate_detailed_tagsr      sc     e  c 	  n 	  h	
 	  r 	  b 	  i 	  ` 	  f 	  l 	  j 	  t 	  v 	  H 	  u  	  o!( ##%++-K((!+.. {m  $U  Va  Ub  bx  y  	yr-   audio_weightgenrec                 B   t        |       }|d   D cg c]  }|d   	 }}dj                  |      }t        j                  t         d|  dt                      t        j                  t         d|  ddd	it               
       |dt        |      ddd| |dddddd}t        j                  t         d|t               
      }|j                  st        d|j                         |j                         }	|	j                  d      }
g }t        j                         }	 t        j                  d       t        j                  t         d|
 t                     }|j                  st        d|j                         |j                         }|r<t        |      dkD  r.|d   }|j                  dd      }|dv r|j                  dg       }n&t        j                         |z
  d kD  rt        d!      |d"v rt        d|       |d   d   |d#   d   fS c c}w )$zcreate remix/cover from clip_idaligned_wordsword r   z/enable_remixesrD   z/update_remix_typetypeREMIXr2   TEXTzinstrumental, spoken wordzchirp-bluejay-t2coverr           )r   style_weightweirdness_constraintT)control_slidersis_remix)promptgeneration_typetagsnegative_tagsmvtaskcover_clip_idmetadataz/api/generate/v2zGeneration failed: r5      z/api/generate/requests?ids=rE   r   rF   rG   )rH   	streamingrI   failedclipsi,  zGeneration timed out)rI   r      )r   joinrM   rN   rO   r,   r   rP   r   rQ   r3   rR   rU   rW   lenrV   )rL   r   r   r   itemwordsjoined_textgeneration_payloadrY   gen_datagen_idfinal_clipsr^   r_   
gen_statusrF   s                   r%   create_remixr   	  s0     F&,_&=>dT&\>E>''%.K MMXJiy@(*U MM*IgY&89g
 !&u-4   !- #(+ 
 
$ 	*$%,>
	A 4409::vvxH\\$F KJ


1LLj3F8<hj
 tt!5affX>??ffh3{+a/$QJ^^Hi8FEE(nnWb999;#c)566) , $$0=>>q>$Q!555S ?s   Harrwindowc                    t         j                  j                  |       } |dkD  rat        |       |kD  rSt        j                  |      |z  }|dz  }t        j
                  | ||fd      }t        j                  ||d      ||  } | S )z,Smooth array while maintaining monotonicity.r      edge)modesame)npmaximum
accumulater   onespadconvolve)r   r   kernelr   paddeds        r%   smooth_monotonicr   Y  sy    
**


$Czc#h'6)kc3Zf5kk&&v6sC4@Jr-   c                 ~   t        |d       }t        j                  |D cg c]  }|d   	 c}      t        j                  |D cg c]  }|d   	 c}      t        j                  dgt        j                        dkD        }|   |   t        |      t        |       }|rt        |      }|j                  }	nd   }	d   dkD  r1t        j                  dd      t        j                  dd         d   |	k  r/t        j                  |	      t        j                  d         fd	}
|j                  |
      j                  |	      }|r|j                        }|j                  |t        d
|rdndd       |j                          |rj                          yyc c}w c c}w )aw  
    Warp video timing based on timestamp pairs and optionally add audio.

    Args:
        video_path: Path to input video
        output_path: Path to output video
        timestamps: List of tuples (original_time, warped_time) in seconds
        audio_path: Optional path to audio file to add (unwarped)
        smooth_win: Window size for smoothing the time mapping
    c                     | d   S )Nr    )xs    r%   <lambda>z,warp_video_with_timestamps.<locals>.<lambda>r  s
    !A$ r-   )r?   r   r   Tư>r   c                 D    t        t        j                  |             S )z)Map from output time to input video time.)floatr   interp)toriginal_timeswarped_timess    r%   map_timez,warp_video_with_timestamps.<locals>.map_time  s    RYYq,?@@r-   libx264aacN   )fpscodecaudio_codecthreads)sortedr   arrayappenddiffr   r   r   durationinsertfl_timeset_duration	set_audiowrite_videofileFPSclose)rv   output_path
timestampsr.   
smooth_winr   maskvideor>   output_durationr   warped_videor   r   s               @@r%   warp_video_with_timestampsr   d  s    
7JXXZ8qt89N88:6aQqT67L 99dVRWW\2T9:D%L#D)N &njAN *%E j)..&r* Ayyq#6>1nQ6GHB/)yy?>>"3EFA
 ==*77HL #--e4   'ET !  
KKM k 96s   F5
F:song_idmp4temp_dirr   warp_timestampsc           	      :   	 	 d|  d}t         j                  j                  |j                  | d      }t	        j
                  |      }|j                          t        |d      5 }|j                  |j                         d d d        	 t        ||j                   d| d||j                   d| d       t        |j                   d| dd	| d       t        d
d	| d        y # 1 sw Y   lxY w# t        $ r}	t        |	       Y d }	~	nd }	~	ww xY w)Nr   r@   z_song_audio.mp3wbz/songify_video_rk   r{   )rv   r   r   r.   songify_video_zUploaded video to S3: )r   pathr   r
   rM   rR   raise_for_statusrS   writecontentr   r   r   r&   )
r   r   r  r   r  song_urlr   responser[   r$   s
             r%   generate_videor    s%    
	.wit<HX]]tfO4LMI||H-H%%'i& *!(()* }}o_TF$?"mm_AdV?;	 ==/d3~dV45P 
"^D6#>"?
@A* *  	!HH	 s0   A$C: 'C.C: .C73C: :	DDDoriginal_lyricsuuidsc           
          t        ||      \  }}t        |      }t        |      }	d\  dt        dt        fdfd}
dt        ffd} ||       } ||      } ||	      } |
||      } |
||      }g }|j	                  t        j                  t        ||||d	   |f
             |j	                  t        j                  t        ||||d   |f
             |D ]  }|j                           |D ]  }|j                           y )N)r   )g333333?g      @txtr   c                     t         j                  ddt        j                  dz         }t	        j
                  d|       j                  |      j                         j                         S )Nr   u   ‘’“”"…—–NFKD)	r   	maketransstringpunctuationunicodedata	normalize	translater   r   )r  tbls     r%   _normz!create_remix_pairs.<locals>._norm  sP    mmBF$6$69Q$QR$$VS1;;C@FFHNNPPr-   c                 &   | D cg c]  }|d   	 }}|D cg c]  }|d   	 }}t        ||d      }g }dx}}|j                         D ]  \  }	}
}}}|	dk7  rt        t        |
|      t        ||            D ]|  \  }}| |   ||   }}|d   |d   }}|d   |d   }}||k  s||k  r/||z
  t	        ||z
  d      z  }|cxk  rk  sPn S|j                  ||f       |j                  ||f       ||}}~  |st        d	      |S c c}w c c}w )
NrQ   F)abautojunkg      equalstart_send_sr   u)   No anchors aligned – check transcripts.)r   get_opcodesziprangemaxr   r   )old_alignmentnew_alignmentwv_wordss_wordssmanchorsprev_vsprev_sstagi1i2j1j2visjvwswvs0ve0ss0se0ratio	RATIO_MAX	RATIO_MINs                          r%   get_anchorsz'create_remix_pairs.<locals>.get_anchors  sQ   &341V944&341V944w'EB  '#%>>#3 	0CRRg~eBmU2r]; 
0B&r*M",=Bi="W+Si="W+S'>SG^sc#)T&::22NNC:.NNC:.'*CWG
0	0 JKK/ 54s
   D	Dr   c                 j    | d   D cg c]  }|d   D ]  }|d |d         iz    c}}S c c}}w )Nr   r   rQ   r   )r   sectionr   r  s      r%   make_cleaned_lyricsz/create_remix_pairs.<locals>.make_cleaned_lyrics  sX     ""23
(
  VU4<011
1
 	
 
s   !/r   targetargsr   )
r   r   r   dictr   	threadingThreadr  startr   )r  rL   r   r  r  r   remix1remix2lyrics_remix1lyrics_remix2r?  rB  clean_original_lyricsclean_remix_lyrics1clean_remix_lyrics2deduped1deduped2r   threadr=  r>  r  s                      @@@r%   create_remix_pairsrT    s.    "'7NFFv&Mv&M#IyQ3 Q3 Q4
D 
 0@-m<-m<02EFH02EFHGNN!ha((S	

 NN!ha((S	

   r-   z
aws-bucketzjason-backend-api-key)secretsT)docs	num_pairsc                    |rt        j                  |      nd }t        d|        t        j                         }t        d|j
                          t        | |j
                        }t        ||j
                        }t        t        |            }t        |      }g }	g }
t        |      D ]{  }|s4t        d      D cg c]  }t        t        j                               ! }}n||dz  |dz   dz   }|	|z  }	|
j                  t!        j"                  t$        ||||||f             } |
D ]  }|j'                           |
D ]  }|j)                           |	S c c}w )Nzuuids: z Temporary directory created at: r   r   rC  )r3   loadsr   tempfileTemporaryDirectoryr
   ru   r   ra   r   r   r$  r   r   r   r   rG  rH  rT  rI  r   )r8   rW  r   r  r  r   r>   rL   r  
all_videosr   i_
this_uuidsrS  s                  r%   songify_a_videor`    sR    "'DJJuDE	GE7
**,H	,X]]O
<=
hmm
,C#x}}-E4;'G )OJG9 
5:1X>#djjl+>J>q1uA{3Jj 
)%wXz5Q	

     ! ?s    $E)N)r   r   )NrK   )z:https://www.tiktok.com/@miryummi/video/7532607674991512862r   r   N)=r3   r   rl   r  r   rZ  rG  rU   r  r   difflibr   r   typingr   r   dotenvnumpyr   rM   moviepy.editorr   r   yt_dlpr   modalImagedebian_slimpip_install_from_pyprojectapt_installr   Appapp	S3_BUCKETrO   r   load_dotenvr   r&   r,   ra   ru   r   r   r   r   r   r   ndarrayintr   r   listr  rF  rT  functionSecret	from_namefastapi_endpointr`  r   r-   r%   <module>rw     s    	         #       7   
KK 01[ 
 eii*%8  	 1    E# ES EC E*TaT ac aHQ Qc Qc Q'c 'C 'C '&  $$y $y $yNM6# M6U M6 M6`"** c bjj  FGEPBBB&)B14BGKB6FFF 
F 	F
 9F FR |,67   	 L	&	&& & 	&&r-   