v2.2 — ComfyUI Portrait Generation
Features:
- 🖼️ Portrait Button im Chat-Header
- /api/comfyui/status: Prüft ob ComfyUI läuft
- /api/character/{name}/portrait: Generiert Profilbild via ComfyUI
- comfyui_integration.py: ComfyUI API Client
- NoobAI-XL Checkpoint
- 25 Steps, DPM++ 2M Karras
- 512x512 Portrait
- Auto-Copy zu static/avatars/
- UI: Avatar wird nach Generierung ersetzt
- UI: Button zeigt Status (ComfyUI nicht erreichbar = ausgegraut)
- Workflow: Character-Beschreibung → ComfyUI Prompt → Bild → Avatar
Voraussetzung: ComfyUI muss auf localhost:8188 laufen
This commit is contained in:
@@ -70,6 +70,7 @@
|
||||
<div class="header-actions">
|
||||
<span class="session-info" id="sessionInfo" title="Session-ID">Session: ...</span>
|
||||
<span class="session-info" id="passcodeInfo" title="Passcode für andere Geräte" style="border-color: var(--accent); color: var(--accent);">Code: ...</span>
|
||||
<button class="btn" id="portraitBtn" onclick="generatePortrait()">🖼️ Portrait</button>
|
||||
<button class="btn" onclick="toggleMemory()">🧠 Gedächtnis</button>
|
||||
<button class="btn btn-danger" onclick="clearMemory()">🗑️ Vergessen</button>
|
||||
</div>
|
||||
@@ -291,6 +292,46 @@
|
||||
{% if not history %}
|
||||
loadHistory();
|
||||
{% endif %}
|
||||
|
||||
// Check ComfyUI status on load
|
||||
fetch('/api/comfyui/status').then(r => r.json()).then(data => {
|
||||
if (!data.running) {
|
||||
const btn = document.getElementById('portraitBtn');
|
||||
btn.title = 'ComfyUI läuft nicht — starte ComfyUI zuerst';
|
||||
btn.style.opacity = '0.5';
|
||||
}
|
||||
});
|
||||
|
||||
async function generatePortrait() {
|
||||
const btn = document.getElementById('portraitBtn');
|
||||
const oldText = btn.textContent;
|
||||
btn.textContent = '⏳ Generiert...';
|
||||
btn.disabled = true;
|
||||
|
||||
try {
|
||||
const resp = await fetch(`/api/character/${encodeURIComponent(charFilename)}/portrait`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({})
|
||||
});
|
||||
const data = await resp.json();
|
||||
if (resp.ok && data.image) {
|
||||
// Update avatar in header
|
||||
const avatarEl = document.querySelector('.avatar');
|
||||
avatarEl.innerHTML = `<img src="${data.image}?t=${Date.now()}" style="width: 100%; height: 100%; border-radius: 50%; object-fit: cover;">`;
|
||||
btn.textContent = '✅ Fertig!';
|
||||
setTimeout(() => { btn.textContent = oldText; btn.disabled = false; }, 2000);
|
||||
} else {
|
||||
alert(data.error || 'Generierung fehlgeschlagen');
|
||||
btn.textContent = oldText;
|
||||
btn.disabled = false;
|
||||
}
|
||||
} catch(e) {
|
||||
alert('Verbindungsfehler: ' + e.message);
|
||||
btn.textContent = oldText;
|
||||
btn.disabled = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user