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.1.1
9 files changed
+112−18
Cargo.lock+1−1@@ -4,7 +4,7 @@ version = 4 [[package]] name = "adom-aiflow-video"-version = "0.1.0"+version = "0.1.1" 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.1.0"+version = "0.1.1" edition = "2021" license = "MIT"
README.md+3−2@@ -34,9 +34,10 @@ AI Flow: Video is a dynamic skill, like AI Flow itself: a small Rust binary that | plan, capture | Short highlight clips of the moments worth showing, never a continuous recording | | walkthrough | The part-by-part 3D walkthrough, with the ready-made director (`adom-aiflow-video director`, `adom-aiflow-video guide`) | | script, cut | Narration with adom-tts, footage fitted to it, captions and chapters as separate files |+| voice | Keep the AI voiceover, or narrate it yourself: read along to a teleprompter copy in your own words, and the film is rebuilt and re-captioned around your recording | | privacy | Looks for email addresses, keys, file paths and other personal details before anything is published | | review | You watch the draft in the Adom video player and ask for changes |-| publish | The `::adom-video` player at the top of your wiki page; YouTube through adom-google, unlisted unless you say otherwise |+| publish | The `::adom-video` player at the top of your wiki page; YouTube through adom-google: uploaded private first so you can review it there, then published when you say so | | cleanup | Removes the raw footage and scratch files and says how much space came back | ## Commands@@ -52,4 +53,4 @@ Every command answers `OK:` with `Hint:` lines. The skill is in [skills/adom-aif ## Status -0.1.0, first cut. 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, and the walkthrough director. 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.1.1, first cut. 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, and the walkthrough director. 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.
bin/adom-aiflow-video⋯ 1 unchanged line ⋯
flows/flow.json+78−11@@ -2,15 +2,82 @@ "name": "video", "description": "From a board build (running or finished) to a narrated walkthrough video on the project's wiki page and, when the human wants it, on YouTube. Every step is a suggestion: take another route when you have a better one, and say what you did.", "steps": [- {"name": "intake", "done": ["state.json"], "do": "Ask the human once, in plain words: do they want a narrated video of this build, ready to review when they are back? Tell them recording takes over the screen of the machine it records, and suggest a second machine on their Adom Mesh so their own stays free. Run `disk` on the recording machine and share the estimate. Then `init` (with `--release <board-release.json>` when the board flow wrote one, `--target <machine>` for the recording machine)."},- {"name": "plan", "done": ["plan.json"], "do": "Write plan.json: the moments worth a short clip for THIS build (the prompt being typed, each AI Flow step landing, parts search, a pup window fetching a part, new wiki part pages, Fields views, the silkscreen landing, the finished board in 3D, the wiki page). Highlights only, 5 to 30 s each, never continuous recording, and leave AI Flow's own full-length step recording off. If the build is already finished, plan the showcase shots instead and say the build footage does not exist."},- {"name": "capture", "done": ["clips/*.mp4"], "do": "Record the planned moments as they happen: `clip start --name <moment> --hwnd <window>` then `clip stop`. Before each take look at the screen: Hydrogen full screen with the taskbar showing, other apps floating at about 90 percent, no dialogs, toasts, mail, chat or other personal windows. Motion in every clip. `track` every file you create on any machine so `clean` can find it later."},- {"name": "walkthrough", "done": ["walkthrough/steps.json"], "do": "Build the 3D walkthrough in the Adom 3D viewer (assets/walkthrough-director.js is ready-made; docs/walkthrough.md explains it): the case or enclosure part by part when the project has one, then the board's major parts on the top and the underside. Highlight each part, label it with its reference and part number, and narrate what it does. Write walkthrough/steps.json (one entry per part: nodes, label, text) and record the take in real time."},- {"name": "script", "done": ["script.json"], "do": "Write script.json: one narration line per scene. Open on the real starting prompt. Name the Adom tool that did each step while it is on screen (AI Flow, the KiCad, Fusion or Altium bridge, parts search, the wiki, Fields, webviews, pup), about one mention per 20 to 30 s, and add a few 'ask your AI to ...' lines so the viewer learns something. Include the parts story (unique parts, where they came from, cost to build one and each at 100) and any custom mechanical work. Close with one line that it was built in Adom Hydrogen and where the files are. Then `script script.json` for feedback."},- {"name": "cut", "done": ["out/*.mp4"], "do": "Narrate with adom-tts, fit each clip to its line (1x to 2x, never dead air, never a flashed shot), add teal circles where the eye should go, and write captions (.vtt, .srt) and chapters as sidecar files, never burned in. Render 1080p one section at a time. Make a contact sheet and look at every scene before calling it a draft."},- {"name": "privacy", "done": ["privacy.json"], "do": "Run `scan <script, captions, description files>` and look through the contact sheet for anything personal on screen: email addresses, names, phone numbers, keys, file paths with a user name, other people's windows. Prefer dropping or reframing a clip to blurring it. Tell the human what you found and what you did about it."},- {"name": "review", "done": ["review.json"], "do": "Show the draft to the human in the Adom video player with chapters (`adom-video play <file> --chapters <json>`), with the list of what the AI did and anything it flagged. Take their changes, re-cut, and when they are happy record it: `mark review --note \"<their words>\"`."},- {"name": "publish", "done": ["publish.json"], "do": "With the human's OK: push the film, poster, captions and a video.json manifest (captions and chapters inlined) to the project's wiki page and put `::adom-video{src=...}` under the title; check the live player. For YouTube, suggest setting up adom-google (a YouTube-only account) if it is not there, upload unlisted unless they ask for public, with the chapters, the starting prompt, the cost line and a 'Built with' list of the Adom tools in the description. `mark publish --note \"<links>\"`."},- {"name": "cleanup", "done": ["cleanup.json"], "do": "Once the human has approved the final film, run `clean` to see what is left on every machine (raw clips, temp recordings, staging copies, render scratch), then `clean --yes` to remove it. Keep the finished film, captions, chapters and the edit plan. Tell the human how much space was freed."}+ {+ "name": "intake",+ "done": [+ "state.json"+ ],+ "do": "Ask the human once, in plain words: do they want a narrated video of this build, ready to review when they are back? Tell them recording takes over the screen of the machine it records, and suggest a second machine on their Adom Mesh so their own stays free. Run `disk` on the recording machine and share the estimate. Then `init` (with `--release <board-release.json>` when the board flow wrote one, `--target <machine>` for the recording machine)."+ },+ {+ "name": "plan",+ "done": [+ "plan.json"+ ],+ "do": "Write plan.json: the moments worth a short clip for THIS build (the prompt being typed, each AI Flow step landing, parts search, a pup window fetching a part, new wiki part pages, Fields views, the silkscreen landing, the finished board in 3D, the wiki page). Highlights only, 5 to 30 s each, never continuous recording, and leave AI Flow's own full-length step recording off. If the build is already finished, plan the showcase shots instead and say the build footage does not exist."+ },+ {+ "name": "capture",+ "done": [+ "clips/*.mp4"+ ],+ "do": "Record the planned moments as they happen: `clip start --name <moment> --hwnd <window>` then `clip stop`. Before each take look at the screen: Hydrogen full screen with the taskbar showing, other apps floating at about 90 percent, no dialogs, toasts, mail, chat or other personal windows. Motion in every clip. `track` every file you create on any machine so `clean` can find it later."+ },+ {+ "name": "walkthrough",+ "done": [+ "walkthrough/steps.json"+ ],+ "do": "Build the 3D walkthrough in the Adom 3D viewer (assets/walkthrough-director.js is ready-made; docs/walkthrough.md explains it): the case or enclosure part by part when the project has one, then the board's major parts on the top and the underside. Highlight each part, label it with its reference and part number, and narrate what it does. Write walkthrough/steps.json (one entry per part: nodes, label, text) and record the take in real time."+ },+ {+ "name": "script",+ "done": [+ "script.json"+ ],+ "do": "Write script.json: one narration line per scene. Open on the real starting prompt. Name the Adom tool that did each step while it is on screen (AI Flow, the KiCad, Fusion or Altium bridge, parts search, the wiki, Fields, webviews, pup), about one mention per 20 to 30 s, and add a few 'ask your AI to ...' lines so the viewer learns something. Include the parts story (unique parts, where they came from, cost to build one and each at 100) and any custom mechanical work. Close with one line that it was built in Adom Hydrogen and where the files are. Then `script script.json` for feedback."+ },+ {+ "name": "cut",+ "done": [+ "out/*.mp4"+ ],+ "do": "Narrate with adom-tts, fit each clip to its line (1x to 2x, never dead air, never a flashed shot), add teal circles where the eye should go, and write captions (.vtt, .srt) and chapters as sidecar files, never burned in. Render 1080p one section at a time. Make a contact sheet and look at every scene before calling it a draft."+ },+ {+ "name": "voice",+ "done": [+ "voice.json"+ ],+ "do": "Offer the human two ways to finish the sound, and let them pick. (1) Keep the AI voiceover and go on. (2) Narrate it themselves: play them a private working copy of the draft with the captions showing, as a teleprompter, and let them record their own voice while they watch, in their own words (they need not read it exactly). Then rebuild the film without the on-screen captions, fit each scene to what they actually said, and write new captions and chapters from their recording (check part names and numbers against the script). The teleprompter copy is never published. `mark voice --note \"ai voiceover\"` or `mark voice --note \"own narration\"`."+ },+ {+ "name": "privacy",+ "done": [+ "privacy.json"+ ],+ "do": "Run `scan <script, captions, description files>` and look through the contact sheet for anything personal on screen: email addresses, names, phone numbers, keys, file paths with a user name, other people's windows. Prefer dropping or reframing a clip to blurring it. Tell the human what you found and what you did about it."+ },+ {+ "name": "review",+ "done": [+ "review.json"+ ],+ "do": "Show the draft to the human in the Adom video player with chapters (`adom-video play <file> --chapters <json>`), with the list of what the AI did and anything it flagged. Then show a pre-flight sheet of everything the public will see: title, description (chapters, the starting prompt, the cost line, the Built-with list), thumbnail, tags, channel and privacy. Take their changes, re-cut, and when they are happy record it: `mark review --note \"<their words>\"`."+ },+ {+ "name": "publish",+ "done": [+ "publish.json"+ ],+ "do": "With the human's OK: push the film, poster, captions and a video.json manifest (captions and chapters inlined) to the project's wiki page and put `::adom-video{src=...}` under the title; check the live player. For YouTube, suggest setting up adom-google (a YouTube-only account) if it is not there, then upload as PRIVATE first so they can watch it on YouTube itself (compression, thumbnail, captions, chapter markers); switch it to unlisted or public only when they say so, and delete it if they do not like it. `mark publish --note \"<links>\"`."+ },+ {+ "name": "cleanup",+ "done": [+ "cleanup.json"+ ],+ "do": "Once the human has approved the final film, run `clean` to see what is left on every machine (raw clips, temp recordings, staging copies, render scratch), then `clean --yes` to remove it. Keep the finished film, captions, chapters and the edit plan. Tell the human how much space was freed."+ } ]-}+}
package.json+1−1@@ -1,7 +1,7 @@ { "slug": "adom-aiflow-video", "type": "app",- "version": "0.1.0",+ "version": "0.1.1", "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.1.0",+ "version": "0.1.1", "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",
skills/adom-aiflow-video/SKILL.md+19−1@@ -46,6 +46,24 @@ Before recording, tell the human three things: it needs disk space (`disk` gives - **One closing line** that it was built in Adom Hydrogen and that the files are on the wiki page, over the project page itself. - Facts and numbers, no superlatives. A fab that is not public is "a 3rd party fab". +## Not AI slop++A film reads as machine-made when it could be about any board. Keep it about this one.++- **Real footage only**: the human's own software and their own board. No generated images, stock clips, music beds or title cards.+- **Narration that adds something**: each line says what the picture cannot: a number, a reason, a trade-off. No filler openers and no hype words (`script` points them out).+- **Specifics over claims**: "thirty-five parts, twenty-nine dollars" rather than "a compact, affordable design".+- **Say what went wrong**: a fix the AI had to make is real engineering, and viewers trust it.+- **Short**: cut any scene that teaches nothing.+- **A person signs off** before anything is public.++## The voice: offer both++Let the human choose, and make either easy.++- **AI voiceover**: fine to publish as it is. Say so; do not make them feel it is second best.+- **Their own voice**: the biggest step up in quality. Make a private working copy of the draft with the captions showing as a teleprompter, and let them record while they watch, in their own words; they do not have to read it exactly. Then rebuild the film without on-screen captions, fit each scene's footage to what they actually said, and write the captions and chapters again from their recording (check part names and numbers against the script; a transcript gets those wrong). The teleprompter copy is a working file and is never published; published captions stay sidecar files.+ ## Privacy A screen recording shows whatever was on the screen. Record only Hydrogen and the build's own windows; a clean second machine is the best protection. `scan` reads the script, captions and description for email addresses, phone numbers, keys and file paths with a user name. Frames need your eyes: look through the contact sheet for mail, chat, names, avatars, other people's windows and toasts. Prefer another take or a tighter crop to a blur, and tell the human what you found.@@ -55,7 +73,7 @@ A screen recording shows whatever was on the screen. Record only Hydrogen and th Show the human the draft in the Adom video player (`adom-video play <file> --chapters <json>`) and take their changes first. Publishing is theirs to approve. - **Wiki**: push the film, a poster, the .vtt and .srt, and a `video.json` manifest with the captions and chapters inlined; put `::adom-video{src="/<owner>/<slug>/render/docs/videos/<name>.video.json"}` on its own line under the page title with a plain download link; use a new file name when replacing a film. Check the live player (duration, chapters, captions, a few seconds of muted playback).-- **YouTube**: if adom-google is not set up, suggest it (a YouTube-only account, then pick the channel). Upload unlisted unless they ask for public: `adom-google --account <name> youtube upload <file> --privacy unlisted --title ... --description ... --thumbnail <png>`. The description carries the chapter timestamps, the starting prompt, the cost line, the "Built with" list and the project page link. If an API upload is not possible for their account, fill in YouTube Studio in their own signed-in browser and leave the Publish click to them.+- **YouTube**: if adom-google is not set up, suggest it (a YouTube-only account, then pick the channel). Show a pre-flight sheet first (title, description, thumbnail, tags, channel, privacy), then upload as PRIVATE so they can watch it on YouTube itself: `adom-google --account <name> youtube upload <file> --privacy private --title ... --description ... --thumbnail <png>`. Switch it to unlisted or public only when they say so; delete it if they do not like it. The description carries the chapter timestamps, the starting prompt, the cost line, the "Built with" list and the project page link. If an API upload is not possible for their account, fill in YouTube Studio in their own signed-in browser and leave the Publish click to them. ## Clean up
src/checks.rs+8@@ -23,6 +23,9 @@ const TOOLS: [(&str, &[&str]); 11] = [ ("adom-tts", &["adom-tts"]), ]; +/// Phrases that make narration sound machine-made: filler openers and hype.+const FILLER: [&str; 22] = ["let's dive", "dive in", "in today's video", "in this video", "welcome to", "without further ado", "game-changer", "game changer", "revolutionary", "cutting-edge", "cutting edge", "seamless", "effortless", "powerful", "amazing", "incredible", "stunning", "unleash", "next-level", "state-of-the-art", "sleek", "robust"];+ fn words(t: &str) -> usize { t.split_whitespace().count() } pub fn disk(dir: &Path, clips: u64, seconds: u64) -> (String, Vec<String>) {@@ -63,6 +66,9 @@ pub fn script(text: &str) -> (String, Vec<String>) { if words(t) > 34 { hints.push(format!("{id}: {} words (about {secs:.0} s) is a long hold for one shot; two shorter scenes may read better.", words(t))); } if t.contains('\u{2014}') { hints.push(format!("{id}: has an em-dash; a comma or a new sentence narrates more cleanly.")); } let low = format!(" {} ", t.to_lowercase());+ let fill: Vec<&str> = FILLER.iter().filter(|w| low.contains(*w)).copied().collect();+ if !fill.is_empty() { hints.push(format!("{id}: \"{}\" reads as filler or hype; a number or a reason says more (what it measures, costs, or why it was done).", fill.join("\", \""))); }+ if !t.is_empty() && !t.chars().any(|ch| ch.is_ascii_digit()) && words(t) > 14 && !["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "twenty", "thirty", "forty", "fifty", "hundred", "half"].iter().any(|n| low.contains(n)) && s["label"].as_str().map(|l| low.contains(&l.to_lowercase())).unwrap_or(false) { hints.push(format!("{id}: the line mostly repeats the on-screen label; say what the picture cannot (a number, a reason, a trade-off).")); } let here: Vec<&str> = TOOLS.iter().filter(|(_, keys)| keys.iter().any(|k| low.contains(k))).map(|(n, _)| *n).collect(); if here.len() > 2 { hints.push(format!("{id}: names {} Adom tools in one scene ({}); one per scene lands better, the rest can go in the description.", here.len(), here.join(", "))); } for n in here { mentions.push((id.clone(), n)); }@@ -171,6 +177,8 @@ mod tests { assert!(hints.iter().any(|h| h.contains("s02") && h.contains("x;"))); assert!(!hints.iter().any(|h| h.contains("No cost line"))); assert!(hints.iter().any(|h| h.contains("ask your AI")));+ let (_, hints) = script(r#"[{"id":"s01","text":"Let's dive in to this amazing board."}]"#);+ assert!(hints.iter().any(|h| h.contains("filler or hype"))); } #[test]