Update app.py
Browse files
app.py
CHANGED
|
@@ -589,7 +589,33 @@ def warmup_audit():
|
|
| 589 |
"present_default": present_default,
|
| 590 |
"missing_default": missing_default,
|
| 591 |
}
|
| 592 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 593 |
|
| 594 |
|
| 595 |
# >>> A1_BEGIN window_fix
|
|
@@ -755,6 +781,11 @@ HTML_TEMPLATE = r"""
|
|
| 755 |
#portionBand{position:absolute;top:0;height:calc(var(--thumbH,110px) + 24px);background:rgba(37,99,235,.12);pointer-events:none;display:none}
|
| 756 |
#inHandle,#outHandle{position:absolute;top:0;height:calc(var(--thumbH,110px) + 24px);width:6px;background:rgba(37,99,235,.9);border-radius:2px;cursor:ew-resize;display:none;pointer-events:auto}
|
| 757 |
.playhead{position:absolute;top:0;bottom:0;width:2px;background:var(--active-border);opacity:.9;pointer-events:none;display:block}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 758 |
</style>
|
| 759 |
<h1>🎬 Video Editor</h1>
|
| 760 |
<div class="topbar card">
|
|
@@ -776,6 +807,8 @@ HTML_TEMPLATE = r"""
|
|
| 776 |
<div style="display:flex;gap:8px;align-items:center">
|
| 777 |
<button id="warmupStartBtn" class="btn" title="Télécharger les modèles (séquentiel)">🔥 Préparer modèles</button>
|
| 778 |
<button id="warmupStopBtn" class="btn" title="Arrêter le warm-up en cours" style="display:none">⏹️ Stop warm-up</button>
|
|
|
|
|
|
|
| 779 |
<button id="warmupLogsBtn" class="btn" title="Voir les logs du warm-up">📜 Logs warm-up</button>
|
| 780 |
<span id="warmupStatus" class="muted"></span>
|
| 781 |
</div>
|
|
@@ -867,49 +900,16 @@ HTML_TEMPLATE = r"""
|
|
| 867 |
<button id="warmupCloseBtn" class="btn">Fermer</button>
|
| 868 |
</div>
|
| 869 |
</div>
|
| 870 |
-
|
| 871 |
-
|
| 872 |
-
|
| 873 |
-
<div
|
| 874 |
-
<
|
| 875 |
-
|
| 876 |
-
|
| 877 |
-
|
| 878 |
-
|
| 879 |
-
|
| 880 |
-
const statusEl = document.getElementById('status');
|
| 881 |
-
const player = document.getElementById('player');
|
| 882 |
-
const srcEl = document.getElementById('vidsrc');
|
| 883 |
-
const canvas = document.getElementById('editCanvas');
|
| 884 |
-
const ctx = canvas.getContext('2d');
|
| 885 |
-
const modeLabel = document.getElementById('modeLabel');
|
| 886 |
-
const btnEdit = document.getElementById('btnEdit');
|
| 887 |
-
const btnBack = document.getElementById('btnBack');
|
| 888 |
-
const btnSave = document.getElementById('btnSave');
|
| 889 |
-
const btnClear= document.getElementById('btnClear');
|
| 890 |
-
const posInfo = document.getElementById('posInfo');
|
| 891 |
-
const goFrame = document.getElementById('goFrame');
|
| 892 |
-
const palette = document.getElementById('palette');
|
| 893 |
-
const fileList= document.getElementById('fileList');
|
| 894 |
-
const tlBox = document.getElementById('timeline');
|
| 895 |
-
const tlNote = document.getElementById('tlNote');
|
| 896 |
-
const playerWrap = document.getElementById('playerWrap');
|
| 897 |
-
const loadingInd = document.getElementById('loading-indicator');
|
| 898 |
-
const isolerBoucle = document.getElementById('isolerBoucle');
|
| 899 |
-
const resetFull = document.getElementById('resetFull');
|
| 900 |
-
const endPortion = document.getElementById('endPortion');
|
| 901 |
-
const popup = document.getElementById('popup');
|
| 902 |
-
const popupLogs = document.getElementById('popup-logs');
|
| 903 |
-
const tlProgressFill = document.getElementById('tl-progress-fill');
|
| 904 |
-
const popupProgressFill = document.getElementById('popup-progress-fill');
|
| 905 |
-
const btnFollow = document.getElementById('btnFollow');
|
| 906 |
-
const btnFilterMasked = document.getElementById('btnFilterMasked');
|
| 907 |
-
const zoomSlider = document.getElementById('zoomSlider');
|
| 908 |
-
const maskedCount = document.getElementById('maskedCount');
|
| 909 |
-
const hud = document.getElementById('hud');
|
| 910 |
-
const toastWrap = document.getElementById('toast');
|
| 911 |
-
const gotoInput = document.getElementById('gotoInput');
|
| 912 |
-
|
| 913 |
|
| 914 |
|
| 915 |
// >>> A2B2_BEGIN warmup_dom
|
|
@@ -1162,6 +1162,90 @@ if (warmupStopBtn){
|
|
| 1162 |
refreshWarmupUI();
|
| 1163 |
// >>> A2B2_END warmup_dom
|
| 1164 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1165 |
|
| 1166 |
|
| 1167 |
|
|
|
|
| 589 |
"present_default": present_default,
|
| 590 |
"missing_default": missing_default,
|
| 591 |
}
|
| 592 |
+
@app.get("/warmup/catalog", tags=["warmup"])
|
| 593 |
+
def warmup_catalog():
|
| 594 |
+
try:
|
| 595 |
+
env = (os.getenv("WARMUP_MODELS") or "").strip()
|
| 596 |
+
base = []
|
| 597 |
+
if env:
|
| 598 |
+
try:
|
| 599 |
+
lst = json.loads(env)
|
| 600 |
+
if isinstance(lst, list) and lst:
|
| 601 |
+
base = [str(x).strip() for x in lst if str(x).strip()]
|
| 602 |
+
except Exception:
|
| 603 |
+
base = []
|
| 604 |
+
except Exception:
|
| 605 |
+
base = []
|
| 606 |
+
|
| 607 |
+
if not base:
|
| 608 |
+
base = [
|
| 609 |
+
"runwayml/stable-diffusion-v1-5",
|
| 610 |
+
"facebook/sam-vit-base",
|
| 611 |
+
"stabilityai/sd-vae-ft-mse",
|
| 612 |
+
"lixiaowen/diffuEraser",
|
| 613 |
+
"facebook/sam2-hiera-base",
|
| 614 |
+
]
|
| 615 |
+
|
| 616 |
+
seen = set()
|
| 617 |
+
out = [m for m in base if not (m in seen or seen.add(m))]
|
| 618 |
+
return {"count": len(out), "models": out}
|
| 619 |
|
| 620 |
|
| 621 |
# >>> A1_BEGIN window_fix
|
|
|
|
| 781 |
#portionBand{position:absolute;top:0;height:calc(var(--thumbH,110px) + 24px);background:rgba(37,99,235,.12);pointer-events:none;display:none}
|
| 782 |
#inHandle,#outHandle{position:absolute;top:0;height:calc(var(--thumbH,110px) + 24px);width:6px;background:rgba(37,99,235,.9);border-radius:2px;cursor:ew-resize;display:none;pointer-events:auto}
|
| 783 |
.playhead{position:absolute;top:0;bottom:0;width:2px;background:var(--active-border);opacity:.9;pointer-events:none;display:block}
|
| 784 |
+
.repo-list{max-height:320px; overflow:auto; border:1px solid var(--b); border-radius:8px; padding:6px}
|
| 785 |
+
.repo-item{display:flex; align-items:center; gap:8px; padding:6px; border-bottom:1px solid #f3f4f6}
|
| 786 |
+
.repo-item:last-child{border-bottom:none}
|
| 787 |
+
.repo-id{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size:12px}
|
| 788 |
+
|
| 789 |
</style>
|
| 790 |
<h1>🎬 Video Editor</h1>
|
| 791 |
<div class="topbar card">
|
|
|
|
| 807 |
<div style="display:flex;gap:8px;align-items:center">
|
| 808 |
<button id="warmupStartBtn" class="btn" title="Télécharger les modèles (séquentiel)">🔥 Préparer modèles</button>
|
| 809 |
<button id="warmupStopBtn" class="btn" title="Arrêter le warm-up en cours" style="display:none">⏹️ Stop warm-up</button>
|
| 810 |
+
<button id="warmupSelectBtn" class="btn" title="Sélectionner les repos à préparer">🧩 Choisir modèles</button>
|
| 811 |
+
|
| 812 |
<button id="warmupLogsBtn" class="btn" title="Voir les logs du warm-up">📜 Logs warm-up</button>
|
| 813 |
<span id="warmupStatus" class="muted"></span>
|
| 814 |
</div>
|
|
|
|
| 900 |
<button id="warmupCloseBtn" class="btn">Fermer</button>
|
| 901 |
</div>
|
| 902 |
</div>
|
| 903 |
+
<div id="warmupSelectPopup" style="display:none; position:fixed; top:24%; left:50%; transform:translate(-50%,-50%); background:#fff; padding:20px; border-radius:8px; box-shadow:0 0 10px rgba(0,0,0,0.2); z-index:1001; min-width:420px; max-width:720px; width:90%">
|
| 904 |
+
<h3>Sélection des modèles à préparer</h3>
|
| 905 |
+
<div id="repoList" class="repo-list"></div>
|
| 906 |
+
<div style="margin-top:12px; display:flex; gap:8px; justify-content:flex-end; flex-wrap:wrap">
|
| 907 |
+
<button id="selectAllBtn" class="btn">Tout cocher</button>
|
| 908 |
+
<button id="selectNoneBtn" class="btn">Tout décocher</button>
|
| 909 |
+
<button id="selectCancelBtn" class="btn">Annuler</button>
|
| 910 |
+
<button id="launchSelectedBtn" class="btn">Lancer la préparation</button>
|
| 911 |
+
</div>
|
| 912 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 913 |
|
| 914 |
|
| 915 |
// >>> A2B2_BEGIN warmup_dom
|
|
|
|
| 1162 |
refreshWarmupUI();
|
| 1163 |
// >>> A2B2_END warmup_dom
|
| 1164 |
|
| 1165 |
+
const warmupSelectBtn = document.getElementById('warmupSelectBtn');
|
| 1166 |
+
const warmupSelectPopup = document.getElementById('warmupSelectPopup');
|
| 1167 |
+
const repoListEl = document.getElementById('repoList');
|
| 1168 |
+
const selectCancelBtn = document.getElementById('selectCancelBtn');
|
| 1169 |
+
const selectAllBtn = document.getElementById('selectAllBtn');
|
| 1170 |
+
const selectNoneBtn = document.getElementById('selectNoneBtn');
|
| 1171 |
+
const launchSelectedBtn = document.getElementById('launchSelectedBtn');
|
| 1172 |
+
|
| 1173 |
+
function openSelect(){ if(warmupSelectPopup) warmupSelectPopup.style.display='block'; }
|
| 1174 |
+
function closeSelect(){ if(warmupSelectPopup) warmupSelectPopup.style.display='none'; }
|
| 1175 |
+
|
| 1176 |
+
async function loadCatalog(){
|
| 1177 |
+
if(!repoListEl) return;
|
| 1178 |
+
repoListEl.innerHTML = '<div class="muted">Chargement…</div>';
|
| 1179 |
+
try{
|
| 1180 |
+
const r = await fetch('/warmup/catalog');
|
| 1181 |
+
if(!r.ok){ repoListEl.innerHTML = '<div class="muted">Erreur de chargement.</div>'; return; }
|
| 1182 |
+
const d = await r.json();
|
| 1183 |
+
const items = Array.isArray(d.models) ? d.models : [];
|
| 1184 |
+
if(!items.length){ repoListEl.innerHTML = '<div class="muted">Aucun modèle proposé.</div>'; return; }
|
| 1185 |
+
repoListEl.innerHTML = '';
|
| 1186 |
+
items.forEach(id=>{
|
| 1187 |
+
const row = document.createElement('div'); row.className='repo-item';
|
| 1188 |
+
const cb = document.createElement('input'); cb.type='checkbox'; cb.value=id;
|
| 1189 |
+
const label = document.createElement('span'); label.className='repo-id'; label.textContent = id;
|
| 1190 |
+
row.appendChild(cb); row.appendChild(label);
|
| 1191 |
+
repoListEl.appendChild(row);
|
| 1192 |
+
});
|
| 1193 |
+
}catch(e){
|
| 1194 |
+
repoListEl.innerHTML = '<div class="muted">Erreur réseau.</div>';
|
| 1195 |
+
}
|
| 1196 |
+
}
|
| 1197 |
+
|
| 1198 |
+
if (warmupSelectBtn){
|
| 1199 |
+
warmupSelectBtn.addEventListener('click', async ()=>{
|
| 1200 |
+
await loadCatalog();
|
| 1201 |
+
openSelect();
|
| 1202 |
+
});
|
| 1203 |
+
}
|
| 1204 |
+
if (selectCancelBtn){ selectCancelBtn.addEventListener('click', closeSelect); }
|
| 1205 |
+
if (selectAllBtn){
|
| 1206 |
+
selectAllBtn.addEventListener('click', ()=>{
|
| 1207 |
+
repoListEl.querySelectorAll('input[type="checkbox"]').forEach(cb=> cb.checked=true);
|
| 1208 |
+
});
|
| 1209 |
+
}
|
| 1210 |
+
if (selectNoneBtn){
|
| 1211 |
+
selectNoneBtn.addEventListener('click', ()=>{
|
| 1212 |
+
repoListEl.querySelectorAll('input[type="checkbox"]').forEach(cb=> cb.checked=false);
|
| 1213 |
+
});
|
| 1214 |
+
}
|
| 1215 |
+
if (launchSelectedBtn){
|
| 1216 |
+
launchSelectedBtn.addEventListener('click', async ()=>{
|
| 1217 |
+
const picks = Array.from(repoListEl.querySelectorAll('input[type="checkbox"]'))
|
| 1218 |
+
.filter(cb=>cb.checked).map(cb=>cb.value);
|
| 1219 |
+
if(!picks.length){ alert('Sélectionne au moins un modèle.'); return; }
|
| 1220 |
+
window.lastRequestedModels = picks.slice();
|
| 1221 |
+
if (typeof openWarmupPopup === 'function') openWarmupPopup();
|
| 1222 |
+
if (typeof refreshWarmupUI === 'function') await refreshWarmupUI();
|
| 1223 |
+
try{
|
| 1224 |
+
const r = await fetch('/warmup/start', {
|
| 1225 |
+
method:'POST',
|
| 1226 |
+
headers:{ 'Content-Type':'application/json' },
|
| 1227 |
+
body: JSON.stringify({ models: picks })
|
| 1228 |
+
});
|
| 1229 |
+
if(!r.ok){
|
| 1230 |
+
const t = await r.text();
|
| 1231 |
+
alert('Échec démarrage: ' + r.status + ' ' + t);
|
| 1232 |
+
return;
|
| 1233 |
+
}
|
| 1234 |
+
if (typeof refreshWarmupUI === 'function') {
|
| 1235 |
+
const id = setInterval(async ()=>{
|
| 1236 |
+
await refreshWarmupUI();
|
| 1237 |
+
try{
|
| 1238 |
+
const s = await (await fetch('/warmup/status')).json();
|
| 1239 |
+
if (!s.running) clearInterval(id);
|
| 1240 |
+
}catch(e){ clearInterval(id); }
|
| 1241 |
+
}, 1000);
|
| 1242 |
+
}
|
| 1243 |
+
closeSelect();
|
| 1244 |
+
}catch(e){
|
| 1245 |
+
alert('Erreur réseau.');
|
| 1246 |
+
}
|
| 1247 |
+
});
|
| 1248 |
+
}
|
| 1249 |
|
| 1250 |
|
| 1251 |
|