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)