JUDIS Descargar JUDIS
Receta pública

Cómo convertir GIF a video ASCII en Google Colab

Procesar un archivo GIF mediante código Python en Google Colab para generar un video en formato ASCII art y descargarlo. Guía paso a paso (13 pasos) par…

13 pasos guiados·Dificultad fácil

JUDIS te señala cada botón sobre tu propia pantalla mientras lo haces. Sin la app, los pasos se leen igual aquí.

Antes de empezar

Tener una cuenta de Google con acceso a Google Colab (colab.research.google.com) y el archivo GIF que quieras convertir guardado en tu computadora.

Ten a la mano

  • Un archivo GIF que quieras convertir a video ASCII · suele estar en Descargas
Pág. 1

Paso a paso

1

Paso 1

Abre una pestaña nueva del navegador y entra a colab.research.google.com.

Escribe: colab.research.google.com

Listo cuando: Se abre la página de Google Colab con la lista de notebooks.

2

Paso 2

Abre un notebook de la lista, o crea uno nuevo.

Listo cuando: Se abre el notebook con la barra de menú (Archivo, Editar, Ver, Insertar) y una celda de código.

3

Paso 3

Haz clic dentro de la celda de código vacía.

Listo cuando: El campo quedó activo (cursor visible) y listo para escribir o pegar contenido.

4

Paso 4

Antes: El campo de entrada de código debe estar activo (cursor visible) — si no, el código no se pega en el lugar correcto.

Pega el código Python completo en la celda.

Escribe:
# ==========================================
# 1. INSTALACIÓN DE DEPENDENCIAS
# ==========================================
import os
import cv2
import numpy as np
from PIL import Image, ImageEnhance, ImageFilter, ImageDraw, ImageFont
from google.colab import files

# Instalar fuente monoespaciada
!apt-get install -y ttf-dejavu > /dev/null 2>&1

ASCII_CHARS = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvrjfI1?i+~i!lI;:,\"^`'. "

# ==========================================
# 2. PROCESAMIENTO ASCII CON MAYOR ALTURA
# ==========================================
def frame_to_ascii_grid(frame_pil, width_chars=320, height_factor=0.9, contrast=2.4):
    img = frame_pil.convert("L")
    img = img.filter(ImageFilter.UnsharpMask(radius=2.0, percent=300, threshold=1))
    img = ImageEnhance.Contrast(img).enhance(contrast)

    w_orig, h_orig = img.size
    aspect_ratio = h_orig / w_orig
    
    pixel_width = width_chars
    # height_factor a 0.9 aumenta las filas de texto verticalmente
    pixel_height = int(pixel_width * aspect_ratio * height_factor)

    img_resized = img.resize((pixel_width, pixel_height), Image.Resampling.LANCZOS)
    
    ascii_grid = []
    num_chars = len(ASCII_CHARS)

    for y in range(pixel_height):
        row = []
        for x in range(pixel_width):
            px = img_resized.getpixel((x, y))
            char_idx = int((px / 255) * (num_chars - 1))
            row.append(ASCII_CHARS[char_idx])
        ascii_grid.append(row)

    return ascii_grid, pixel_width, pixel_height

def render_ascii_ultra_tight(
    ascii_grid, 
    pixel_width, 
    pixel_height, 
    font_size=12,
    bg_color=(0, 0, 0), 
    text_color=(255, 255, 255)
):
    font_path = "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf"
    try:
        font = ImageFont.truetype(font_path, font_size)
    except Exception:
        font = ImageFont.load_default()

    bbox = font.getbbox("W")
    char_w = bbox[2] - bbox[0]
    char_h = bbox[3] - bbox[1]

    # Paso apretado sin espacios
    step_x = char_w * 0.72  
    step_y = char_h * 0.85

    margin = 20
    canvas_w = int(pixel_width * step_x) + (margin * 2)
    canvas_h = int(pixel_height * step_y) + (margin * 2)

    canvas = Image.new("RGB", (canvas_w, canvas_h), color=bg_color)
    draw = ImageDraw.Draw(canvas)

    for y in range(pixel_height):
        for x in range(pixel_width):
            char = ascii_grid[y][x]
            if char != ' ':
                pos_x = margin + (x * step_x)
                pos_y = margin + (y * step_y)
                draw.text((pos_x, pos_y), char, font=font, fill=text_color)

    return canvas

def process_gif_in_colab(gif_path, output_mp4="caballo_ascii_ultra_hd.mp4", width_chars=320):
    try:
        gif = Image.open(gif_path)
    except Exception as e:
        print(f"❌ Error al abrir el GIF: {e}")
        return None

    fps = 12
    if "duration" in gif.info and gif.info["duration"] > 0:
        fps = 1000 / gif.info["duration"]

    frames_processed = []
    frame_idx = 0

    print(f"🚀 Procesando fotogramas a Alta Resolución ({width_chars} cols)...")
    try:
        while True:
            gif.seek(frame_idx)
            frame_pil = Image.new("RGBA", gif.size)
            frame_pil.paste(gif)

            # 1. Matriz con height_factor=0.9 para dar más altura
            ascii_grid, p_w, p_h = frame_to_ascii_grid(
                frame_pil, 
                width_chars=width_chars, 
                height_factor=0.9,
                contrast=2.4
            )

            # 2. Renderizado compacto
            frame_rendered = render_ascii_ultra_tight(
                ascii_grid, p_w, p_h,
                font_size=12
            )
            
            frames_processed.append(frame_rendered)
            frame_idx += 1
            print(f"✔ Frame {frame_idx} procesado.")
    except EOFError:
        pass

    if not frames_processed:
        print("❌ No se encontraron fotogramas.")
        return None

    # 3. Exportar MP4
    v_w, v_h = frames_processed[0].size
    if v_w % 2 != 0: v_w += 1
    if v_h % 2 != 0: v_h += 1

    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    out = cv2.VideoWriter(output_mp4, fourcc, fps, (v_w, v_h))

    for frame in frames_processed:
        if frame.size != (v_w, v_h):
            frame = frame.resize((v_w, v_h))
        cv_img = cv2.cvtColor(np.array(frame), cv2.COLOR_RGB2BGR)
        out.write(cv_img)

    out.release()
    print(f"\n🎉 ¡Proceso finalizado! Archivo guardado en Colab como '{output_mp4}'.")
    return output_mp4

# ==========================================
# 3. EJECUCIÓN
# ==========================================
print("📂 Sube tu archivo GIF:")
uploaded = files.upload()

if uploaded:
    input_gif = list(uploaded.keys())[0]
    output_mp4 = "caballo_ascii_ultra_hd.mp4"

    res = process_gif_in_colab(input_gif, output_mp4, width_chars=320)

    if res and os.path.exists(res):
        print("\n📁 El video está listo. Puedes encontrarlo en la pestaña de archivos (ícono de carpeta a la izquierda en Colab) para descargarlo cuando quieras.")

Listo cuando: El código aparece en la celda con colores. Empieza con '1. INSTALACIÓN DE DEPENDENCIAS'.

5

Paso 5

Toca 'Ejecutar todo' para correr el código.

Listo cuando: Abajo aparece 'Asignando entorno de ejecución' y la celda empieza a correr.

6

Paso 6

Baja hasta el final de la celda, hasta donde dice 'Sube tu archivo GIF'.

Listo cuando: Ves el botón 'Seleccionar archivos'.

7

Paso 7

Toca 'Seleccionar archivos'.

Listo cuando: Se abre la ventana 'Elige los archivos a cargar'.

8

Paso 8

Busca tu GIF (suele estar en Descargas) y selecciónalo.

Listo cuando: El archivo queda resaltado en azul.

9

Paso 9

Antes: Tu GIF debe estar seleccionado (en azul).

Toca el botón 'Cargar'.

Listo cuando: La ventana se cierra y bajo la celda aparece el nombre de tu GIF como subido.

10

Paso 10

Espera a que el código procese el GIF. No hace falta volver a ejecutar: empieza solo al subirlo.

Listo cuando: Aparecen líneas 'Frame X procesado' y al final un mensaje de que el video se guardó.

11

Paso 11

Mira el panel de archivos a la izquierda.

Listo cuando: Aparece un archivo .mp4 que termina en '_ascii_ultra_hd.mp4'.

12

Paso 12

Pasa el mouse sobre el video .mp4 del panel de archivos.

Listo cuando: Junto al archivo aparecen los tres puntos de opciones.

13

Paso 13

Haz doble clic en el nombre del video para descargarlo. También puedes tocar los tres puntos y elegir 'Descargar'.

Listo cuando: El video se guarda en tu carpeta de Descargas.

Qué puede cambiar en tu caso

El nombre del notebook puede variar (Untitled1, Untitled2, etc.). El nombre de tu GIF y del video resultante dependen del archivo que subas. El tiempo de procesamiento depende de lo largo que sea el GIF.

En qué se suele equivocar la gente

Pegar el código sin haber hecho clic antes dentro de la celda. Tocar 'Cargar' sin haber seleccionado el GIF. Buscar el botón para subir el archivo sin bajar hasta el final de la celda.