Zonza : dictée vocale locale macOS (MLX-Whisper + cercle pulsant)

Reconstruction propre de l'ancien projet Dictée. Bundle id neuf
(cloud.mrtechlab.zonza), chemin de build unique vers /Applications
(plus jamais de builds /tmp enregistrés dans LaunchServices).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 23:57:59 +02:00
co-authored by Claude Fable 5
commit 22080eb997
18 changed files with 955 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
"""Génère assets/icon.png (1024×1024) : un micro stylisé sur un carré violet dégradé.
Reproductible et sans dépendance externe (Pillow seulement). Lancer : python assets/make_icon.py
"""
import os
from PIL import Image, ImageDraw
SIZE = 1024
BG_TOP = (130, 80, 235) # violet
BG_BOT = (85, 50, 180) # violet plus foncé (dégradé vertical)
MIC = (255, 255, 255)
def _rounded_gradient(size, radius):
"""Carré arrondi avec dégradé vertical."""
base = Image.new("RGBA", (size, size), (0, 0, 0, 0))
grad = Image.new("RGBA", (size, size))
for y in range(size):
t = y / (size - 1)
r = int(BG_TOP[0] * (1 - t) + BG_BOT[0] * t)
g = int(BG_TOP[1] * (1 - t) + BG_BOT[1] * t)
b = int(BG_TOP[2] * (1 - t) + BG_BOT[2] * t)
for x in range(size):
grad.putpixel((x, y), (r, g, b, 255))
mask = Image.new("L", (size, size), 0)
ImageDraw.Draw(mask).rounded_rectangle([0, 0, size, size], radius=radius, fill=255)
base.paste(grad, (0, 0), mask)
return base
def make_icon(path):
img = _rounded_gradient(SIZE, radius=int(SIZE * 0.22))
d = ImageDraw.Draw(img)
cx = SIZE / 2
# corps du micro (capsule arrondie)
mic_w, mic_h = SIZE * 0.26, SIZE * 0.40
top = SIZE * 0.20
d.rounded_rectangle(
[cx - mic_w / 2, top, cx + mic_w / 2, top + mic_h],
radius=mic_w / 2, fill=MIC,
)
# arceau (support en U sous le micro)
arc_r = SIZE * 0.20
arc_cy = top + mic_h * 0.55
d.arc(
[cx - arc_r, arc_cy - arc_r, cx + arc_r, arc_cy + arc_r],
start=20, end=160, fill=MIC, width=int(SIZE * 0.035),
)
# pied du micro
foot_top = arc_cy + arc_r
d.line([cx, foot_top, cx, foot_top + SIZE * 0.10], fill=MIC, width=int(SIZE * 0.035))
d.line(
[cx - SIZE * 0.10, foot_top + SIZE * 0.10, cx + SIZE * 0.10, foot_top + SIZE * 0.10],
fill=MIC, width=int(SIZE * 0.035),
)
os.makedirs(os.path.dirname(path), exist_ok=True)
img.save(path)
print(f"icône écrite : {path}")
if __name__ == "__main__":
here = os.path.dirname(os.path.abspath(__file__))
make_icon(os.path.join(here, "icon.png"))