Compare commits

..

No commits in common. "b68896754bac5ecf7d1e4c1dc4390665a21935e1" and "6bc9a5cb4438f982696af5ea7a2488e3af109729" have entirely different histories.

316 changed files with 3281 additions and 10747 deletions

BIN
ElevenLabs.mp3 Normal file

Binary file not shown.

BIN
ElevenLabs1.mp3 Normal file

Binary file not shown.

BIN
Rodrigo Cahuantzi_1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,350 +0,0 @@
import asyncio
from pydub import AudioSegment
import os
import threading
import http.server
import socketserver
import socket
import time
import subprocess
import urllib.request # Para enviar HTTP GET a la ESP32 (sin librerías extra)
# ================= CONFIGURACIÓN =================
IP_BOCINA = "192.168.15.135"
PUERTO_ESP32 = 80
PUERTO_HTTP = 8000
CARPETA_AUDIO = "public_audio"
if not os.path.exists(CARPETA_AUDIO):
os.makedirs(CARPETA_AUDIO)
# ================= AUTO-DETECTAR MI IP =================
def obtener_mi_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect((IP_BOCINA, 80))
IP = s.getsockname()[0]
except Exception:
IP = '127.0.0.1'
finally:
s.close()
return IP
MI_IP = obtener_mi_ip()
print(f"[RED] IP auto-detectada para el servidor de audio: {MI_IP}")
def iniciar_servidor_http():
class Handler(http.server.SimpleHTTPRequestHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, directory=CARPETA_AUDIO, **kwargs)
def log_message(self, format, *args):
print(f"[SERVIDOR HTTP] Petición de ESP32: {args[0]}")
def handle(self):
try:
super().handle()
except (BrokenPipeError, ConnectionResetError):
pass
def copyfile(self, source, outputfile):
try:
super().copyfile(source, outputfile)
except (BrokenPipeError, ConnectionResetError):
pass
class ReusableTCPServer(socketserver.TCPServer):
allow_reuse_address = True
try:
with ReusableTCPServer(("", PUERTO_HTTP), Handler) as httpd:
print(f"Servidor de Audio activo en http://{MI_IP}:{PUERTO_HTTP}")
httpd.serve_forever()
except Exception as e:
print(f"ERROR CRÍTICO AL LEVANTAR EL SERVIDOR: {e}")
# ================= ORDEN A LA ESP32 =================
# La ESP32 usa HTTP GET en /play?url=..., NO WebSocket.
# Antes usábamos WebSocket al puerto 81 → la ESP32 nunca recibió nada.
def _mandar_orden_reproduccion(nombre_archivo):
url_mp3 = f"http://{MI_IP}:{PUERTO_HTTP}/{nombre_archivo}"
# Construimos la URL exacta que espera el handlePlay() de la ESP32
url_orden = f"http://{IP_BOCINA}:{PUERTO_ESP32}/play?url={url_mp3}"
try:
print(f"Ordenando a ESP32 reproducir: {url_mp3}")
with urllib.request.urlopen(url_orden, timeout=5) as respuesta:
estado = respuesta.read().decode()
print(f"ESP32 respondió: {estado}")
return True
except Exception as e:
print(f" Error enviando orden a la bocina: {e}")
return False
# ================= CONTROL DE VOLUMEN =================
def _mandar_orden_volumen(nivel=18):
"""Establece volumen directamente (0-21)"""
url_orden = f"http://{IP_BOCINA}:{PUERTO_ESP32}/volume?level={nivel}"
try:
with urllib.request.urlopen(url_orden, timeout=5) as respuesta:
print(f"Volumen: {respuesta.read().decode()}")
return True
except Exception as e:
print(f"Error cambiando volumen: {e}")
return False
def subir_volumen():
"""Sube 1 nivel de volumen"""
url_orden = f"http://{IP_BOCINA}:{PUERTO_ESP32}/volume_up"
try:
with urllib.request.urlopen(url_orden, timeout=5) as respuesta:
print(f" {respuesta.read().decode()}")
return True
except Exception as e:
print(f"Error: {e}")
return False
def bajar_volumen():
"""Baja 1 nivel de volumen"""
url_orden = f"http://{IP_BOCINA}:{PUERTO_ESP32}/volume_down"
try:
with urllib.request.urlopen(url_orden, timeout=5) as respuesta:
print(f"{respuesta.read().decode()}")
return True
except Exception as e:
print(f"Error: {e}")
return False
# ================= LÓGICA PRINCIPAL =================
def enviar_archivos_bocina(lista_archivos):
if not lista_archivos:
return
try:
# 1. Unimos los audios
audio_final = AudioSegment.empty()
for archivo in lista_archivos:
if os.path.exists(archivo):
audio_final += AudioSegment.from_file(archivo)
# 2. WAV temporal
ruta_temp = os.path.join(CARPETA_AUDIO, "temp.wav")
audio_final.export(ruta_temp, format="wav")
# 3. Nombre único anti-caché
timestamp = int(time.time())
nombre_salida = f"saludo_{timestamp}.mp3"
ruta_salida = os.path.join(CARPETA_AUDIO, nombre_salida)
# 4. MP3 ligero para reducir la presión sobre el buffer de Audio.h
# El fix completo del OOM va en el .ino (ver abajo)
comando_ffmpeg = [
"/usr/bin/ffmpeg", "-y",
"-i", ruta_temp,
"-codec:a", "libmp3lame",
"-b:a", "48k",
"-ar", "24000",
"-ac", "1",
# FILTRO ACÚSTICO: Corta todo lo que no sea voz humana
"-af", "highpass=f=150, lowpass=f=7500",
"-map_metadata", "-1",
"-id3v2_version", "0",
"-write_xing", "0",
ruta_salida
]
subprocess.run(comando_ffmpeg, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
# 5. Limpieza del temporal
if os.path.exists(ruta_temp):
os.remove(ruta_temp)
# 6. Enviamos la orden en un hilo separado
# (evita conflicto con el runtime de InsightFace/ONNX)
def _lanzar_orden():
time.sleep(0.5) # Aseguramos que el archivo ya está en disco
_mandar_orden_reproduccion(nombre_salida)
# Limpiamos MP3 viejos DESPUÉS de que la ESP32 confirmó
for archivo in os.listdir(CARPETA_AUDIO):
if archivo.startswith("saludo_") and archivo != nombre_salida:
try:
os.remove(os.path.join(CARPETA_AUDIO, archivo))
except Exception:
pass
hilo = threading.Thread(target=_lanzar_orden, daemon=True)
hilo.start()
except Exception as e:
print(f"Error procesando el audio: {e}")
# ==============================================================================
# AUTO-ARRANQUE DEL SERVIDOR (Hilo en segundo plano)
# ==============================================================================
servidor_thread = threading.Thread(target=iniciar_servidor_http, daemon=True)
servidor_thread.start()
"""
import asyncio
from pydub import AudioSegment
import os
import threading
import http.server
import socketserver
import socket
import time
import subprocess
import urllib.request # Para enviar HTTP GET a la ESP32 (sin librerías extra)
# ================= CONFIGURACIÓN =================
IP_BOCINA = "192.168.1.77" # La IP de la ESP32 que se definio como estatica
PUERTO_ESP32 = 80 # La ESP32 escucha HTTP en el puerto 80
PUERTO_HTTP = 8000
CARPETA_AUDIO = "public_audio"
if not os.path.exists(CARPETA_AUDIO):
os.makedirs(CARPETA_AUDIO)
# ================= SERVIDOR HTTP =================
def obtener_mi_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect(('10.255.255.255', 1))
IP = s.getsockname()[0]
except Exception:
IP = '127.0.0.1'
finally:
s.close()
return IP
MI_IP = obtener_mi_ip()
def iniciar_servidor_http():
class Handler(http.server.SimpleHTTPRequestHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, directory=CARPETA_AUDIO, **kwargs)
def log_message(self, format, *args):
print(f"[SERVIDOR HTTP] Petición de ESP32: {args[0]}")
def handle(self):
try:
super().handle()
except (BrokenPipeError, ConnectionResetError):
pass
def copyfile(self, source, outputfile):
try:
super().copyfile(source, outputfile)
except (BrokenPipeError, ConnectionResetError):
pass
class ReusableTCPServer(socketserver.TCPServer):
allow_reuse_address = True
try:
with ReusableTCPServer(("", PUERTO_HTTP), Handler) as httpd:
print(f"Servidor de Audio activo en http://{MI_IP}:{PUERTO_HTTP}")
httpd.serve_forever()
except Exception as e:
print(f"ERROR CRÍTICO AL LEVANTAR EL SERVIDOR: {e}")
# ================= ORDEN A LA ESP32 =================
# La ESP32 usa HTTP GET en /play?url=..., NO WebSocket.
# Antes usábamos WebSocket al puerto 81 → la ESP32 nunca recibió nada.
def _mandar_orden_reproduccion(nombre_archivo):
url_mp3 = f"http://{MI_IP}:{PUERTO_HTTP}/{nombre_archivo}"
# Construimos la URL exacta que espera el handlePlay() de la ESP32
url_orden = f"http://{IP_BOCINA}:{PUERTO_ESP32}/play?url={url_mp3}"
try:
print(f"Ordenando a ESP32 reproducir: {url_mp3}")
with urllib.request.urlopen(url_orden, timeout=5) as respuesta:
estado = respuesta.read().decode()
print(f"ESP32 respondió: {estado}")
return True
except Exception as e:
print(f" Error enviando orden a la bocina: {e}")
return False
# ================= LÓGICA PRINCIPAL =================
def enviar_archivos_bocina(lista_archivos):
if not lista_archivos:
return
try:
# 1. Unimos los audios
audio_final = AudioSegment.empty()
for archivo in lista_archivos:
if os.path.exists(archivo):
audio_final += AudioSegment.from_file(archivo)
# 2. WAV temporal
ruta_temp = os.path.join(CARPETA_AUDIO, "temp.wav")
audio_final.export(ruta_temp, format="wav")
# 3. Nombre único anti-caché
timestamp = int(time.time())
nombre_salida = f"saludo_{timestamp}.mp3"
ruta_salida = os.path.join(CARPETA_AUDIO, nombre_salida)
# 4. MP3 ligero para reducir la presión sobre el buffer de Audio.h
# El fix completo del OOM va en el .ino (ver abajo)
comando_ffmpeg = [
"/usr/bin/ffmpeg", "-y",
"-i", ruta_temp,
"-codec:a", "libmp3lame",
"-b:a", "48k",
"-ar", "24000",
"-ac", "1",
# FILTRO ACÚSTICO: Corta todo lo que no sea voz humana
"-af", "highpass=f=150, lowpass=f=7500",
"-map_metadata", "-1",
"-id3v2_version", "0",
"-write_xing", "0",
ruta_salida
]
subprocess.run(comando_ffmpeg, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
# 5. Limpieza del temporal
if os.path.exists(ruta_temp):
os.remove(ruta_temp)
# 6. Enviamos la orden en un hilo separado
# (evita conflicto con el runtime de InsightFace/ONNX)
def _lanzar_orden():
time.sleep(0.5) # Aseguramos que el archivo ya está en disco
_mandar_orden_reproduccion(nombre_salida)
# Limpiamos MP3 viejos DESPUÉS de que la ESP32 confirmó
for archivo in os.listdir(CARPETA_AUDIO):
if archivo.startswith("saludo_") and archivo != nombre_salida:
try:
os.remove(os.path.join(CARPETA_AUDIO, archivo))
except Exception:
pass
hilo = threading.Thread(target=_lanzar_orden, daemon=True)
hilo.start()
except Exception as e:
print(f"Error procesando el audio: {e}")
# ==============================================================================
# AUTO-ARRANQUE DEL SERVIDOR (Hilo en segundo plano)
# ==============================================================================
servidor_thread = threading.Thread(target=iniciar_servidor_http, daemon=True)
servidor_thread.start()
"""

Binary file not shown.

View File

@ -1,225 +0,0 @@
#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>
#include "Audio.h"
const char* ssid = "SmartEstancia";
const char* password = "Smart12345";
IPAddress local_IP(192, 168, 1, 77);
IPAddress gateway(192, 168, 1, 254);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);
IPAddress secondaryDNS(8, 8, 4, 4);
#define I2S_BCLK 26
#define I2S_LRC 25
#define I2S_DOUT 33
Audio audio;
WebServer server(80);
void handlePlay() {
if (server.hasArg("url")) {
String url = server.arg("url");
Serial.print("🎵 Python ordenó reproducir: ");
Serial.println(url);
audio.stopSong();
audio.connecttohost(url.c_str());
server.send(200, "text/plain", "Reproduciendo OK");
} else {
server.send(400, "text/plain", "Error: Falta la URL");
}
}
// --- NUEVO: Control de Volumen ---
void handleVolume() {
if (server.hasArg("level")) {
int nivel = server.arg("level").toInt();
if (nivel >= 0 && nivel <= 21) {
audio.setVolume(nivel);
Serial.print("🔊 Volumen cambiado a: ");
Serial.println(nivel);
server.send(200, "text/plain", "Volumen OK: " + String(nivel));
} else {
server.send(400, "text/plain", "Error: Nivel debe ser 0-21");
}
} else {
server.send(400, "text/plain", "Error: Falta parametro 'level'");
}
}
void handleVolumeUp() {
int actual = audio.getVolume();
if (actual < 21) audio.setVolume(actual + 1);
server.send(200, "text/plain", "Volumen: " + String(audio.getVolume()));
}
void handleVolumeDown() {
int actual = audio.getVolume();
if (actual > 0) audio.setVolume(actual - 1);
server.send(200, "text/plain", "Volumen: " + String(audio.getVolume()));
}
void setup() {
Serial.begin(115200);
Serial.println("\n--- INICIANDO SISTEMA DE AUDIO ESP32 ---");
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
Serial.println("Fallo al configurar la IP Estatica");
}
WiFi.begin(ssid, password);
Serial.print("Conectando a WiFi");
int intento = 0;
while (WiFi.status() != WL_CONNECTED && intento < 20) {
delay(500);
Serial.print(".");
intento++;
}
if (WiFi.status() != WL_CONNECTED) {
Serial.println("\nFallo de conexion.");
while(true){ delay(1000); }
}
Serial.println("\nWiFi Conectado!");
Serial.print("IP FIJA: ");
Serial.println(WiFi.localIP());
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(15); // Volumen inicial medio
server.on("/play", HTTP_GET, handlePlay);
server.on("/volume", HTTP_GET, handleVolume);
server.on("/volume_up", HTTP_GET, handleVolumeUp);
server.on("/volume_down", HTTP_GET, handleVolumeDown);
server.begin();
Serial.println("Listo para recibir audio...");
}
void loop() {
audio.loop();
server.handleClient();
if (Serial.available()) {
String url = Serial.readStringUntil('\n');
url.trim();
if (url.length() > 5 && url.startsWith("http")) {
audio.stopSong();
audio.connecttohost(url.c_str());
}
}
}
void audio_info(const char *info){ Serial.print("INFO AUDIO: "); Serial.println(info); }
void audio_id3data(const char *info){ Serial.print("METADATOS: "); Serial.println(info); }
void audio_eof_mp3(const char *info){ Serial.print("FIN DEL AUDIO: "); Serial.println(info); }
"""
#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>
#include "Audio.h"
// =======================================================
// 1. CONFIGURACIÓN DE RED
// =======================================================
const char* ssid = "SmartEstancia";
const char* password = "Smart12345";
// --- CONFIGURACIÓN DE IP ESTÁTICA ---
IPAddress local_IP(192, 168, 1, 77); // La IP que le asiganamos a la bocina
IPAddress gateway(192, 168, 1, 254); // la IP del router
IPAddress subnet(255, 255, 255, 0); // Máscara de subred
IPAddress primaryDNS(8, 8, 8, 8); // DNS primario (Google)
IPAddress secondaryDNS(8, 8, 4, 4); // DNS secundario (Google)
// =======================================================
// 2. CONFIGURACIÓN DE PINES CORRECTOS
// =======================================================
#define I2S_BCLK 26
#define I2S_LRC 25
#define I2S_DOUT 33
Audio audio;
WebServer server(80);
void handlePlay() {
if (server.hasArg("url")) {
String url = server.arg("url");
Serial.print("🎵 Python ordenó reproducir: ");
Serial.println(url);
audio.stopSong();
audio.connecttohost(url.c_str());
server.send(200, "text/plain", "Reproduciendo OK");
} else {
server.send(400, "text/plain", "Error: Falta la URL");
}
}
void setup() {
Serial.begin(115200);
Serial.println("\n--- INICIANDO SISTEMA DE AUDIO ESP32 ---");
if (psramFound()) {
Serial.println("PSRAM encontrada.");
} else {
Serial.println(" Sin PSRAM. Usando RAM interna.");
}
// ⚡ APLICAR IP ESTÁTICA ANTES DE CONECTAR
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
Serial.println(" Fallo al configurar la IP Estática");
}
WiFi.begin(ssid, password);
Serial.print("Conectando a WiFi");
int intento = 0;
while (WiFi.status() != WL_CONNECTED && intento < 20) {
delay(500);
Serial.print(".");
intento++;
}
if (WiFi.status() != WL_CONNECTED) {
Serial.println("\n Fallo de conexión.");
while(true){ delay(1000); }
}
Serial.println("\n WiFi Conectado de verdad!");
Serial.print("Tu IP es FIJA: ");
Serial.println(WiFi.localIP());
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(18);
server.on("/play", HTTP_GET, handlePlay);
server.begin();
Serial.println("Listo para recibir audio...");
}
void loop() {
audio.loop();
server.handleClient();
if (Serial.available()) {
String url = Serial.readStringUntil('\n');
url.trim();
if (url.length() > 5 && url.startsWith("http")) {
audio.stopSong();
audio.connecttohost(url.c_str());
}
}
}
void audio_info(const char *info){ Serial.print("INFO AUDIO: "); Serial.println(info); }
void audio_id3data(const char *info){ Serial.print("METADATOS: "); Serial.println(info); }
void audio_eof_mp3(const char *info){ Serial.print("FIN DEL AUDIO: "); Serial.println(info); }
"""

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Some files were not shown because too many files have changed in this diff Show More