← back to Consulting Rentv Com
auto-save: 2026-07-23T13:51:43 (2 files) — data/audit-video/compose_noavatar.py data/audit-video/concat_clean.txt
9f15eaa72c639598d0d7bbd7d390a80a6157434a · 2026-07-23 13:51:44 -0700 · Steve Abrams
Files touched
A data/audit-video/compose_noavatar.pyA data/audit-video/concat_clean.txt
Diff
commit 9f15eaa72c639598d0d7bbd7d390a80a6157434a
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Jul 23 13:51:44 2026 -0700
auto-save: 2026-07-23T13:51:43 (2 files) — data/audit-video/compose_noavatar.py data/audit-video/concat_clean.txt
---
data/audit-video/compose_noavatar.py | 66 ++++++++++++++++++++++++++++++++++++
data/audit-video/concat_clean.txt | 3 ++
2 files changed, 69 insertions(+)
diff --git a/data/audit-video/compose_noavatar.py b/data/audit-video/compose_noavatar.py
new file mode 100644
index 0000000..923f3d7
--- /dev/null
+++ b/data/audit-video/compose_noavatar.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python3
+# Same as compose.py but WITHOUT the Steve avatar PIP. Keeps chips + title + outro.
+import json, subprocess, os
+from PIL import Image, ImageDraw, ImageFont
+HERE = os.path.dirname(os.path.abspath(__file__)); os.chdir(HERE)
+nar = json.load(open("narration.json")); tim = json.load(open("timing.json"))
+starts = tim["starts"]; audio_end = tim["audio_end"]; segs = nar["segments"]
+ids = [s["id"] for s in segs]
+ARIAL = "/System/Library/Fonts/Supplemental/Arial Bold.ttf"
+GOLD = (200,161,90); BG = (12,16,22); INK = (238,241,246)
+labels = {
+ "summary":"EXECUTIVE SUMMARY","swot":"SWOT ANALYSIS","reputation":"REPUTATION & AUTHORITY",
+ "empire":"THE EMPIRE & SUBLEASE.COM","competitors":"COMPETITORS","advertising":"WHERE TO ADVERTISE",
+ "timing":"TIMING & CADENCE","audit":"WEBSITE AUDIT","teardown":"PAGE-BY-PAGE TEARDOWN",
+ "social":"SOCIAL MEDIA AUDIT","suggested":"SUGGESTED NEW WEBSITES","partners":"UNLIKELY PARTNERS",
+ "revenue":"UNLIKELY REVENUE","videos":"VIDEO & BRAND FILMS","dealdesk":"LIVE DEAL DESK",
+ "roadmap":"90-DAY ROADMAP",
+}
+os.makedirs("chips", exist_ok=True)
+fnum = ImageFont.truetype(ARIAL, 30); ftxt = ImageFont.truetype(ARIAL, 30)
+padx, pady, gap = 26, 16, 16
+chip_paths = []
+tmp = ImageDraw.Draw(Image.new("RGBA",(10,10)))
+for i, id in enumerate(ids):
+ num = f"{i+1:02d}"; title = labels[id]
+ wn = tmp.textlength(num, font=fnum); wt = tmp.textlength(title, font=ftxt)
+ W = int(padx + wn + gap + wt + padx); H = 62
+ im = Image.new("RGBA", (W, H), (0,0,0,0)); d = ImageDraw.Draw(im)
+ d.rounded_rectangle([0,0,W-1,H-1], radius=8, fill=BG+(210,), outline=GOLD+(120,), width=1)
+ ty = (H-30)//2 - 4
+ d.text((padx, ty), num, font=fnum, fill=GOLD+(255,))
+ d.text((padx+wn+gap, ty), title, font=ftxt, fill=INK+(255,))
+ p = f"chips/{i:02d}.png"; im.save(p); chip_paths.append(p)
+print("chips:", len(chip_paths))
+
+# main body: NO avatar. input 1 kept only so 1:a preserves original length/parity.
+inputs = ["-i","rec/portal-walk.webm","-i","steve-narration.mp4"]
+for p in chip_paths: inputs += ["-i", p]
+fc = ["[0:v]scale=1920:1080,setsar=1,fps=25[bg]"]
+prev = "bg"
+for i, id in enumerate(ids):
+ s = 0.0 if i == 0 else starts[id]
+ e = starts[ids[i+1]] if i+1 < len(ids) else audio_end
+ inp = 2 + i
+ out = f"o{i}"
+ fc.append(f"[{prev}][{inp}:v]overlay=48:H-h-44:enable='between(t,{s:.2f},{e:.2f})'[{out}]")
+ prev = out
+fc_str = ";".join(fc)
+cmd = ["ffmpeg","-y",*inputs,"-filter_complex",fc_str,
+ "-map",f"[{prev}]","-map","1:a",
+ "-c:v","libx264","-pix_fmt","yuv420p","-crf","19","-preset","medium","-r","25",
+ "-c:a","aac","-b:a","160k","-ar","48000","-ac","2","-shortest","main_clean.mp4"]
+print("== main body (no avatar) =="); subprocess.run(cmd, check=True)
+
+def card(png, out, dur):
+ subprocess.run(["ffmpeg","-y","-loop","1","-i",png,"-f","lavfi","-i","anullsrc=r=48000:cl=stereo",
+ "-t",str(dur),"-vf",f"scale=1920:1080,fps=25,fade=in:0:15,fade=out:st={dur-0.6:.2f}:d=0.6",
+ "-c:v","libx264","-pix_fmt","yuv420p","-r","25","-c:a","aac","-b:a","160k","-shortest",out], check=True)
+print("== title / outro =="); card("title.png","title.mp4",4.0); card("outro.png","outro.mp4",4.0)
+
+open("concat_clean.txt","w").write("file 'title.mp4'\nfile 'main_clean.mp4'\nfile 'outro.mp4'\n")
+r = subprocess.run(["ffmpeg","-y","-f","concat","-safe","0","-i","concat_clean.txt","-c","copy","clean_final.mp4"])
+if r.returncode != 0:
+ subprocess.run(["ffmpeg","-y","-f","concat","-safe","0","-i","concat_clean.txt",
+ "-c:v","libx264","-pix_fmt","yuv420p","-crf","19","-r","25","-c:a","aac","-b:a","160k","clean_final.mp4"], check=True)
+print("DONE -> clean_final.mp4")
diff --git a/data/audit-video/concat_clean.txt b/data/audit-video/concat_clean.txt
new file mode 100644
index 0000000..4663389
--- /dev/null
+++ b/data/audit-video/concat_clean.txt
@@ -0,0 +1,3 @@
+file 'title.mp4'
+file 'main_clean.mp4'
+file 'outro.mp4'
← d203297 auto-save: 2026-07-23T13:21:35 (1 files) — data/intakes.json
·
back to Consulting Rentv Com
·
portal: drop the outbound rentv.com link (plain text, no lin 4ff250a →