¿Estás harto de herramientas online lentas y limitadas? ¡Aquí tienes una app en Python con GUI que comprime cualquier video a exactamente 10 MB! Ideal para compartir en WhatsApp, emails, formularios, etc. 💥
Características de la app
- Comprime cualquier video
.mp4
,.mov
,.avi
,.mkv
a un tamaño máximo de 10 MB. - Estima el bitrate óptimo automáticamente.
- Interfaz gráfica en pantalla completa con barra de progreso 🔥
- Muestra el nombre, tamaño original y tamaño final del video.
- Reproduce un sonido de éxito o error.
¿Cómo funciona?
Usamos ffmpeg
y ffprobe
para analizar la duración del video, calcular el bitrate exacto necesario, y luego lo comprimimos con esa calidad de video más un bitrate de audio fijo de 128 kbps.
import tkinter as tk from tkinter import filedialog, messagebox, ttk import subprocess import os import threading import re import winsound TAMANIO_MAX_MB = 10 BITRATE_AUDIO = 128000 def reproducir_sonido(tipo="ok"): try: if tipo == "ok": winsound.Beep(1000, 500) else: winsound.Beep(500, 500) except Exception as e: print(f"🔇 Error al reproducir el sonido: {e}") def comprimir_10mb(): ruta_video = filedialog.askopenfilename(filetypes=[("Videos", "*.mp4 *.mov *.avi *.mkv")]) if not ruta_video: return carpeta_salida = filedialog.askdirectory() if not carpeta_salida: return def proceso_compresion(): try: peso_original = os.path.getsize(ruta_video) / (1024 * 1024) archivo_origen_label.config(text=f"📦 Archivo original: {ruta_video}") tamaño_origen_label.config(text=f"📏 Tamaño original: {peso_original:.2f} MB") update_estado("🔍 Obteniendo duración del video...") comando_duracion = [ "ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", ruta_video ] duracion_segundos = float(subprocess.check_output(comando_duracion).decode().strip()) bits_totales = TAMANIO_MAX_MB * 8 * 1024 * 1024 bitrate_total = bits_totales / duracion_segundos bitrate_video = int(bitrate_total - BITRATE_AUDIO) if bitrate_video < 100000: bitrate_video = 100000 nombre_archivo = os.path.splitext(os.path.basename(ruta_video))[0] salida = os.path.join(carpeta_salida, f"{nombre_archivo}_10MB.mp4") comando = [ "ffmpeg", "-i", ruta_video, "-b:v", str(bitrate_video), "-b:a", "128k", "-preset", "slow", "-y", salida ] update_estado("🚀 Iniciando compresión...") progreso["maximum"] = duracion_segundos progreso["value"] = 0 proceso = subprocess.Popen(comando, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) for linea in proceso.stdout: ventana.update() tiempo_match = re.search(r"time=(\d+):(\d+):(\d+.\d+)", linea) if tiempo_match: h, m, s = tiempo_match.groups() tiempo_actual = int(h) * 3600 + int(m) * 60 + float(s) progreso["value"] = tiempo_actual porcentaje = min(100, (tiempo_actual / duracion_segundos) * 100) update_estado(f"⏳ Progreso: {porcentaje:.1f}%") proceso.wait() progreso["value"] = duracion_segundos update_estado("✅ ¡Compresión completada!") if os.path.exists(salida): peso_final = os.path.getsize(salida) / (1024 * 1024) archivo_salida_label.config(text=f"📁 Archivo comprimido: {salida}") tamaño_final_label.config(text=f"📉 Tamaño final: {peso_final:.2f} MB") if peso_final <= TAMANIO_MAX_MB: reproducir_sonido("ok") messagebox.showinfo("✅ ¡Listo!", f"Video comprimido a {peso_final:.2f} MB:\n{salida}") else: reproducir_sonido("error") messagebox.showwarning("⚠️ Casi", f"Pesa {peso_final:.2f} MB (ligeramente más de 10 MB)") else: reproducir_sonido("error") messagebox.showerror("❌ Error", "No se generó el archivo.") except Exception as e: reproducir_sonido("error") update_estado("❌ Error durante la compresión.") messagebox.showerror("Error", f"Algo falló:\n{str(e)}") threading.Thread(target=proceso_compresion).start() def update_estado(mensaje): progreso_label.config(text=mensaje) ventana.update() ventana = tk.Tk() ventana.title("🔥 Compresor Exacto a 10MB 🔥") ventana.attributes('-fullscreen', True) frame = tk.Frame(ventana, bg="#1e1e1e") frame.pack(expand=True, fill="both") titulo = tk.Label(frame, text="🎥 Compresor de Video a 10MB", font=("Helvetica", 32, "bold"), fg="white", bg="#1e1e1e") titulo.pack(pady=(40, 20)) subtexto = tk.Label(frame, text="Selecciona un video y lo comprimimos al máximo: 10 MB", font=("Helvetica", 18), fg="#bbbbbb", bg="#1e1e1e") subtexto.pack(pady=(0, 40)) btn = tk.Button(frame, text="📁 Seleccionar Video y Comprimir", font=("Helvetica", 20), bg="#00cc66", fg="white", activebackground="#00994d", command=comprimir_10mb) btn.pack(pady=10, ipadx=20, ipady=10) progreso_label = tk.Label(frame, text="", font=("Helvetica", 18), fg="white", bg="#1e1e1e") progreso_label.pack(pady=(30, 10)) progreso = ttk.Progressbar(frame, mode="determinate", length=700) progreso.pack(pady=10) archivo_origen_label = tk.Label(frame, text="📦 Archivo original: ", font=("Helvetica", 14), fg="white", bg="#1e1e1e") archivo_origen_label.pack(pady=(10, 5)) tamaño_origen_label = tk.Label(frame, text="📏 Tamaño original: ", font=("Helvetica", 14), fg="white", bg="#1e1e1e") tamaño_origen_label.pack(pady=(0, 10)) archivo_salida_label = tk.Label(frame, text="📁 Archivo comprimido: ", font=("Helvetica", 14), fg="white", bg="#1e1e1e") archivo_salida_label.pack(pady=(10, 5)) tamaño_final_label = tk.Label(frame, text="📉 Tamaño final: ", font=("Helvetica", 14), fg="white", bg="#1e1e1e") tamaño_final_label.pack(pady=(0, 10)) btn_salir = tk.Button(frame, text="❌ Salir", font=("Helvetica", 16), bg="#ff3333", fg="white", activebackground="#cc0000", command=ventana.destroy) btn_salir.pack(side="bottom", pady=30) ventana.mainloop()
¿Qué necesitas para que funcione?
- Python 3 instalado
- Instalar
ffmpeg
en el sistema (disponible para Windows/macOS/Linux) - Tener el módulo
tkinter
, que viene incluido con Python
Recomendado: empaquetar como .exe
Puedes convertir esta app en un .exe
con pyinstaller
para que cualquier persona sin Python lo use:
pyinstaller --onefile --noconsole --add-data "*.mp3;." compresor.py