From a54539344bdc6105fa1bddf0bbacd838f7703a13 Mon Sep 17 00:00:00 2001 From: "prompt.ac/@jeffrey" Date: Mon, 7 Sep 2026 15:27:30 -0400 Subject: [PATCH] vhs-jeffrey-ac-os campaign: the generator scripts (takes stay local) Claude-Session: https://claude.ai/code/session_018RKzjn5crREMTkDaZwrq8b --- .../generate-seedance-2.5-test.mjs | 83 +++++++++++++++++++ .../vhs-jeffrey-ac-os/generate-v2.mjs | 82 ++++++++++++++++++ .../generate-v3-identity.mjs | 72 ++++++++++++++++ .../generate-v4-multiview.mjs | 59 +++++++++++++ .../campaigns/vhs-jeffrey-ac-os/generate.mjs | 74 +++++++++++++++++ 5 files changed, 370 insertions(+) create mode 100644 marketing/campaigns/vhs-jeffrey-ac-os/generate-seedance-2.5-test.mjs create mode 100644 marketing/campaigns/vhs-jeffrey-ac-os/generate-v2.mjs create mode 100644 marketing/campaigns/vhs-jeffrey-ac-os/generate-v3-identity.mjs create mode 100644 marketing/campaigns/vhs-jeffrey-ac-os/generate-v4-multiview.mjs create mode 100644 marketing/campaigns/vhs-jeffrey-ac-os/generate.mjs diff --git a/marketing/campaigns/vhs-jeffrey-ac-os/generate-seedance-2.5-test.mjs b/marketing/campaigns/vhs-jeffrey-ac-os/generate-seedance-2.5-test.mjs new file mode 100644 index 0000000000..967a141523 --- /dev/null +++ b/marketing/campaigns/vhs-jeffrey-ac-os/generate-seedance-2.5-test.mjs @@ -0,0 +1,83 @@ +#!/usr/bin/env node + +import { existsSync, writeFileSync } from "node:fs"; +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { spawnSync } from "node:child_process"; +import { generateSeedance25ReferenceShot } from "../../../pop/lib/fal.mjs"; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const repo = resolve(HERE, "../../.."); +const motionSource = resolve(HERE, "jeffrey-ac-os-omnihuman-v1.5.mp4"); +const audioSource = resolve(HERE, "jeffrey-pvc-v2.mp3"); +const motion = resolve(HERE, "seedance-test-driver-4s.mp4"); +const audio = resolve(HERE, "jeffrey-pvc-seedance-test-4s.mp3"); +const out = resolve(HERE, "jeffrey-ac-os-seedance-2.5-test-4s.mp4"); +const promptPath = resolve(HERE, "seedance-2.5-test-prompt.txt"); + +function ffmpeg(args) { + const result = spawnSync("ffmpeg", ["-hide_banner", "-loglevel", "error", "-y", ...args], { + stdio: "inherit", + }); + if (result.status !== 0) throw new Error(`ffmpeg exited ${result.status}`); +} + +if (!existsSync(motion)) { + ffmpeg([ + "-i", motionSource, "-t", "4", + "-an", "-c:v", "libx264", "-preset", "medium", "-crf", "18", + "-pix_fmt", "yuv420p", motion, + ]); +} + +if (!existsSync(audio)) { + ffmpeg([ + "-i", audioSource, "-t", "4", + "-c:a", "libmp3lame", "-q:a", "2", audio, + ]); +} + +const images = [ + resolve(repo, "xbox/assets/jeffrey-meshy-v6/refs/front.png"), + resolve(repo, "xbox/assets/jeffrey-meshy-v6/refs/three-quarter.png"), + resolve(repo, "xbox/assets/jeffrey-meshy-v6/refs/profile.png"), + resolve(repo, "xbox/assets/jeffrey-meshy-v6/refs/full-body.png"), + resolve(HERE, "source-v3-identity.png"), + resolve(repo, "papers/iclc-2027-notespatial/figures/ac-native-laptop.png"), + resolve(repo, "marketing/campaigns/keymaps-cover/refs/ac-native-notepat.png"), +]; + +const prompt = `[Identity] +[Image1], [Image2], [Image3], and [Image4] are four views of the same real person, Jeffrey Alan Scudder: front, three-quarter, profile, and full body. Together they exclusively define Jeffrey's facial geometry, eye spacing, long narrow nose, slim jaw and chin, ears, hairline, uneven medium-brown hair, skin texture, body proportions, and clothing. Preserve the same Jeffrey continuously in every frame and at every angle. Do not use the white photo backgrounds. + +[Scene and prop] +[Image5] is the exact opening frame and defines the early-1990s community-access television studio, framing, lighting, Jeffrey's initial pose and clothing, the black ThinkPad in his hands, and the Aesthetic Computer screen. [Image6] defines the exact laptop hardware. [Image7] defines the exact screen interface. Keep one coherent laptop rigidly supported throughout; do not replace or redesign it. + +[Motion] +[Video1] supplies only Jeffrey's body movement, head movement, hand gesture, weight shift, forward approach, camera movement, timing, and blocking. Do not use or inherit the person's face, identity, skin, hair, clothing, laptop, studio, image texture, or audio from [Video1]. Jeffrey's appearance comes only from [Image1] through [Image5]. + +[Audio] +[Audio1] is the exact Jeffrey voice recording and dialogue timing. Preserve this audio and synchronize Jeffrey's mouth naturally to it. Do not synthesize a different speaker, change the words, add music, or add narration. + +[Output] +Create one continuous four-second vertical 9:16 photorealistic community-TV take beginning from [Image5]. Jeffrey speaks naturally while his head, shoulders, torso, weight, and free hand remain alive. Natural blinking and mouth motion; restrained facial expression; ordinary skin texture; no beauty filter. Preserve Jeffrey's identity, facial proportions, hair, clothing, laptop, screen, set geometry, equipment count, and lighting throughout. No cuts, duplicated objects, extra fingers, warped laptop, face morphing, enlarged eyes, widened jaw, generic presenter face, captions, logos, or watermarks.`; + +writeFileSync(promptPath, `${prompt}\n`); + +if (!existsSync(out)) { + const result = await generateSeedance25ReferenceShot({ + images, + videos: [motion], + audios: [audio], + prompt, + duration: "4", + ratio: "9:16", + resolution: "480p", + audio: true, + outPath: out, + label: "vhs-jeffrey-seedance-2.5-test", + }); + if (!result.ok) throw new Error(result.error); +} + +console.log(`✓ ${out}`); diff --git a/marketing/campaigns/vhs-jeffrey-ac-os/generate-v2.mjs b/marketing/campaigns/vhs-jeffrey-ac-os/generate-v2.mjs new file mode 100644 index 0000000000..72de6ae61c --- /dev/null +++ b/marketing/campaigns/vhs-jeffrey-ac-os/generate-v2.mjs @@ -0,0 +1,82 @@ +#!/usr/bin/env node + +import { existsSync, readFileSync, writeFileSync } from "node:fs"; +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { spawnSync } from "node:child_process"; +import { generateOmniHuman, generateSync3Lipsync } from "../../../pop/lib/fal.mjs"; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const source = resolve(HERE, "source-v2-full-body.png"); +const scriptPath = resolve(HERE, "script-v2.txt"); +const audio = resolve(HERE, "jeffrey-pvc-v2.mp3"); +const performance = resolve(HERE, "jeffrey-ac-os-omnihuman-v1.5.mp4"); +const clean = resolve(HERE, "jeffrey-ac-os-clean-v2.mp4"); +const final = resolve(HERE, "jeffrey-ac-os-vhs-v2.mp4"); + +if (!existsSync(audio)) { + const text = readFileSync(scriptPath, "utf8").trim(); + console.log(`→ Jeffrey PVC: ${text}`); + const response = await fetch("https://aesthetic.computer/api/say", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + from: text, + provider: "jeffrey", + voice: "neutral:0", + speed: 0.98, + }), + }); + if (!response.ok) { + throw new Error(`/api/say ${response.status}: ${(await response.text()).slice(0, 240)}`); + } + writeFileSync(audio, Buffer.from(await response.arrayBuffer())); + console.log(`✓ ${audio}`); +} + +if (!existsSync(performance)) { + const result = await generateOmniHuman({ + image: source, + audio, + outPath: performance, + label: "vhs-jeffrey-omnihuman-v1.5", + }); + if (!result.ok) throw new Error(result.error); + console.log(`✓ ${performance}`); +} + +if (!existsSync(clean)) { + const result = await generateSync3Lipsync({ + video: performance, + audio, + outPath: clean, + label: "vhs-jeffrey-sync-3", + }); + if (!result.ok) throw new Error(result.error); + console.log(`✓ ${clean}`); +} + +const videoFilter = [ + "scale=1092:1092:flags=lanczos", + "crop=1080:1080:x='6+4*sin(t*11)':y=6", + "eq=contrast=1.07:brightness=-0.022:saturation=0.72:gamma=0.95", + "chromashift=cbh=-4:crh=3", + "noise=alls=10:allf=t+u", + "vignette=PI/5", + "fps=30000/1001", + "format=yuv420p", +].join(","); + +const ffmpeg = spawnSync("ffmpeg", [ + "-hide_banner", "-loglevel", "error", "-y", + "-i", clean, + "-vf", videoFilter, + "-af", "highpass=f=90,lowpass=f=7600,acompressor=threshold=-18dB:ratio=2.2:attack=15:release=180", + "-c:v", "libx264", "-preset", "slow", "-crf", "20", + "-c:a", "aac", "-b:a", "160k", + "-movflags", "+faststart", + final, +], { stdio: "inherit" }); + +if (ffmpeg.status !== 0) throw new Error(`ffmpeg exited ${ffmpeg.status}`); +console.log(`✓ ${final}`); diff --git a/marketing/campaigns/vhs-jeffrey-ac-os/generate-v3-identity.mjs b/marketing/campaigns/vhs-jeffrey-ac-os/generate-v3-identity.mjs new file mode 100644 index 0000000000..322eacd630 --- /dev/null +++ b/marketing/campaigns/vhs-jeffrey-ac-os/generate-v3-identity.mjs @@ -0,0 +1,72 @@ +#!/usr/bin/env node + +import { existsSync } from "node:fs"; +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { spawnSync } from "node:child_process"; +import { + generateKlingMotionControlV3, + generateSync3Lipsync, +} from "../../../pop/lib/fal.mjs"; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const source = resolve(HERE, "source-v3-identity.png"); +const driver = resolve(HERE, "jeffrey-ac-os-omnihuman-v1.5.mp4"); +const face = resolve(HERE, "../../../slab/menuband/marketing/notepat-launch/refs/jeffrey-face.jpg"); +const faceContext = resolve(HERE, "../../../slab/menuband/marketing/notepat-launch/refs/jeffrey-alt.jpg"); +const audio = resolve(HERE, "jeffrey-pvc-v2.mp3"); +const identityMotion = resolve(HERE, "jeffrey-ac-os-kling-v3-identity.mp4"); +const clean = resolve(HERE, "jeffrey-ac-os-clean-v3-identity.mp4"); +const final = resolve(HERE, "jeffrey-ac-os-vhs-v3-identity.mp4"); + +if (!existsSync(identityMotion)) { + const result = await generateKlingMotionControlV3({ + image: source, + video: driver, + faceImage: face, + faceReferences: [faceContext], + prompt: "@Element1 is Jeffrey Alan Scudder. Preserve his exact real facial geometry, natural asymmetry, long narrow nose, blue-green eyes, slim jaw, mouth shape, hairline, and uneven medium-brown hair throughout every frame. Transfer only the body movement, head movement, gaze changes, free-hand gestures, timing, and camera movement from the driving video. The source image owns Jeffrey's appearance, clothing, black ThinkPad, readable Aesthetic Computer screen, and the entire community-TV studio. Do not inherit facial identity from the driving video. Keep the laptop rigid, coherent, and supported in his left hand.", + characterOrientation: "video", + keepOriginalSound: true, + outPath: identityMotion, + label: "vhs-jeffrey-kling-v3-identity", + }); + if (!result.ok) throw new Error(result.error); + console.log(`✓ ${identityMotion}`); +} + +if (!existsSync(clean)) { + const result = await generateSync3Lipsync({ + video: identityMotion, + audio, + outPath: clean, + label: "vhs-jeffrey-sync-3-identity", + }); + if (!result.ok) throw new Error(result.error); + console.log(`✓ ${clean}`); +} + +const videoFilter = [ + "scale=-2:1920:flags=lanczos", + "pad=1080:1920:(ow-iw)/2:0:black", + "eq=contrast=1.07:brightness=-0.022:saturation=0.72:gamma=0.95", + "chromashift=cbh=-4:crh=3", + "noise=alls=10:allf=t+u", + "vignette=PI/5", + "fps=30000/1001", + "format=yuv420p", +].join(","); + +const ffmpeg = spawnSync("ffmpeg", [ + "-hide_banner", "-loglevel", "error", "-y", + "-i", clean, + "-vf", videoFilter, + "-af", "highpass=f=90,lowpass=f=7600,acompressor=threshold=-18dB:ratio=2.2:attack=15:release=180", + "-c:v", "libx264", "-preset", "slow", "-crf", "20", + "-c:a", "aac", "-b:a", "160k", + "-movflags", "+faststart", + final, +], { stdio: "inherit" }); + +if (ffmpeg.status !== 0) throw new Error(`ffmpeg exited ${ffmpeg.status}`); +console.log(`✓ ${final}`); diff --git a/marketing/campaigns/vhs-jeffrey-ac-os/generate-v4-multiview.mjs b/marketing/campaigns/vhs-jeffrey-ac-os/generate-v4-multiview.mjs new file mode 100644 index 0000000000..ef1a55fe5b --- /dev/null +++ b/marketing/campaigns/vhs-jeffrey-ac-os/generate-v4-multiview.mjs @@ -0,0 +1,59 @@ +#!/usr/bin/env node + +import { existsSync } from "node:fs"; +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { spawnSync } from "node:child_process"; +import { generateKlingMotionControlV3 } from "../../../pop/lib/fal.mjs"; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const repo = resolve(HERE, "../../.."); +const source = resolve(HERE, "source-v3-identity.png"); +const driver = resolve(HERE, "jeffrey-ac-os-omnihuman-v1.5.mp4"); +const front = resolve(repo, "xbox/assets/jeffrey-meshy-v6/refs/front.png"); +const threeQuarter = resolve(repo, "xbox/assets/jeffrey-meshy-v6/refs/three-quarter.png"); +const profile = resolve(repo, "xbox/assets/jeffrey-meshy-v6/refs/profile.png"); +const fullBody = resolve(repo, "xbox/assets/jeffrey-meshy-v6/refs/full-body.png"); +const clean = resolve(HERE, "jeffrey-ac-os-kling-v3-multiview.mp4"); +const final = resolve(HERE, "jeffrey-ac-os-vhs-v4-multiview.mp4"); + +if (!existsSync(clean)) { + const result = await generateKlingMotionControlV3({ + image: source, + video: driver, + faceImage: front, + faceReferences: [threeQuarter, profile, fullBody], + prompt: "@Element1 is Jeffrey Alan Scudder, one real person defined jointly by the supplied frontal, three-quarter, profile, and full-body photographs. Preserve Jeffrey's exact facial geometry at every angle: natural eye size and spacing, blue-green eyes, long narrow nose and profile, high forehead, slim jaw and chin, ears, mouth shape, facial asymmetry, skin texture, hairline, and uneven medium-brown hair. The source image exclusively defines Jeffrey's clothing, the black ThinkPad and its Aesthetic Computer screen, lighting, framing, and the entire community-TV studio. Transfer only body movement, head orientation, gaze, expression timing, free-hand gestures, weight shift, forward approach, and camera movement from the driving video. Do not inherit the driving video's identity, facial geometry, hair, clothing, laptop, or environment. Keep Jeffrey recognizable and anatomically stable in wide, medium, close, and partial-profile views. Keep one coherent laptop rigidly supported in his left hand. Preserve the source's photographic texture; no beauty filter, face smoothing, generic presenter face, enlarged eyes, widened jaw, shortened nose, duplicated equipment, or malformed hands.", + characterOrientation: "video", + keepOriginalSound: true, + outPath: clean, + label: "vhs-jeffrey-kling-v3-multiview", + }); + if (!result.ok) throw new Error(result.error); + console.log(`✓ ${clean}`); +} + +const videoFilter = [ + "scale=-2:1920:flags=lanczos", + "pad=1080:1920:(ow-iw)/2:0:black", + "eq=contrast=1.07:brightness=-0.022:saturation=0.72:gamma=0.95", + "chromashift=cbh=-4:crh=3", + "noise=alls=10:allf=t+u", + "vignette=PI/5", + "fps=30000/1001", + "format=yuv420p", +].join(","); + +const ffmpeg = spawnSync("ffmpeg", [ + "-hide_banner", "-loglevel", "error", "-y", + "-i", clean, + "-vf", videoFilter, + "-af", "highpass=f=90,lowpass=f=7600,acompressor=threshold=-18dB:ratio=2.2:attack=15:release=180", + "-c:v", "libx264", "-preset", "slow", "-crf", "20", + "-c:a", "aac", "-b:a", "160k", + "-movflags", "+faststart", + final, +], { stdio: "inherit" }); + +if (ffmpeg.status !== 0) throw new Error(`ffmpeg exited ${ffmpeg.status}`); +console.log(`✓ ${final}`); diff --git a/marketing/campaigns/vhs-jeffrey-ac-os/generate.mjs b/marketing/campaigns/vhs-jeffrey-ac-os/generate.mjs new file mode 100644 index 0000000000..96ca5de22f --- /dev/null +++ b/marketing/campaigns/vhs-jeffrey-ac-os/generate.mjs @@ -0,0 +1,74 @@ +#!/usr/bin/env node + +import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { spawnSync } from "node:child_process"; +import { generateSync3Avatar } from "../../../pop/lib/fal.mjs"; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const source = resolve(HERE, "source.png"); +const scriptPath = resolve(HERE, "script.txt"); +const audio = resolve(HERE, "jeffrey-pvc.mp3"); +const clean = resolve(HERE, "jeffrey-ac-os-clean.mp4"); +const final = resolve(HERE, "jeffrey-ac-os-vhs.mp4"); + +mkdirSync(HERE, { recursive: true }); + +if (!existsSync(audio)) { + const text = readFileSync(scriptPath, "utf8").trim(); + console.log(`→ Jeffrey PVC: ${text}`); + const response = await fetch("https://aesthetic.computer/api/say", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + from: text, + provider: "jeffrey", + voice: "neutral:0", + speed: 1.02, + }), + }); + if (!response.ok) { + throw new Error(`/api/say ${response.status}: ${(await response.text()).slice(0, 240)}`); + } + writeFileSync(audio, Buffer.from(await response.arrayBuffer())); + console.log(`✓ ${audio}`); +} + +if (!existsSync(clean)) { + const result = await generateSync3Avatar({ + image: source, + audio, + outPath: clean, + label: "vhs-jeffrey-ac-os", + }); + if (!result.ok) throw new Error(result.error); + console.log(`✓ ${clean}`); +} + +const videoFilter = [ + "scale=540:810:flags=lanczos", + "crop=532:810:x='4+3*sin(t*11)'", + "scale=720:1096:flags=bicubic", + "pad=720:1280:0:92:black", + "eq=contrast=1.06:brightness=-0.018:saturation=0.76:gamma=0.96", + "chromashift=cbh=-3:crh=3", + "noise=alls=9:allf=t+u", + "vignette=PI/5", + "fps=30000/1001", + "format=yuv420p", +].join(","); + +const ffmpeg = spawnSync("ffmpeg", [ + "-hide_banner", "-loglevel", "error", "-y", + "-i", clean, + "-vf", videoFilter, + "-af", "highpass=f=90,lowpass=f=7800,acompressor=threshold=-18dB:ratio=2.2:attack=15:release=180", + "-c:v", "libx264", "-preset", "slow", "-crf", "20", + "-c:a", "aac", "-b:a", "160k", + "-movflags", "+faststart", + final, +], { stdio: "inherit" }); + +if (ffmpeg.status !== 0) throw new Error(`ffmpeg exited ${ffmpeg.status}`); +console.log(`✓ ${final}`); -- 2.51.2