AlexandreScriptsMT commited on
Commit
9583a19
·
verified ·
1 Parent(s): 9168b3f

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +90 -0
app.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import requests
3
+ import uvicorn
4
+ from fastapi import FastAPI, HTTPException
5
+ from fastapi.responses import FileResponse
6
+ from pydantic import BaseModel
7
+ from faster_whisper import WhisperModel
8
+ from moviepy.editor import ImageClip, AudioFileClip, TextClip, CompositeVideoClip
9
+
10
+ # Inicializa a API
11
+ app = FastAPI()
12
+
13
+ # Modelo de dados que esperamos receber do GAS
14
+ class VideoRequest(BaseModel):
15
+ image_url: str
16
+ audio_url: str
17
+
18
+ # --- Funções Auxiliares ---
19
+
20
+ def download_file(url, filename):
21
+ """Baixa o arquivo da URL e salva localmente"""
22
+ response = requests.get(url, stream=True)
23
+ if response.status_code == 200:
24
+ with open(filename, 'wb') as f:
25
+ for chunk in response.iter_content(1024):
26
+ f.write(chunk)
27
+ else:
28
+ raise Exception(f"Erro ao baixar {url}")
29
+
30
+ def criar_video_logica(imagem_path, audio_path, output_path):
31
+ """A lógica de edição (Whisper + MoviePy)"""
32
+ print("Carregando modelo Whisper...")
33
+ model = WhisperModel("tiny", device="cpu", compute_type="int8")
34
+ segments, _ = model.transcribe(audio_path, language="pt")
35
+
36
+ text_clips = []
37
+ # Configuração visual da legenda
38
+ font_settings = {
39
+ "fontsize": 30, "color": 'white', "font": 'Arial-Bold',
40
+ "stroke_color": 'black', "stroke_width": 2, "method": 'caption',
41
+ "size": (800, None)
42
+ }
43
+
44
+ print("Gerando legendas...")
45
+ for segment in segments:
46
+ txt_clip = TextClip(segment.text.strip(), **font_settings)
47
+ txt_clip = txt_clip.set_start(segment.start).set_duration(segment.end - segment.start)
48
+ txt_clip = txt_clip.set_position(('center', 'bottom'))
49
+ text_clips.append(txt_clip)
50
+
51
+ audio_clip = AudioFileClip(audio_path)
52
+ image_clip = ImageClip(imagem_path).set_duration(audio_clip.duration).set_audio(audio_clip)
53
+
54
+ final = CompositeVideoClip([image_clip] + text_clips)
55
+
56
+ print("Renderizando vídeo...")
57
+ final.write_videofile(output_path, fps=10, codec="libx264", audio_codec="aac", preset="ultrafast", threads=2)
58
+ return output_path
59
+
60
+ # --- O Endpoint da API (Onde o GAS conecta) ---
61
+
62
+ @app.post("/gerar-video")
63
+ async def gerar_video_endpoint(request: VideoRequest):
64
+ try:
65
+ # 1. Definir caminhos temporários
66
+ temp_img = "temp_image.png"
67
+ temp_audio = "temp_audio.mp3"
68
+ output_video = "video_final.mp4"
69
+
70
+ # 2. Baixar os assets que o GAS mandou os links
71
+ print(f"Baixando imagem de: {request.image_url}")
72
+ download_file(request.image_url, temp_img)
73
+
74
+ print(f"Baixando áudio de: {request.audio_url}")
75
+ download_file(request.audio_url, temp_audio)
76
+
77
+ # 3. Rodar a mágica
78
+ criar_video_logica(temp_img, temp_audio, output_video)
79
+
80
+ # 4. Devolver o arquivo pronto para o GAS
81
+ # O FileResponse envia o arquivo binário na resposta HTTP
82
+ return FileResponse(output_video, media_type="video/mp4", filename="video_editado.mp4")
83
+
84
+ except Exception as e:
85
+ print(f"Erro: {e}")
86
+ raise HTTPException(status_code=500, detail=str(e))
87
+
88
+ # Configuração para rodar no Hugging Face
89
+ if __name__ == "__main__":
90
+ uvicorn.run(app, host="0.0.0.0", port=7860)