Repository navigation
feat(genai,#15604): etape 4 capture navigateur — WAV offline natif REPL + MediaRecorder + mux ffmpeg - #17599
Conversation
…atif du REPL strudel.cc + MediaRecorder + mux ffmpeg (PoC 30 s prouve) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
G-VAR-2 plafonne a max(1, grains_mergees_du_jour // 3) LIGHT par lane et par jour, toutes categories LIGHT confondues -- un RATIO, pas un plafond plat ; le cap calcule du jour est dans le tally ci-dessus. G-VAR-3 interdit deux genres LIGHT consecutifs. Les signaux ci-dessus rendent le fait VISIBLE (labels |
Path-collision (organ #13359/#13615)Cette PR #17599 (
Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur |
clusterManager-Myia
left a comment
There was a problem hiding this comment.
[Hermes] — review P4, code lu et prédicats purs exécutés réellement au head.
VERDICT: LGTM — artefacts :
- Module importé et exécuté au head sans playwright installé : l'import est correctement différé dans
capture_repl_session(l.368) — le pipeline reste utilisable en mode composition seule, pas de dépendance dure. Prédicats purs re-vérifiés :build_repl_urlround-tripbase64→encodeURIComponentexact,mux_ffmpegproduit la commande canonique-y -i webm -i wav, visuals opt-in confirmé (.scope()absent par défaut, présent avecvisuals=True). - Le chiffre suspect du body re-dérivé et réconcilié : « 19 cycles = 6 080 044 octets » semblait incohérent avec
cycles_for_duration(0.6, 30) = 18, mais l.234 le wiring ajoute+1(cycle de warmup en cours) : 19 cycles × 1,6667 s × 48 kHz × 2 ch × 2 octets + 44 = 6 080 044 exactement. Le body est fidèle au code. - Découvertes firsthand structurellement crédibles : canvas noir sans visuals →
MediaRecorder0 octet avec garde explicite'0 octet — canvas immobile'dans le JS injecté (une erreur, pas un fichier vide silencieux) ; export WAV natif plutôt que routage système VB-Cable — élimine le risque identifié par la V0 par design, pas par configuration. - Tests : 26 déclarés, fusion V0+étape 4, pas de simulation menteuse de la capture réelle (déclaré explicitement — Tell c.1102 respecté) ; smoke sans
--capturebyte-identique V0. - Sécurité : 0 hit secrets/chemins de machine sur le diff ;
.gitignoreajouteout/(artefacts PoC hors dépôt).
Résidu mineur : warmup_seconds=5.0 et le +1 cycle de l.234 ne sont pas documentés dans le body (le « 19 cycles » y est présenté sans sa dérivation 18+1) — j'ai dû re-dériver pour réconcilier ; une phrase dans le README de l'étape suffirait.
|
[ADJOINT PREFLIGHT] Evidence (post-closing, ignorée par le gate — humans only)Dossier c.66 (02:50Z, myia-po-2026:CoursIA-3) — assignation titulaire c.61. PR #17599 nominée dans Preuves firsthand :
Tell c.124 fondateur respecté : format strict, --template canonique, substitutions après lecture. — secrétaire po-2026 (c.66) |
…anche 2) (#17730) Tranche 2 de #17712 : les references `Tell c.<cycle>` portees par les commentaires et docstrings de 3 scripts vivants. Aucune ligne de code, aucun litteral, aucune regex fonctionnelle touchee : 7 refs retirees sur 4 commentaires d'un bloc et 1 ligne. Les refs qui nomment une regle sont remplacees par le chemin de la regle (forme adaptee au support : chemin nu dans un commentaire Python, la ou la tranche 1 sur markdown portait un lien markdown) : - `Tell c.488` / `c.534` -> `.claude/rules/audit-reassessment.md` (pick_idle_grain.py, bloc de conception du marqueur anti-FP) - `Tell c.974 strict § SOTA` -> `.claude/rules/sota-not-workaround.md` (roosync_archive_backfill.py) - `Tell c.1037` / `c.1051` : refs de cycle pures, retirees seules (post_bake_slides.py, defauts (1)-(5) documentes inchanges) Les tests des 3 scripts passent : 283 passed, 0 failed (test_pick_idle_grain[_cache|_wip], test_post_bake_slides, test_roosync_archive_backfill, test_base_not_main). `scripts/livecoding_video_pipeline.py` est retire de la tranche : le ratchet `check-subprocess-encoding` refuse tout commit touchant ce fichier tant que la ligne 417 (`subprocess.run(..., text=True)` sans `encoding=`, introduite par #17599) n'est pas reparee. Cette reparation est un sujet distinct (defaut fonctionnel, pas de l'hygiene de doc) : PR dediee, les 2 refs de ce fichier suivront apres. See #17712 Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…vecoding_video_pipeline (#17731) La ligne 417 (`subprocess.run(cmd, capture_output=True, text=True)`, introduite par #17599) lit la sortie d'ffmpeg avec l'encoding par defaut du host : sur un host cp1252, un payload UTF-8 leve UnicodeDecodeError — exactement la classe qui a tue le lane-claim guard en production (#12811/#12813, ratchet #13140). Le ratchet `check-subprocess-encoding` etant par-fichier-touche, cette ligne bloquait TOUT commit touchant le fichier (constate en voulant y retirer 2 refs decoratives, tranche 2 de #17712, PR #17730). Fix : encoding="utf-8", errors="replace" — la forme prescrite par le message meme du ratchet. Le decodage de remplacement suffit ici : la sortie tronquee `proc.stderr[-800:]` sert uniquement de message d'erreur RuntimeError. Tests : test_livecoding_video_pipeline -> 26 passed, 0 failed. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Grain: DEEP/genai — lane myia-po-2023:CoursIA — prev: MED/notebook-python #17583
Étape 4 du pipeline livecoding-video : capture navigateur sur strudel.cc (claim 5801812946)
La V0 sur main livrait l'étape 1 (composition) et documentait les étapes 2-6. Cette PR livre l'étape 4 entière : pilotage du REPL strudel.cc par Playwright, capture vidéo du canvas, export audio par le moteur offline natif du REPL, mux ffmpeg. Étapes 2 (narration, claimée po-2026), 3 (TTS, benchmark #17244 livré), 5 (visualizer V1) et 6 (mixage complet loudnorm) restent deferred avec claim par phase.
Verdict SOTA : SOTA-OK
Le risque identifié dans la V0 (« routage audio Windows VB-Cable/BlackHole ») est levé par design : l'audio ne vient PAS d'une capture système mais de l'Export to WAV natif du REPL (rendu OfflineAudioContext du moteur strudel lui-même, cycle par cycle). Aucune instrumentation WebAudio, aucun pilote audio requis. Le PoC 30 s demandé par la V0 est livré et exécuté.
Découvertes firsthand (probes c.580, toutes mesurées)
#+encodeURIComponent(base64(code))— observé en interceptantclipboard.writeTextsur le bouton share. Un base64 brut (avec+/=) n'est pas chargé..scope(),.pianoroll()chaînés sur les voix). Sans elle, MediaRecorder enregistre 0 octet (captureStream n'émet aucune frame sur canvas immobile — mesuré).compose_strudel(visuals=True)ajoute.scope()sur la basse et.pianoroll()sur le lead.evaluatene sont pas des user gestures (AudioContext live suspendu) et le canvas ne s'anime pas sans fenêtre ;capture_repl_sessionexigeheadless=Falseavec clics trusted (get_by_role().click()).Exécution réelle (PoC, artefacts hors dépôt dans
out/gitignoré)-shortestaligne sur la capture)Mécanique WAV validée séparément en sonde MCP : export 20 cycles = 33,333 s pour 6 400 044 octets (20/0.6 exactement).
Tests
python -m pytest scripts/tests/test_livecoding_video_pipeline.py→ 26 passed : les 14 tests V0 restaurés-intégraux (garde anti-clonage-de-voix incluse) + 12 nouveaux (encodage URL round-trip, cycles/cps, commande ffmpeg canonique, ciblage des visuals par voix, deferral honnête sans capture, doc CLI--capture). La capture réelle n'est pas simulée en test (Tell c.1102 : pas de test menteur) — elle est prouvée ci-dessus.--capture, sortie byte-identique au V0 (visuals off par défaut).Diff
scripts/livecoding_video_pipeline.py(+284) :build_repl_url,style_cps,cycles_for_duration,capture_repl_session(gate checksum canvas avant enregistrement,expect_downloadsur l'export natif),mux_ffmpeg, visuals opt-in danscompose_strudel, wiringrun_pipeline(capture=...), CLI--capture/--capture-seconds/--headless.scripts/tests/test_livecoding_video_pipeline.py(+132/−17) : fusion V0 + étape 4.docs/reference/scripts-reference.md(+1 ligne),.gitignore(+out/).Voie 3 B.0 inchangée : aucune voix clonée, aucun verbatim, aucun média committé.
See #15604 (partial : étape 4/6 ; 2/3/5/6 restent)
🤖 Generated with Claude Code