APIvideo / app.py
AlexandreScriptsMT's picture
Create app.py
9583a19 verified
raw
history blame
3.19 kB
import os
import requests
import uvicorn
from fastapi import FastAPI, HTTPException
from fastapi.responses import FileResponse
from pydantic import BaseModel
from faster_whisper import WhisperModel
from moviepy.editor import ImageClip, AudioFileClip, TextClip, CompositeVideoClip
# Inicializa a API
app = FastAPI()
# Modelo de dados que esperamos receber do GAS
class VideoRequest(BaseModel):
image_url: str
audio_url: str
# --- Funções Auxiliares ---
def download_file(url, filename):
"""Baixa o arquivo da URL e salva localmente"""
response = requests.get(url, stream=True)
if response.status_code == 200:
with open(filename, 'wb') as f:
for chunk in response.iter_content(1024):
f.write(chunk)
else:
raise Exception(f"Erro ao baixar {url}")
def criar_video_logica(imagem_path, audio_path, output_path):
"""A lógica de edição (Whisper + MoviePy)"""
print("Carregando modelo Whisper...")
model = WhisperModel("tiny", device="cpu", compute_type="int8")
segments, _ = model.transcribe(audio_path, language="pt")
text_clips = []
# Configuração visual da legenda
font_settings = {
"fontsize": 30, "color": 'white', "font": 'Arial-Bold',
"stroke_color": 'black', "stroke_width": 2, "method": 'caption',
"size": (800, None)
}
print("Gerando legendas...")
for segment in segments:
txt_clip = TextClip(segment.text.strip(), **font_settings)
txt_clip = txt_clip.set_start(segment.start).set_duration(segment.end - segment.start)
txt_clip = txt_clip.set_position(('center', 'bottom'))
text_clips.append(txt_clip)
audio_clip = AudioFileClip(audio_path)
image_clip = ImageClip(imagem_path).set_duration(audio_clip.duration).set_audio(audio_clip)
final = CompositeVideoClip([image_clip] + text_clips)
print("Renderizando vídeo...")
final.write_videofile(output_path, fps=10, codec="libx264", audio_codec="aac", preset="ultrafast", threads=2)
return output_path
# --- O Endpoint da API (Onde o GAS conecta) ---
@app.post("/gerar-video")
async def gerar_video_endpoint(request: VideoRequest):
try:
# 1. Definir caminhos temporários
temp_img = "temp_image.png"
temp_audio = "temp_audio.mp3"
output_video = "video_final.mp4"
# 2. Baixar os assets que o GAS mandou os links
print(f"Baixando imagem de: {request.image_url}")
download_file(request.image_url, temp_img)
print(f"Baixando áudio de: {request.audio_url}")
download_file(request.audio_url, temp_audio)
# 3. Rodar a mágica
criar_video_logica(temp_img, temp_audio, output_video)
# 4. Devolver o arquivo pronto para o GAS
# O FileResponse envia o arquivo binário na resposta HTTP
return FileResponse(output_video, media_type="video/mp4", filename="video_editado.mp4")
except Exception as e:
print(f"Erro: {e}")
raise HTTPException(status_code=500, detail=str(e))
# Configuração para rodar no Hugging Face
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=7860)