File size: 29,440 Bytes
374892b
 
d920b40
 
 
 
 
73da8fb
 
 
 
374892b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92ca4bb
374892b
 
 
 
 
 
 
 
 
 
4b25dd6
374892b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2cfbfa1
 
 
 
 
 
 
 
 
 
 
 
 
d920b40
 
 
 
 
374892b
 
73da8fb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374892b
d920b40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374892b
 
 
 
 
 
 
 
 
2cfbfa1
 
 
73da8fb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8e18f37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73da8fb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92ca4bb
 
73da8fb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
# smoothloopv3 — diário de bordo (LoRA MiniMax H3)

> **ESTADO EM 2026-09-19 11:0x** — migrado para outra instância e **treinando**.
> A instância 51502554 perdeu a GPU no step 191 (falha de host). Migramos para a **51567720**
> usando o runbook desta nota: restauração completa em ~25 min, views religadas pelo manifesto
> batendo 963/491/298, treino relançado às 10:37. Medido: **11,75 s/it**, VRAM 25,1/32 GB,
> samples do step 0 gerados e no HF.
>
> **Para retomar em outra máquina: vá direto para a seção "RETOMADA EM OUTRA MÁQUINA" no fim
> deste arquivo.** Não refaça captions, conversão, views nem cache — tudo está pronto no HF.

Início: 2026-09-19. GPU: RTX 5090 32 GB (driver 595.91.07, CUDA 13.2).
Disco: overlay 350 GB, **NÃO é volume persistente** (`df` mostra overlay em /workspace).
→ Tudo que importa precisa ir para o HF. Recycle/destroy apaga tudo.

## Decisões fixadas
- Trainer: fork AkaneTendo25/musubi-tuner, branch minimax-h3, pin `ede9ed9f...` (relatório 18/09).
- Receita base: v3 (rank/alpha 32, LR 5e-5, AdamW8bit, sem preservation, guidance 4/sigma/normalized,
  jitter 0.2, swap 32, SDPA, convrot int8, AdaLN rank 16, fused qk/rope).
- HF: conta AdwolfCzar, padrão `minih33`, público + gated manual, sem "minimax" no nome.

## Descobertas
| # | Quando | Achado |
|---|---|---|
| 1 | 02:5x | `captionkreator` é repo privado; acesso via `$GITHUB_TOKEN` (ghp_...) do ambiente. |
| 2 | 02:5x | Tokens HF no ambiente: `HF_TOKEN`→AdwolfCzar, `HF_TOKEN_USER`→adbrasi. hf-xet 1.6.0 presente. |
| 3 | 02:5x | Mega: `megatools` (apt) baixa link público de pasta sem login. rclone não tinha config. |
| 4 | 02:5x | Dataset traz `.txt` com **tags danbooru** (não captions). O perfil smoothloop NÃO as usa como |
|   |        | entrada (user.md só manda `Animation type: {{folder}}` + vídeo) e o `run` **sobrescreve** o .txt. |
|   |        | → Backup das tags antes de rodar o captioner. |
| 5 | 02:5x | Amostra inicial: 512x384, **10 fps**, 16 frames (1,6 s), sem áudio, tag `looping_animation`. |
|   |        | `captioner convert` (smoothloop) resolve: fps 24 + `loop:true`/`min_duration:5` (tiling de ciclos |
|   |        | inteiros) + `max_edge 1280` + CFR. Substitui o `extend_loops.py` histórico. |
| 6 | 02:5x | `OPENROUTER_API_KEY` presente no ambiente (perfil smoothloop usa openrouter). |
| 7 | 03:1x | Venv estava **sem torch** (ambiente novo, nao o de agosto). Instalado torch 2.10.0+cu130 |
|   |        | (combo validado no historico); `torch.cuda` ok, cc (12,0) = Blackwell. |
|   |        | `/venv/main` exigiu `sudo chown -R claude:claude` antes de instalar (armadilha ja no NOTES). |
| 8 | 03:1x | Mega a 0,57 MB/s com `megadl` (sequencial) = 3,6 h. Escrevi downloader paralelo |
|   |        | (`/workspace/scripts/mega_folder_dl.py`, API do Mega + AES-CTR, 16 conexoes) -> **4,1 MB/s**, |
|   |        | ETA ~30 min. Retoma o que o megadl ja tinha baixado (compara tamanho). |
| 9 | 03:1x | Dataset real: **7,82 GB, 1749 mp4 + 1752 txt**, raiz `smoothlooper_v3_datasetCRU` com |
|   |        | subpastas `1`..`6` (mp4 por pasta: 1=180, 2=521, 3=~471, 4=76, 5=39, 6=463). |
|   |        | A estrutura 1..6 e exatamente o que o perfil smoothloop espera (`Animation type: {{folder}}`). |
| 10| 03:2x | **BUG no template do handoff**: `--save_last_n_steps_state` NAO existe no pin ede9ed9f. |
|   |        | So existe `--save_last_n_checkpoints N`, que apaga LoRAs antigos junto com os states. |
|   |        | Decisao: NAO passar retencao nenhuma (guarda todos os LoRAs p/ checkpoint picking) e deixar |
|   |        | o meu uploader apagar states antigos localmente depois de confirmados no HF. |
| 11| 03:2x | O trainer tem upload HF embutido (`--huggingface_repo_id`, `--async_upload`), mas nao cobre |
|   |        | os samples mp4. Vou usar uploader proprio (watcher) como no historico. |
| 12| 03:1x | `captioner convert` (smoothloop) validado em 3 clipes reais: 604x504@14,6fps/2,19s -> 24fps/6,58s/158f; |
|   |        | 512x384@10fps/1,6s -> 24fps/6,29s/151f; 1080x1920@60fps -> **720x1280** (max_edge 1280)/24fps/160f. |
|   |        | Dataset e heterogeneo (retrato/paisagem/quadrado, 10-60 fps). Tiling entrega ~150-160f > 124f. |
| 13| 03:2x | **`OPENROUTER_API_KEY` do ambiente estava EXPIRADA** ("API key expired"). Usuario forneceu chave nova, |
|   |        | gravada em `/workspace/.env` (chmod 600). Sem limite, sem expiracao. |
| 14| 03:3x | `captioner run` NAO pula arquivos que ja tem .txt (Skipped 0) -> as tags danbooru SAO sobrescritas. |
|   |        | Backup obrigatorio antes. Custo medido: **$0,0024 / 3 videos** => ~$1,40 para os 1749. |
| 15| 03:3x | Decisao do usuario: samples usam o **primeiro frame** (casa com o contrato "<Picture 1> em 0.00s"). |
| 16| 03:4x | Meu downloader tinha bug: o campo `k` do Mega traz varias entradas `handle:chave` separadas |
|   |        | por `/` (pasta compartilhada). `split(":")[1]` pegava lixo -> **147 arquivos indecifraveis**. |
|   |        | Corrigido testando todas as entradas. Dataset integro: 3501 = 1749 txt + 1651 mp4 + 101 webm. |
| 17| 03:4x | Inventario do bruto: fps caotico (30/16/60/24/10/29,97/25/33,33/6,67/12,5/5/20/4...), |
|   |        | resolucoes de 486x1080 a 3840x2160, **480 clipes COM audio** (historico tinha zero), |
|   |        | duracao mediana 5,53 s / p90 20 s / max 85,9 s. 51,3% ja >=124f a 24fps. |
| 18| 03:5x | **BUG no captionkreator (corrigido)**: fontes de fps baixo (4-12) falhavam a conversao com |
|   |        | "duration changed from 6.000s to 5.750s" -> ~11% do dataset. Duas causas: `-stream_loop` |
|   |        | com uma copia a menos do que o `-t` precisa, e tolerancia usando o fps ALVO em vez do da FONTE. |
|   |        | Branch `fix/low-fps-duration`, commit `5f9ffe4`, **publicado** em github.com/adbrasi/captionkreator. Suite: os mesmos 10 testes |
|   |        | falham com e sem o patch (pre-existentes, versao do ffmpeg do container). |
| 19| 03:5x | Armadilha do NOTES confirmada 2x na pratica: `pgrep/pkill -f <padrao>` casa com o proprio |
|   |        | shell e mata a sessao. Passei a gravar PID em arquivo (`/workspace/logs/*.pid`). |
| 20| 04:0x | Projecao de disco: dataset convertido fica **menor** que o bruto (fator 0,45x; max_edge 1280 |
|   |        | reduz fontes 4K/1440p, max_duration 10s corta as longas). ~4 GB convertido + ~4 GB zip + |
|   |        | ~18 GB cache + ~1,1 GB por checkpoint. Total ~35 GB contra 239 GB livres. |
|   |        | ComfyUI do usuario: 9,3 GB (8,1 GB so o venv dele) - irrelevante, mantido a pedido. |
|   |        | Gargalo real e VRAM (treino ~18-24 GB dos 32 GB), nao disco: nao rodar ComfyUI junto. |
| 21| 04:1x | Segunda iteracao do fix de fps baixo: tolerancia `1,05/source_fps` errava por 0,5 ms num |
|   |        | clipe 888x888 a 6,67 fps (deficit 0,158 s vs limite 0,1575 s). Corrigida para |
|   |        | `1/source_fps + 2/target_fps`. Commit `5f9ffe4` (publicado). 1 unico arquivo do dataset era afetado. |
| 22| 04:3x | Dataset convertido: **100% a 24 fps**, lado maior <=1280, 1752 mp4 / 0 webm, 4,3 GB. |
|   |        | Mediana 183f (7,6 s), p75 239f, max 240f (teto de 10 s). 96% >=124f. |
| 23| 04:4x | **Captions: 1752/1752, zero falhas, $0,65** (17,9 M tokens in / 1,28 M out). |
|   |        | Validacao pasta->gatilho: 180 static / 522 slow / 472 smooth / 76 intense / 39 turntable / |
|   |        | 463 chroma-key = **100% corretos**, zero contaminacao cruzada. |
| 24| 04:4x | **Decisao do usuario: respeitar o minimo do H3 de 5 s.** No grid 17k+5 o valor acima de 5 s |
|   |        | e 124f (5,17 s) -> NENHUMA view abaixo disso. Descartados os esquemas com f107/f90/f73 |
|   |        | (inclusive a receita do smoothloop historico). Esquema final: 3 areas (512x288/640x384/ |
|   |        | 832x480, quotas 55/28/17) **todas em f124**, estratificadas por resolucao de origem. |
|   |        | Tokens medios de video ~7870; ancora historica mais proxima = quick (124f multi-res) 12,8 s/it, |
|   |        | mas este pin tem fused_qk_norm_rope + fixes de recompilacao/sync, entao esperar menos. |
| 25| 04:4x | 70 clipes (4%) sairam com 117-123f. Reconvertidos com perfil derivado `smoothloop_min124` |
|   |        | (min_duration 5.3, max_duration 12) para ganhar um ciclo inteiro a mais. |
| 26| 04:4x | Armadilha nova: `captioner` consome stdin; dentro de `while read -r f` ele come caracteres |
|   |        | do caminho lido (paths viravam "orkspace/..."). Fix: `</dev/null` no comando interno. |
| 27| 04:4x | Armadilha nova: `:` sem aspas em `description:` do profile.yaml quebra o parse YAML |
|   |        | ("mapping values are not allowed here") e o convert falha sem dizer qual arquivo. |
| 28| 05:0x | Dataset FINAL: 1752 clipes, 100% 24 fps, **100% >=124f** (min exatamente 124 = 5,17 s), |
|   |        | 1752/1752 com caption H3. Mediana 191f, max 246f. 4,3 GB. |
| 29| 05:0x | Views (estratificadas por px da fonte, seed 42): v288 963 / v384 491 / v480 298 = 1752. |
|   |        | So 6 clipes (0,3%) tem fonte abaixo da area de 512x288; com bucket_no_upscale eles treinam |
|   |        | no bucket nativo menor, que e o comportamento correto. |
| 30| 05:0x | Dataset publicado: huggingface.co/datasets/AdwolfCzar/smoothloopv3_dataset (zip -0 + backup |
|   |        | das tags danbooru). Upload via xet a ~76 MB/s. |
| 31| 05:0x | Samples: 3 previews cobrindo paisagem/quadrado/retrato E tipos smooth/slow/static. |
|   |        | 832x480 seed42 / 576x704 seed43 / 480x832 seed44, todos 124f, 20 passos. |
|   |        | Troquei o 2o sorteio: o clipe tinha a moldura inteira girando (cunhas pretas), ruim como |
|   |        | referencia de monitoramento. Substituido por um com fundo liso, que isola o movimento. |
| 32| 05:0x | **SMOKE LEG 1 PASSOU**: 10 steps (loss 0,074), samples nos steps 0/5/10 (9 mp4 + json |
|   |        | validos: 832x480 / 576x704 / 480x832, todos 124f a 24 fps), checkpoints 5 e 10 + states. |
|   |        | **~10 s/it** nos itens MAIS PESADOS (melhor que a ancora historica de 12,8 s/it). |
|   |        | VRAM: pico 15,1 GiB reservado no sampling; 15,3 GiB em uso durante os steps. Folga grande |
|   |        | nos 32 GB com swap 32. |
|   |        | Custo de sampling medido: ~113 s por preview (101,6 s denoising + 11,7 s decode) => ~6 min |
|   |        | por evento de 3 previews. A cada 500 steps (~83 min) isso e ~7% de overhead. |
| 33| 05:0x | Conversao ComfyUI validada: 600 tensores do trainer -> 400 com chaves `diffusion_model.*`, |
|   |        | 569 MB. O uploader gera essa versao automaticamente a cada checkpoint. |
| 34| 06:0x | Smoke leg 2 (resume) PASSOU: retomou de global_step=10, pulou 10 batches, foi a 15. |
|   |        | Loss 0,074 -> 0,046. Gatilho de parada confirmado no codigo (trainer_base.py:2462, |
|   |        | poll_checkpoint_request_files a cada optimizer step). |
| 35| 08:2x | **CACHE COMPLETO**: 21,5 GB (v288 9,6 / v384 6,5 / v480 5,4), 3504 arquivos = |
|   |        | 1752 latentes + 1752 TE. Preflight de captions passou com 1752 itens. |
|   |        | Latentes ~2,5 h (GPU 100%, VAE-bound), TE ~20 min. Serial, como manda o historico. |
| 36| 08:4x | **TREINO LANCADO** (`minih33_smoothloopv3`), 6000 steps de teto, save+sample a cada 500. |
|   |        | Medido: **12,07 s/it**, loss 0,0996 -> 0,0952 nos primeiros 33 steps. |
|   |        | **VRAM 25,1 GB / 32 GB** - bem acima dos 15,3 GB do smoke (dataset real tem mais variedade |
|   |        | de bucket). Folga ~7 GB. Historico teve OOM no step ~4502 com swap 24; aqui swap 32. |
|   |        | MONITORAR: se passar de ~29 GB, reiniciar com BLOCKS_TO_SWAP=40 e RESUME=1. |
| 37| 08:4x | Uploader em tempo real ativo: sobe checkpoint + versao _comfy + samples mp4/json + tb, |
|   |        | e apaga states locais antigos (mantem 2). Samples do step 0 ja no HF. |
| 38| 11:0x | **Treino rodando na maquina nova**: 11,75 s/it, loss ~0,10 no step 46 (warmup 50 ainda em |
|   |        | curso), VRAM 25,1/32 GB, GPU 82 C. Samples do step 0 (832x480 / 576x704 / 480x832, 124f) |
|   |        | gerados e no HF. `train_supervisor.sh` relanca sozinho com RESUME=1 se o processo cair. |
| 39| 11:0x | SAVE_EVERY baixado para **250** (era 500) apos a queda: perder 250 steps custa ~50 min em vez |
|   |        | de ~100. SAMPLE_EVERY continua 500 (o sampling e o que custa ~6 min por evento). |

## Bugs / incidentes

### 2026-09-19 09:38 — GPU caiu do barramento durante o treino (NAO resolvido de dentro)
Treino morreu no **step 191** (11,59 s/it, loss 0,0795). `nvidia-smi` passou a responder
`Unable to determine the device handle for GPU0: 0000:81:00.0: Unknown Error / No devices were found`.
Os device nodes (`/dev/nvidia*`) continuavam existindo, mas o driver nao falava mais com a placa.
`vastai show instance` reportou `actual_status: offline` com `cur_state: running` — ou seja, a
propria Vast perdeu contato: **falha de host, nao do treino** (nao houve OOM, nao houve erro CUDA).

Num container sem privilegios nao da para resetar a GPU, recarregar o modulo nem re-escanear o
barramento PCI. Unica recuperacao seria reiniciar a instancia pela API da Vast (preserva o
filesystem do container); o usuario optou por esperar, dizendo que isso as vezes acontece e volta.

Perda: 191 steps (~37 min). Nenhum checkpoint existia ainda porque o primeiro save era no 500.
**Acao tomada:** `SAVE_EVERY` baixado de 500 para **250** no relancamento, e um watchdog
(`/workspace/scripts/watch_gpu_relaunch.sh`) que testa a GPU a cada 60 s, exige 45 s de
estabilidade e relanca o treino sozinho.

Nada mais foi perdido: dataset, captions, cache (22 GB) e samples sobreviveram, e desde entao
estao todos espelhados no HF.

### 2026-09-19 10:0x — migração para a instância 51567720 (bem-sucedida)

A antiga (51502554) era **69,21% de confiabilidade, host não verificado, GPU a 89 °C** — perfil de
máquina que solta a GPU do barramento, e foi o que aconteceu. A nova é **94,87%, verificada,
39 °C em repouso**, 12% mais cara ($0,691 vs $0,617/h).

| | antiga | nova | impacto medido |
|---|---|---|---|
| PCIe | 4.0 ×16, 27,0 GB/s | **3.0 ×16, 12,2 GB/s** | **nenhum** (ver abaixo) |
| RAM | 80/128,7 GB | 193,2 GB | mais folga p/ pinned memory |
| CPU | 48/48 | 26/104 | irrelevante (8 workers no dataloader) |
| Disco | 4986 MB/s | 2279 MB/s | irrelevante (lemos latentes cacheados) |
| Driver / Max CUDA | 595.91.07 / 13.2 | 580.178.04 / **13.0** | torch cu130 funcionou normalmente |
| Kernel / usuário | 5.15.0-191 / uid 1002 | 6.8.0-139 / **uid 0 (root)** | nenhum |

**Previsão minha que estava ERRADA:** estimei que o PCIe 3.0 custaria 3–8% por step (12,1 →
12,5–13,0 s/it), porque `blocks_to_swap 32` atravessa o barramento a cada step. Medido:
**11,75 s/it**, dentro do ruído da máquina antiga (11,59–12,07). `--block_swap_h2d_only` com
ring 2 esconde as transferências atrás do compute melhor do que eu supus — coerente com a nota
histórica de que o H3 é compute-bound e o swap custa ~5%.

**A sessão do Claude Code migrou junto.** Não existe recurso oficial para mover uma sessão local
entre máquinas: Remote Control só dirige de longe uma sessão que continua rodando na máquina
original, e `--teleport` só puxa sessões que nasceram na nuvem. O caminho suportado é copiar o
transcript (`~/.claude/projects/<cwd-escapado>/<session-id>.jsonl`) e rodar
`claude --resume <caminho-absoluto-do-.jsonl>`, que ignora diferenças de diretório.
Scripts: `export_session.sh` (empacota) e `restore_session.sh` (restaura do outro lado).
**O transcript contém credenciais em texto puro** — não subir para repo público.

**Tempo total da migração:** ~25 min de restauração desacompanhada (88 GB de pesos + 4 GB de
dataset + 22 GB de cache), com o `restore_on_new_machine.sh` conferindo cada contagem.

## Progresso
- [x] Ler relatório + NOTES + handoff
- [x] Acesso Mega, GitHub, HF validados
- [x] Download dataset Mega (7,3 GB, 1752 midias em 6 pastas de tipo de animacao)
- [x] Backup tags + convert + captions (1752/1752, $0,65, gatilhos 100% corretos)
- [x] Upload dataset (zip + xet) para HF
- [x] Download pesos H3 (82 GB, Comfy-Org/MiniMax-H3: DiT fl2va bf16, TE nvfp4_awq, 2 VAEs)
- [x] Views/buckets + TOMLs (3 areas, todas f124)
- [ ] Samples (3 vídeos aleatórios, first frame + caption)
- [x] Smoke test + resume (leg1 10 steps + leg2 resume ate 15, ambos exit 0)
- [x] Cache completo (21,5 GB)
- [x] Treino lancado + uploader em tempo real ativo

---

# RETOMADA EM OUTRA MÁQUINA — runbook completo

Escrito em 2026-09-19 depois que a GPU desta instância caiu do barramento no step 191.
**Tudo que está abaixo já foi decidido, executado e verificado. Não refaça nada disso.**

## 0. O que NÃO precisa ser refeito

| Etapa | Situação | Onde está |
|---|---|---|
| Download do dataset do Mega | pronto | zip no HF |
| Normalização 24 fps CFR + tiling de loop + max_edge 1280 | pronto | dentro do zip |
| Correção dos 70 clipes <124f | pronto | dentro do zip |
| Captions H3 (1752/1752, $0,65) | pronto | dentro do zip, sidecar `.txt` |
| Escolha das views e quotas | **decidida** | `manifest_views.csv` |
| TOMLs de cache e treino | prontos | `configs/` no repo do modelo |
| 3 imagens de sample + prompts + seeds | prontos | `samples/` no repo do modelo |
| Cache de latentes + text encoder (22 GB, ~2,5 h de GPU) | pronto | tar no repo do dataset |
| Smoke test (10 steps + resume até 15) | passou | — |

Só falta **rodar o treino**.

## 1. Artefatos no Hugging Face

Repo do dataset — `AdwolfCzar/smoothloopv3_dataset` (público, gated manual):
- `smoothloopv3_dataset.zip` (3,88 GB) — 1752 mp4 já convertidos + 1752 `.txt` com as captions H3
- `cache/cache_smoothloopv3_pin_ede9ed9f.tar` (22,81 GB) — latentes + TE, **amarrado ao pin `ede9ed9f`**
- `tags_danbooru_originais.tar.gz` — tags originais que o captioner sobrescreveu (não são usadas no treino)

Repo do modelo — `AdwolfCzar/minih33-smoothloopv3` (público, gated manual):
- `configs/` — TOMLs, scripts de cache/treino, uploader, scripts auxiliares
- `samples/previews_20260919/` — 3 PNGs, `sample_prompts.txt`, `sample_manifest.json`
- `manifest_views.csv` — **congela qual clipe vai para qual view** (crítico, ver §4)
- `PROGRESSO.md` — este diário

## 2. Ambiente exato que funcionou

```
GPU        RTX 5090 32 GB (sm_120 / cc 12.0), driver 595.91.07, CUDA 13.2
python     3.12.14 em /venv/main
torch      2.10.0+cu130     <- NÃO troque; instale com --index-url .../whl/cu130
transformers 4.57.6   accelerate 1.6.0   safetensors 0.4.5   hf_hub 0.34.3
av 14.0.1   bitsandbytes 0.50.2   diffusers 0.32.1   einops 0.7.0
tensorboard 2.21.0   toml 0.10.2   voluptuous 0.15.2   hf-xet 1.6.0
ffmpeg     6.1.1
trainer    AkaneTendo25/musubi-tuner, branch minimax-h3, commit ede9ed9f769d605db32d37e32243d4c979f9eee3
```

Se `/venv/main` der `Permission denied` ao instalar: `sudo chown -R claude:claude /venv/main`.

## 3. Montagem da máquina nova

**Atalho:** todos os passos 3 a 4 estão empacotados em um script idempotente.
Baixe `configs/restore_on_new_machine.sh` do repo do modelo e rode:

```bash
export HF_TOKEN=<token da conta AdwolfCzar>
bash restore_on_new_machine.sh
```

Ele instala o trainer no pin, baixa os pesos, o dataset pronto e o cache, restaura
configs/samples/manifesto e religa as views pelo manifesto — conferindo as contagens
em cada etapa. Se cair no meio, rode de novo: ele pula o que já está pronto.

O passo a passo manual abaixo é a mesma coisa, caso queira fazer à mão ou entender
o que o script faz.


```bash
export HF_TOKEN=<token da conta AdwolfCzar>
source /venv/main/bin/activate
sudo chown -R claude:claude /venv/main   # se necessário

# 3.1 trainer no pin auditado
git clone https://github.com/AkaneTendo25/musubi-tuner.git /workspace/projects/musubi-tuner
cd /workspace/projects/musubi-tuner
git fetch origin minimax-h3 && git checkout ede9ed9f769d605db32d37e32243d4c979f9eee3
uv pip install torch==2.10.0 torchvision --index-url https://download.pytorch.org/whl/cu130
uv pip install -e . && uv pip install tensorboard

# 3.2 pesos (~88 GB, xet é rápido) — SÓ estes 4 arquivos
python - <<'PY'
from huggingface_hub import hf_hub_download
for f in ["diffusion_models/minimax_h3_fl2va_bf16.safetensors",
          "text_encoders/qwen3vl_32b_minimax_h3_nvfp4_awq.safetensors",
          "vae/minimax_h3_video_vae_fp16.safetensors",
          "vae/minimax_h3_audio_vae_fp32.safetensors"]:
    hf_hub_download("Comfy-Org/MiniMax-H3", f, local_dir="/workspace/models/MiniMax-H3")
PY

# 3.3 dataset pronto (NÃO recaptionar, NÃO reconverter)
python - <<'PY'
from huggingface_hub import hf_hub_download
hf_hub_download("AdwolfCzar/smoothloopv3_dataset","smoothloopv3_dataset.zip",
                repo_type="dataset", local_dir="/workspace/datasets")
PY
cd /workspace/datasets && unzip -q smoothloopv3_dataset.zip   # cria smoothloopv3_work/{1..6}

# 3.4 cache pronto (pula ~2,5 h de GPU)
python - <<'PY'
from huggingface_hub import hf_hub_download
hf_hub_download("AdwolfCzar/smoothloopv3_dataset","cache/cache_smoothloopv3_pin_ede9ed9f.tar",
                repo_type="dataset", local_dir="/workspace/dl")
PY
mkdir -p /workspace/cache && tar xf /workspace/dl/cache/cache_smoothloopv3_pin_ede9ed9f.tar -C /workspace/cache

# 3.5 configs, scripts e samples
python - <<'PY'
from huggingface_hub import snapshot_download
snapshot_download("AdwolfCzar/minih33-smoothloopv3",
                  allow_patterns=["configs/*","samples/*","manifest_views.csv"],
                  local_dir="/workspace/restore")
PY
mkdir -p /workspace/projects/h3_smoothloopv3/{configs,output,samples} /workspace/scripts /workspace/notes
cp /workspace/restore/configs/*.toml /workspace/projects/h3_smoothloopv3/configs/
cp /workspace/restore/configs/*.sh /workspace/restore/configs/*.py /workspace/scripts/
cp /workspace/restore/manifest_views.csv /workspace/notes/
cp -r /workspace/restore/samples/previews_20260919 /workspace/projects/h3_smoothloopv3/samples/
chmod +x /workspace/scripts/*.sh
```

**Os caminhos acima não são sugestão, são requisito.** `sample_prompts.txt` e os TOMLs guardam
caminhos absolutos; se a árvore mudar, o sampling não acha as PNGs e o trainer não acha o cache.

## 4. Religar as views — o passo que não pode ser improvisado

Os arquivos de cache são indexados pelo **stem** do item (`1_8xsg9eu5sz`). Rodar
`assign_views.py` de novo re-sorteia a distribuição e **invalida os 22 GB de cache**.
Use sempre o manifesto congelado:

```bash
python /workspace/scripts/rebuild_views_from_manifest.py \
  --manifest /workspace/notes/manifest_views.csv \
  --dataset  /workspace/datasets/smoothloopv3_work \
  --out      /workspace/datasets/views_smoothloopv3
```

Deve imprimir exatamente `v288: 963 · v384: 491 · v480: 298` (1752 itens) e sair com código 0.
O script falha de propósito se algum arquivo faltar, porque nesse caso o cache não casaria.
Verificado nesta máquina: a reconstrução pelo manifesto bate 100% com as views originais
(hash idêntico das três listas).

## 5. Lançar o treino

```bash
cd /workspace
DATASET_CONFIG=/workspace/projects/h3_smoothloopv3/configs/dataset_smoothloopv3_train.toml \
SAMPLE_PROMPTS=/workspace/projects/h3_smoothloopv3/samples/previews_20260919/sample_prompts.txt \
RUN_NAME=minih33_smoothloopv3 MAX_STEPS=6000 SAVE_EVERY=250 SAMPLE_EVERY=500 \
nohup bash /workspace/scripts/train_smoothloopv3.sh > /workspace/logs/train.log 2>&1 &

# uploader em tempo real (obrigatório: /workspace não é volume, some no recycle)
nohup python /workspace/scripts/hf_uploader.py \
  --output-dir /workspace/projects/h3_smoothloopv3/output/minih33_smoothloopv3 \
  --repo AdwolfCzar/minih33-smoothloopv3 --interval 60 --keep-states 2 \
  > /workspace/logs/uploader.log 2>&1 &
```

Se já existir checkpoint no HF e você quiser continuar de onde parou, baixe o `*-state`
correspondente para dentro do `output/` e acrescente `RESUME=1`.

Parada graciosa a qualquer momento (salva e encerra no próximo optimizer step):
```bash
touch /workspace/projects/h3_smoothloopv3/output/minih33_smoothloopv3/save-and-stop.flag
```
Salvar sem parar: `touch .../save-now.flag`.

## 6. Configuração, e por que ela é assim

| Item | Valor | Motivo |
|---|---|---|
| Base | FL2VA BF16 → ConvRot INT8 na carga, fwd BF16 | pipeline histórico do projeto |
| Condicionamento | `--task i2va`, `target_modalities = ["video"]` | preserva o experimento anterior; áudio é ignorado |
| LoRA | dim 32 / alpha 32 | histórico v3 |
| Otimizador / LR | AdamW8bit, **5e-5**, constant_with_warmup 50 | v3 revisou 1e-4 → 5e-5 para H3 destilado |
| Batch / acumulação | 1 / 1 | obrigatório no H3 |
| Guidance | escala 4, schedule `sigma`, form `normalized` | receita v3 |
| Jitter de densidade espacial | 0,2 | receita v3 |
| Base preservation | **0 (desligada)** | decisão explícita do v3 |
| Atenção / precisão | SDPA / BF16 | flash_attn quebra o ConvRot INT8 |
| AdaLN | rank 16 | histórico |
| Block swap | 32, h2d_only, ring 2, pinned | OOM histórico no step 4502 com swap 24 |
| Views | 3 áreas (512×288 / 640×384 / 832×480), quotas 55/28/17, **todas `max_frames = 124`** | ver abaixo |
| Samples | 3 previews, seeds 42/43/44, 124f, 20 passos, ~480p | ver abaixo |

**Por que todas as views em 124 frames:** decisão do Cesar de respeitar o mínimo do H3 de 5 s.
No grid `17k+5` o primeiro valor acima de 5 s é **124** (5,17 s), então nenhuma view pode ficar
abaixo disso. Isso descartou a receita do smoothloop histórico (que usava f124/90/73) e a escada
do videovibe (f192/141/107). 124 também é exatamente o regime de geração alvo. Multi-resolução
foi mantida porque o RoPE do H3 é normalizado por área — treinar numa área só deixa a LoRA
frágil fora dela. Como a duração deixou de diferenciar as views, a área é estratificada pela
resolução da fonte (as fontes mais densas ancoram a área maior), como o `assign_buckets.py`
histórico fazia.

**Samples:** 3 clipes reais do próprio dataset, **primeiro frame** como condição (a caption H3
ancora `<Picture 1>` em 0.00 s, então um frame do meio contradiria o texto). Cobrem paisagem /
quase-quadrado / retrato e os tipos smooth / slow / static. Seeds, dimensões e passos são fixos
entre checkpoints de propósito: é o que isola a evolução da LoRA de mudanças na avaliação.
São clipes do treino, então servem para **acompanhamento visual**, não como validação independente.

## 7. Números medidos nesta máquina

| | |
|---|---|
| Velocidade | **11,6–12,4 s/it** (smoke nos itens mais pesados: ~10 s/it) |
| Loss | 0,0996 → 0,0795 nos primeiros 191 steps |
| VRAM | **25,1 GB / 32 GB** durante os steps; pico 15,1 GiB no sampling |
| Sampling | ~113 s por preview (101,6 s denoising + 11,7 s decode) → ~6 min por evento de 3 |
| Cache | latentes ~2,5 h (GPU 100%, VAE-bound) + TE ~20 min = 21,5 GB |
| 1 época | 1752 steps ≈ 5,7 h |

Âncoras históricas para comparação: quick (124f multi-res) 12,8 s/it · v2 10,15 · smoothloop 8,7 ·
videovibe 12,4. Estamos na faixa esperada.

**Orçamento de steps:** 6000 é teto, não alvo. O histórico parou o smoothloop em 2100 (966 clipes)
e o jiggle em 2500 (1232 clipes) — ambos ~2 épocas. Com 1752 clipes, 2 épocas ≈ 3500 steps.
A decisão é visual, comparando os previews de seed fixa entre checkpoints, não pela loss.

## 8. Armadilhas desta máquina que valem para a próxima

1. **`pgrep -f` / `pkill -f` casam com o próprio shell** e matam a sessão. Aconteceu 2×. Grave o
   PID num arquivo ao lançar (`echo $! > /workspace/logs/x.pid`) e mate por PID.
2. **`captioner` consome stdin.** Dentro de `while read -r f` ele come caracteres do caminho lido
   (viravam `orkspace/...`). Use `</dev/null` no comando interno.
3. **`--save_last_n_steps_state` NÃO existe no pin `ede9ed9f`.** O template do handoff de 18/09
   usa esse argumento e falharia. A única retenção é `--save_last_n_checkpoints N`, que apaga
   LoRAs antigos junto com os states e quebraria o checkpoint picking — por isso **não passamos
   retenção nenhuma**; o uploader sobe tudo e limpa só os states locais (mantém 2).
4. **Jupyter cria `.ipynb_checkpoints` dentro de `output/`** quando alguém navega pela pasta. O
   uploader já ignora esse padrão; se escrever outro, ignore também.
5. **`/workspace` é overlay, não volume.** Confirme com
   `vast-capabilities | jq '.instance.workspace_is_volume'`. Se for `false`, o upload em tempo
   real não é conforto, é requisito.
6. **Não rode ComfyUI junto com o treino.** O gargalo é VRAM (25,1 de 32 GB), não disco.
7. **Falha de GPU não é OOM.** Se `nvidia-smi` responder `Unable to determine the device handle
   ... No devices were found`, a GPU caiu do barramento — não dá para consertar de dentro de um
   container sem privilégios. Confira `vastai show instance $CONTAINER_ID`: `actual_status:
   offline` confirma que é host. Foi o que matou o run no step 191.
8. **captionkreator precisa do fix de fps baixo** se for recaptionar qualquer coisa: fontes de
   4–16 fps falhavam a conversão com `duration changed from X to Y` (~11% deste dataset).
   Branch `fix/low-fps-duration`, commit `5f9ffe4` em `github.com/adbrasi/captionkreator`
   (publicado; ainda não mergeado em `main`). Duas causas: `-stream_loop` com uma cópia a menos do que o `-t`
   precisa, e tolerância medida no fps do alvo em vez do da fonte.