Spaces:
Running
Running
Update routers/video.py
Browse files- routers/video.py +84 -2
routers/video.py
CHANGED
|
@@ -131,7 +131,7 @@ def render_headline_text(draw: ImageDraw.Draw, text: str, x: int, y: int, max_wi
|
|
| 131 |
draw.text((centered_x, adjusted_y), line, fill=(0, 0, 0, 89), font=final_font) # Texto com opacidade para sombra
|
| 132 |
|
| 133 |
# Atualizar posição para próxima linha (subindo)
|
| 134 |
-
current_y -= int(line_height * 1.4) # Line height de
|
| 135 |
|
| 136 |
def render_headline_text_white(draw: ImageDraw.Draw, text: str, x: int, y: int, max_width: int, max_lines: int = 5) -> None:
|
| 137 |
"""
|
|
@@ -238,7 +238,37 @@ def render_headline_text_white(draw: ImageDraw.Draw, text: str, x: int, y: int,
|
|
| 238 |
draw.text((centered_x, adjusted_y), line, fill=(255, 255, 255, 255), font=final_font)
|
| 239 |
|
| 240 |
# Atualizar posição para próxima linha (subindo)
|
| 241 |
-
current_y -= int(line_height * 1.4) # Line height de
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 242 |
|
| 243 |
@router.get("/cover/video")
|
| 244 |
def get_video_cover(
|
|
@@ -297,6 +327,58 @@ def get_video_cover(
|
|
| 297 |
# Converter para RGBA para suportar transparência na sombra
|
| 298 |
background_image = background_image.convert('RGBA')
|
| 299 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 300 |
# Criar uma nova imagem para o texto com transparência
|
| 301 |
text_img = Image.new('RGBA', background_image.size, (0, 0, 0, 0))
|
| 302 |
text_draw = ImageDraw.Draw(text_img)
|
|
|
|
| 131 |
draw.text((centered_x, adjusted_y), line, fill=(0, 0, 0, 89), font=final_font) # Texto com opacidade para sombra
|
| 132 |
|
| 133 |
# Atualizar posição para próxima linha (subindo)
|
| 134 |
+
current_y -= int(line_height * 1.4) # Line height de 140%
|
| 135 |
|
| 136 |
def render_headline_text_white(draw: ImageDraw.Draw, text: str, x: int, y: int, max_width: int, max_lines: int = 5) -> None:
|
| 137 |
"""
|
|
|
|
| 238 |
draw.text((centered_x, adjusted_y), line, fill=(255, 255, 255, 255), font=final_font)
|
| 239 |
|
| 240 |
# Atualizar posição para próxima linha (subindo)
|
| 241 |
+
current_y -= int(line_height * 1.4) # Line height de 140%
|
| 242 |
+
|
| 243 |
+
def render_badge(image: Image.Image, x: int, y: int) -> None:
|
| 244 |
+
"""
|
| 245 |
+
Renderiza o badge.png acima do título.
|
| 246 |
+
|
| 247 |
+
Args:
|
| 248 |
+
image: Imagem principal onde o badge será desenhado
|
| 249 |
+
x: Posição X centralizada
|
| 250 |
+
y: Posição Y (topo do badge)
|
| 251 |
+
"""
|
| 252 |
+
try:
|
| 253 |
+
# Carregar o badge
|
| 254 |
+
badge = Image.open("badge.png")
|
| 255 |
+
|
| 256 |
+
# Redimensionar para as dimensões especificadas (L: 197, Altura: 37)
|
| 257 |
+
badge = badge.resize((197, 37), Image.Resampling.LANCZOS)
|
| 258 |
+
|
| 259 |
+
# Converter para RGBA se necessário
|
| 260 |
+
if badge.mode != 'RGBA':
|
| 261 |
+
badge = badge.convert('RGBA')
|
| 262 |
+
|
| 263 |
+
# Calcular posição centralizada
|
| 264 |
+
badge_x = x - (197 // 2) # Centralizar horizontalmente
|
| 265 |
+
|
| 266 |
+
# Colar o badge na imagem principal
|
| 267 |
+
image.paste(badge, (badge_x, y), badge)
|
| 268 |
+
|
| 269 |
+
except (OSError, IOError) as e:
|
| 270 |
+
# Se não conseguir carregar o badge, apenas ignora
|
| 271 |
+
print(f"Erro ao carregar badge: {e}")
|
| 272 |
|
| 273 |
@router.get("/cover/video")
|
| 274 |
def get_video_cover(
|
|
|
|
| 327 |
# Converter para RGBA para suportar transparência na sombra
|
| 328 |
background_image = background_image.convert('RGBA')
|
| 329 |
|
| 330 |
+
# Calcular altura total do texto para posicionar o badge
|
| 331 |
+
# Criar uma imagem temporária para calcular a altura
|
| 332 |
+
temp_img = Image.new('RGBA', background_image.size, (0, 0, 0, 0))
|
| 333 |
+
temp_draw = ImageDraw.Draw(temp_img)
|
| 334 |
+
|
| 335 |
+
# Calcular altura do texto
|
| 336 |
+
try:
|
| 337 |
+
font_path = "fonts/Montserrat-ExtraBold.ttf"
|
| 338 |
+
test_font = ImageFont.truetype(font_path, 70)
|
| 339 |
+
except (OSError, IOError):
|
| 340 |
+
test_font = ImageFont.load_default()
|
| 341 |
+
|
| 342 |
+
# Simular quebra de texto para calcular altura
|
| 343 |
+
words = headline.upper().split()
|
| 344 |
+
lines = []
|
| 345 |
+
current_line = []
|
| 346 |
+
max_width = 720
|
| 347 |
+
|
| 348 |
+
for word in words:
|
| 349 |
+
test_line = " ".join(current_line + [word])
|
| 350 |
+
bbox = temp_draw.textbbox((0, 0), test_line, font=test_font)
|
| 351 |
+
line_width = bbox[2] - bbox[0]
|
| 352 |
+
|
| 353 |
+
if line_width <= max_width:
|
| 354 |
+
current_line.append(word)
|
| 355 |
+
else:
|
| 356 |
+
if current_line:
|
| 357 |
+
lines.append(" ".join(current_line))
|
| 358 |
+
current_line = [word]
|
| 359 |
+
else:
|
| 360 |
+
lines.append(word)
|
| 361 |
+
|
| 362 |
+
if current_line:
|
| 363 |
+
lines.append(" ".join(current_line))
|
| 364 |
+
|
| 365 |
+
# Limitar a 5 linhas
|
| 366 |
+
if len(lines) > 5:
|
| 367 |
+
lines = lines[:5]
|
| 368 |
+
|
| 369 |
+
# Calcular altura total do texto
|
| 370 |
+
total_text_height = 0
|
| 371 |
+
for line in lines:
|
| 372 |
+
bbox = temp_draw.textbbox((0, 0), line, font=test_font)
|
| 373 |
+
line_height = bbox[3] - bbox[1]
|
| 374 |
+
total_text_height += int(line_height * 1.4)
|
| 375 |
+
|
| 376 |
+
# Posição do badge: 16px acima do topo do texto
|
| 377 |
+
badge_y = 1270 - total_text_height - 16
|
| 378 |
+
|
| 379 |
+
# Renderizar o badge
|
| 380 |
+
render_badge(background_image, 540, badge_y)
|
| 381 |
+
|
| 382 |
# Criar uma nova imagem para o texto com transparência
|
| 383 |
text_img = Image.new('RGBA', background_image.size, (0, 0, 0, 0))
|
| 384 |
text_draw = ImageDraw.Draw(text_img)
|