Spaces:
Sleeping
Sleeping
File size: 4,380 Bytes
9583a19 4da758a aca6f46 9583a19 aca6f46 9583a19 aca6f46 9583a19 aca6f46 9583a19 aca6f46 9583a19 aca6f46 9583a19 aca6f46 4da758a aca6f46 4da758a aca6f46 4da758a aca6f46 9583a19 aca6f46 9583a19 aca6f46 9583a19 aca6f46 9583a19 aca6f46 9583a19 aca6f46 9583a19 aca6f46 9583a19 aca6f46 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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | 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
# --- A IMPORTAÇÃO CLÁSSICA E SEGURA ---
# Na versão 1.0.3, este módulo contém tudo que precisamos
from moviepy.editor import ImageClip, AudioFileClip, TextClip, CompositeVideoClip, concatenate_videoclips
app = FastAPI()
# Modelo de dados
class VideoRequest(BaseModel):
audio_url: str
imagens: list[str] # Aceita lista de imagens agora
duracao_estimada: int = 60
# --- Funções Auxiliares ---
def download_file(url, filename):
try:
response = requests.get(url, stream=True)
response.raise_for_status() # Garante que deu 200 OK
with open(filename, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
except Exception as e:
print(f"Erro ao baixar {url}: {e}")
raise e
def criar_video_v1(lista_imagens_paths, audio_path, output_path):
print("1. Carregando Áudio...")
audio_clip = AudioFileClip(audio_path)
duracao_total = audio_clip.duration
# Cálculos de tempo
qtd_imgs = len(lista_imagens_paths)
if qtd_imgs == 0: raise Exception("Nenhuma imagem fornecida")
tempo_por_imagem = duracao_total / qtd_imgs
print(f"2. Montando Timeline ({qtd_imgs} imagens, {tempo_por_imagem:.2f}s cada)...")
clips_visuais = []
for img_path in lista_imagens_paths:
# Configuração Versão 1.0.3 (usando set_)
clip = ImageClip(img_path).set_duration(tempo_por_imagem)
# Opcional: Resize para garantir que caiba (se necessário)
# clip = clip.resize(height=1080)
clips_visuais.append(clip)
# Junta as imagens em sequência
video_sem_audio = concatenate_videoclips(clips_visuais, method="compose")
# Junta com o áudio
video_final = video_sem_audio.set_audio(audio_clip)
# --- GERAÇÃO DE LEGENDAS (Opcional - Pode comentar se der erro de ImageMagick) ---
# Para ativar legendas, descomente abaixo. Se der erro de "convert", deixe comentado por enquanto.
# print("3. Gerando Legendas (Whisper)...")
# model = WhisperModel("tiny", device="cpu", compute_type="int8")
# segments, _ = model.transcribe(audio_path, language="pt")
# legendas_clips = []
# for segment in segments:
# txt = TextClip(segment.text, fontsize=24, color='white', font='DejaVu-Sans-Bold', stroke_color='black', stroke_width=1, size=(800, None), method='caption')
# txt = txt.set_start(segment.start).set_duration(segment.end - segment.start).set_position(('center', 'bottom'))
# legendas_clips.append(txt)
# video_final = CompositeVideoClip([video_final] + legendas_clips)
# ---------------------------------------------------------------------------------
print("4. Renderizando Arquivo Final...")
# fps=10 é leve e rápido para imagens estáticas
video_final.write_videofile(
output_path,
fps=10,
codec="libx264",
audio_codec="aac",
preset="ultrafast",
threads=2
)
# Limpeza de memória (importante no Hugging Face)
audio_clip.close()
video_final.close()
return output_path
@app.post("/gerar-video")
async def gerar_video_endpoint(request: VideoRequest):
try:
# Nomes temporários
temp_audio = "temp_audio.mp3"
lista_imgs_locais = []
output_video = "video_final.mp4"
# 1. Baixar Audio
print(f"Baixando áudio...")
download_file(request.audio_url, temp_audio)
# 2. Baixar Imagens (Loop)
print(f"Baixando {len(request.imagens)} imagens...")
for i, url in enumerate(request.imagens):
nome_img = f"temp_img_{i}.jpg"
download_file(url, nome_img)
lista_imgs_locais.append(nome_img)
# 3. Processar
criar_video_v1(lista_imgs_locais, temp_audio, output_video)
# 4. Retornar
return FileResponse(output_video, media_type="video/mp4", filename="video_renderizado.mp4")
except Exception as e:
print(f"ERRO CRÍTICO: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=7860) |