Spaces:
Sleeping
Sleeping
File size: 3,190 Bytes
9583a19 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | 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) |