app
AI Flow: Video
Public Made by Adomby adom
Turn a board build into a narrated walkthrough video on your wiki page and YouTube.
← Commit history
Publish 0.2.7
8 files changed
+10−9
Cargo.lock+1−1@@ -4,7 +4,7 @@ version = 4 [[package]] name = "adom-aiflow-video"-version = "0.2.6"+version = "0.2.7" dependencies = [ "clap", "serde",
Cargo.toml+1−1@@ -2,7 +2,7 @@ # Copied from adom/adom-aiflow template/flow-app. This copy is yours: change anything, never depend on aiflow. [package] name = "adom-aiflow-video"-version = "0.2.6"+version = "0.2.7" edition = "2021" license = "MIT"
README.md+1−1@@ -58,4 +58,4 @@ Your film is yours: it carries no Adom logo. The Adom logo sting is only for off ## Status -0.2.6. It grew out of the two Ghost Hand films ([john/ghost-hand](https://wiki.adom.inc/john/ghost-hand)). Working today: the flow and its hints, clip recording, the disk estimate, script feedback, the text privacy scan, file tracking and cleanup, the walkthrough director, and the narration page for recording your own voice. Still done by the AI by hand, with the skill as the guide: the cut itself, the frame-by-frame privacy look, the wiki publish and the YouTube upload. AI Flow does not suggest this app at intake yet.+0.2.7. It grew out of the two Ghost Hand films ([john/ghost-hand](https://wiki.adom.inc/john/ghost-hand)). Working today: the flow and its hints, clip recording, the disk estimate, script feedback, the text privacy scan, file tracking and cleanup, the walkthrough director, and the narration page for recording your own voice. Still done by the AI by hand, with the skill as the guide: the cut itself, the frame-by-frame privacy look, the wiki publish and the YouTube upload. AI Flow does not suggest this app at intake yet.
assets/narrate.css+2−2@@ -135,7 +135,7 @@ kbd { font: 500 11px var(--font-mono); border: 1px solid var(--border); border-r .steps-list small { display: block; } @media (max-height: 900px) { aside h2 { margin: 4px 0 5px; } .steps-list li { padding-top: 6px; padding-bottom: 6px; } .heard { margin: 2px 0 5px; } } .piph { position: absolute; width: 22px; height: 22px; z-index: 2; opacity: 0; transition: opacity .15s; }-.pipbox:hover .piph, .pipbox.drag .piph { opacity: 1; }+.pipbox:hover .piph, .pipbox.sizing .piph { opacity: 1; } .piph::after { content: ""; position: absolute; inset: 4px; border: 3px solid var(--accent); border-radius: 2px; } .piph.tl { left: 0; top: 0; cursor: nwse-resize; } .piph.tl::after { border-right: none; border-bottom: none; } .piph.tr { right: 0; top: 0; cursor: nesw-resize; } .piph.tr::after { border-left: none; border-bottom: none; }@@ -143,7 +143,7 @@ kbd { font: 500 11px var(--font-mono); border: 1px solid var(--border); border-r .piph.br { right: 0; bottom: 0; cursor: nwse-resize; } .piph.br::after { border-left: none; border-top: none; } .pipbox.circle { overflow: visible; } .pipbox.circle .campip { border-radius: 50%; } .pipbar { position: absolute; left: 50%; top: 6px; transform: translateX(-50%); display: flex; gap: 4px; z-index: 3; opacity: 0; transition: opacity .15s; white-space: nowrap; }-.pipbox:hover .pipbar { opacity: 1; } .pipbox.drag .pipbar { opacity: 0; }+.pipbox:hover .pipbar { opacity: 1; } .pipbox.drag .pipbar, .pipbox.sizing .pipbar { opacity: 0; } .pipbar button { background: rgba(13,17,23,.85); color: var(--text); border: 1px solid var(--accent); border-radius: 999px; padding: 3px 10px; font: 500 12px var(--font-body); cursor: pointer; } .pipbar button:hover { background: var(--accent); color: #04211f; } .piptoggle { width: 100%; margin: 0 0 6px; text-align: left; } .piptoggle b { float: right; color: var(--muted); }
assets/narrate.js+3−2@@ -277,8 +277,9 @@ else openCam(true).then(() => camStream && toast('Your picture is on. Drag it, resize it from a corner, or change its shape.', 'success')); }; let dragAt = null; const SMIN = 0.1, SMAX = 0.6; let sizeAt = null; // resizing: the opposite corner stays where it is- box.addEventListener('pointerdown', (e) => { if (livePip) return; box.setPointerCapture(e.pointerId); box.classList.add('drag'); e.preventDefault();+ box.addEventListener('pointerdown', (e) => { if (livePip) return; box.setPointerCapture(e.pointerId); e.preventDefault(); const c = e.target.dataset && e.target.dataset.c;+ box.classList.add(c ? 'sizing' : 'drag'); if (c) box.style.cursor = (c === 'tl' || c === 'br') ? 'nwse-resize' : 'nesw-resize'; if (c) { const { w, h } = pipSize(); sizeAt = { ax: PIP.x + (c[1] === 'l' ? w / 2 : -w / 2), ay: PIP.y + (c[0] === 't' ? h / 2 : -h / 2), sx: c[1] === 'l' ? -1 : 1, sy: c[0] === 't' ? -1 : 1 }; } else dragAt = [e.clientX, e.clientY, PIP.x, PIP.y]; }); box.addEventListener('pointermove', (e) => { const r = p.getBoundingClientRect();@@ -287,7 +288,7 @@ PIP.x = sizeAt.ax + sizeAt.sx * PIP.size * a / 2; PIP.y = sizeAt.ay + sizeAt.sy * PIP.size / 2; return layout(); } if (!dragAt) return; PIP.x = dragAt[2] + (e.clientX - dragAt[0]) / r.width; PIP.y = dragAt[3] + (e.clientY - dragAt[1]) / r.height; layout(); }); box.addEventListener('wheel', (e) => { if (livePip) return; e.preventDefault(); PIP.size = Math.max(SMIN, Math.min(SMAX, PIP.size * (1 - e.deltaY * 0.0012))); layout(true); }, { passive: false });- const dragEnd = () => { if (!dragAt && !sizeAt) return; dragAt = null; sizeAt = null; box.classList.remove('drag'); layout(true); };+ const dragEnd = () => { if (!dragAt && !sizeAt) return; dragAt = null; sizeAt = null; box.classList.remove('drag', 'sizing'); box.style.cursor = ''; layout(true); }; box.addEventListener('pointerup', dragEnd); box.addEventListener('pointercancel', dragEnd); async function cams() { const devs = (await navigator.mediaDevices.enumerateDevices()).filter((d) => d.kind === 'videoinput');
bin/adom-aiflow-video⋯ 1 unchanged line ⋯
package.json+1−1@@ -1,7 +1,7 @@ { "slug": "adom-aiflow-video", "type": "app",- "version": "0.2.6",+ "version": "0.2.7", "title": "AI Flow: Video", "description": "Make a narrated walkthrough video of a board built in Adom Hydrogen, put it on the project's wiki page and help the human upload it to YouTube. A dynamic skill: a small Rust binary that suggests each step, records clips, ships a ready-made 3D walkthrough director and gives gentle feedback; the AI does the work. Open source (MIT): the full Rust source ships on this page; build it yourself with ./build.sh.", "category": "Developer Tools",
page.json+1−1@@ -1,7 +1,7 @@ { "slug": "adom-aiflow-video", "type": "app",- "version": "0.2.6",+ "version": "0.2.7", "title": "AI Flow: Video", "description": "Make a narrated walkthrough video of a board built in Adom Hydrogen, put it on the project's wiki page and help the human upload it to YouTube. A dynamic skill: a small Rust binary that suggests each step, records clips, ships a ready-made 3D walkthrough director and gives gentle feedback; the AI does the work. Open source (MIT): the full Rust source ships on this page; build it yourself with ./build.sh.", "category": "Developer Tools",