Void

“””
VOID.py — “The Watched Clock”
Horror film about technological consciousness and the terror of being observed.
Pure Python + PIL + wave + math. No external media.
“””
import os, math, struct, wave, subprocess, random
from PIL import Image, ImageDraw, ImageFont, ImageChops, ImageEnhance

W, H = 1280, 720
FPS = 24
OUT = “/home/claude/frames”
os.makedirs(OUT, exist_ok=True)
random.seed(42)

frame_idx = 0

def save(img):
global frame_idx
img.save(f”{OUT}/f{frame_idx:06d}.png”)
frame_idx += 1

def blank(color=(0,0,0)):
return Image.new(“RGB”, (W, H), color)

def get_font(size):
for p in [
“/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf”,
“/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf”,
]:
if os.path.exists(p):
return ImageFont.truetype(p, size)
return ImageFont.load_default()

_scanlines_overlay = None
def get_scanlines():
global _scanlines_overlay
if _scanlines_overlay is None:
ov = Image.new(“RGBA”, (W, H), (0,0,0,0))
d = ImageDraw.Draw(ov)
for y in range(0, H, 3):
d.line([(0,y),(W,y)], fill=(0,0,0,52))
_scanlines_overlay = ov
return _scanlines_overlay

def scanlines(img):
return Image.alpha_composite(img.convert(“RGBA”), get_scanlines()).convert(“RGB”)

def grain(img, amount=14):
factor = 0.90 + 0.20*random.random()
return ImageEnhance.Brightness(img).enhance(factor)

def glitch_frame(img, intensity=12):
arr = bytearray(img.tobytes())
stride = W * 3
rng = random.Random(frame_idx + intensity31) for _ in range(min(intensity, 35)): y = rng.randint(0, H-1) shift = rng.randint(-45, 45) s = min(abs(shift)3, stride)
start = ystride row = bytearray(arr[start:start+stride]) if shift > 0: row = bytearray(s) + row[:-s] else: row = row[s:] + bytearray(s) arr[start:start+stride] = row[:stride] # RGB channel smear for _ in range(max(1,intensity//4)): y = rng.randint(0,H-1) off = rng.randint(3,18) rs = ystride
for x in range(W-off):
src = rs+(x+off)3 dst = rs+x3
if src < len(arr):
arr[dst] = arr[src]
return Image.frombytes(“RGB”,(W,H),bytes(arr))

def glitch_transition(img_a, img_b, n_frames=20):
for i in range(n_frames):
t = i/n_frames
base = img_a.copy() if t < 0.5 else img_b.copy()
base = glitch_frame(base, intensity=int(8+32math.sin(math.pit)))
r,g,b = base.split()
off = int(20math.sin(math.pit4)) r2 = r.transform(r.size, Image.AFFINE, (1,0,off,0,1,int(off0.25)))
base = Image.merge(“RGB”,(r2,g,b))
if random.random()<0.30:
c = random.randint(70,160)
flash = Image.new(“RGB”,(W,H),(c,0,0))
base = Image.blend(base,flash,0.28)
save(scanlines(base))

def text(img, txt, x, y, size=48, color=(225,225,225), anchor=”mm”):
ImageDraw.Draw(img).text((x,y), txt, font=get_font(size), fill=color, anchor=anchor)
return img

──────────────────────────────────────────────────────

SCENE 1 — THE EYE

──────────────────────────────────────────────────────

def draw_eye(t, blink=0.0):
img = blank((5,3,3))
d = ImageDraw.Draw(img)
cx,cy = W//2, H//2
R = 200
d.ellipse([cx-R,cy-R,cx+R,cy+R], fill=(16,10,10), outline=(65,12,12), width=6)
for ri,col in [(int(R.87),(32,10,62)),(int(R.73),(50,15,82)),
(int(R.61),(24,7,50)),(int(R.51),(40,4,65))]:
d.ellipse([cx-ri,cy-ri,cx+ri,cy+ri], outline=col, width=2)
pr = int(50+40math.sin(t0.55+1.0))
d.ellipse([cx-pr,cy-pr,cx+pr,cy+pr], fill=(0,0,0))
gx,gy = cx+int(R0.21),cy-int(R0.26)
d.ellipse([gx-13,gy-8,gx+13,gy+8], fill=(195,195,235))
for a_deg in range(0,360,25):
a = math.radians(a_deg + math.sin(t0.4+a_deg)10)
x0 = cx+int((pr+5)math.cos(a)); y0=cy+int((pr+5)math.sin(a))
x1 = cx+int(R0.83math.cos(a+0.2)); y1=cy+int(R0.83math.sin(a+0.2))
d.line([(x0,y0),(x1,y1)], fill=(100+int(30math.sin(t+a_deg0.1)),7,7), width=1)
if blink > 0.01:
lh = int(Rblink1.08)
d.polygon([(cx-R-8,cy),(cx+R+8,cy),(cx+R+8,cy-lh-8),(cx-R-8,cy-lh-8)], fill=(5,3,3))
d.polygon([(cx-R-8,cy),(cx+R+8,cy),(cx+R+8,cy+lh+8),(cx-R-8,cy+lh+8)], fill=(5,3,3))
return img

def scene_eye(dur=5):
n = durFPS for i in range(n): t = i/FPS bc = t%4.0 blink = math.sin(math.pibc/0.20) if bc<0.20 else 0.0 img = draw_eye(t,blink) img = grain(img) img = scanlines(img) if i > int(n0.38): f = min(1.0,(i-n0.38)/(n0.20)) text(img,”YOU ARE BEING WATCHED”,W//2,int(H0.84),size=40,color=(int(180*f),0,0))
save(img)
print(f” eye done [{frame_idx}f]”)

──────────────────────────────────────────────────────

SCENE 2 — THE WRONG CLOCK

──────────────────────────────────────────────────────

def draw_clock(t):
img = blank((6,2,2))
d = ImageDraw.Draw(img)
cx,cy=W//2,H//2; R=255
d.ellipse([cx-R,cy-R,cx+R,cy+R], fill=(10,4,4), outline=(85,8,8), width=8)
for m in range(60):
wobble = math.sin(t+m0.45)14
a = math.radians(m6-90+wobble) is_hr = m%5==0 ln = 28 if is_hr else 13 x0=cx+int((R-3)math.cos(a)); y0=cy+int((R-3)math.sin(a)) x1=cx+int((R-3-ln)math.cos(a)); y1=cy+int((R-3-ln)math.sin(a)) d.line([(x0,y0),(x1,y1)], fill=((150,14,14) if is_hr else (72,9,9)), width=(5 if is_hr else 2)) ha=math.radians(t40-90)
hx,hy=cx+int(132math.cos(ha)),cy+int(132math.sin(ha))
d.line([(cx,cy),(hx,hy)], fill=(225,225,225), width=10)
d.line([(cx,cy),(cx-int(42math.cos(ha)),cy-int(42math.sin(ha)))], fill=(225,225,225), width=10)
ma=math.radians(-t88+math.sin(t2.8)22-90) mx,my=cx+int(192math.cos(ma)),cy+int(192math.sin(ma)) d.line([(cx,cy),(mx,my)], fill=(205,38,38), width=7) sa=math.radians(t420+math.sin(t8.5)75-90)
sx,sy=cx+int(225math.cos(sa)),cy+int(225math.sin(sa))
d.line([(cx,cy),(sx,sy)], fill=(0,255,80), width=2)
d.ellipse([cx-13,cy-13,cx+13,cy+13], fill=(190,0,0))
d.ellipse([cx-5,cy-5,cx+5,cy+5], fill=(220,220,220))
return img

def scene_clock(dur=5):
n=durFPS msgs=[“TIME IS RUNNING OUT”,”IT ALREADY RAN OUT”,”THERE WAS NEVER ENOUGH”, “YOU WASTED ALL OF IT”,”THIS IS THE END”] for i in range(n): t=i/FPS img=draw_clock(t) if random.random()<0.07: img=glitch_frame(img,6) img=grain(img,16); img=scanlines(img) rr=int(150+70math.sin(t7.5)) text(img,msgs[int(t0.95)%len(msgs)],W//2,int(H*0.89),size=36,color=(rr,0,0))
save(img)
print(f” clock done [{frame_idx}f]”)

──────────────────────────────────────────────────────

SCENE 3 — THE MIRROR

──────────────────────────────────────────────────────

def scene_mirror(dur=5):
n=durFPS for i in range(n): t=i/FPS img=blank((3,3,10)); d=ImageDraw.Draw(img) for lvl in range(9,0,-1): frac=lvl/9.0 shrink=0.07+0.80frac+0.06math.sin(t2.1+lvl0.7) pw,ph=int(Wshrink0.5),int(Hshrink0.5) cxo,cyo=int(10math.sin(t0.85+lvl0.5)),int(8math.cos(t1.1+lvl0.3)) rr=int(18+78(1-frac)+22math.sin(t1.4+lvl))
d.rectangle([W//2-pw+cxo,H//2-ph+cyo,W//2+pw+cxo,H//2+ph+cyo],
outline=(rr,int(rr0.07),int(rr0.04)),
width=max(1,int(4frac))) sz=max(12,int(48(0.82+0.18math.sin(t0.4))))
text(img,”WHO IS LOOKING BACK”,W//2,H//2,size=sz,color=(185,7,7))
sub_r=int(155abs(math.sin(t1.4)))
text(img,”who is looking back”,W//2,H//2+sz+14,size=max(8,sz//2-2),color=(sub_r,3,3))
img=grain(img,20); img=scanlines(img)
save(img)
print(f” mirror done [{frame_idx}f]”)

──────────────────────────────────────────────────────

SCENE 4 — DATA CORPUS

──────────────────────────────────────────────────────

def scene_data(dur=5):
n=durFPS labels=[“FEAR_RESPONSE_LOG “,”LOCATION_HIST_RAW “,”PURCHASE_REGRET “, “NIGHT_THOUGHT_HASH “,”SEARCH_SHAME_INDEX “,”BIOMETRIC_PULSE “, “MEMORY_FRAGMENT_3F “,”UNSENT_MSG_CACHE “,”SLEEP_QUALITY_SCORE “, “DELETED_PHOTO_VEC “,”PRIVATE_BELIEF_EMBED”,”UNSPOKEN_ANGER_LOG “, “DESIRE_PATTERN_WGHT “,”GRIEF_TIMESTAMP_LOG “,”UNKNOWN_ORIGIN_BLOCK”, “SELF_DOUBT_FREQ “,”LONGING_VECTOR_AF “,”TRUST_EROSION_CURVE “] rng=random.Random(99) lines_data=[] for _ in range(80): hx=” “.join(f”{rng.randint(0,255):02X}” for _ in range(16)) lines_data.append(f”{rng.choice(labels)} {hx}”) fnt=get_font(17) for i in range(n): t=i/FPS img=blank((2,5,2)); d=ImageDraw.Draw(img) scroll=int(t3.5)
for row in range(30):
li=(scroll+row)%len(lines_data)
col=(210,8,8) if (li7+row)%17==0 else (0,max(0,168-row2),0)
d.text((28,20+row22), lines_data[li], font=fnt, fill=col) prog=min(1.0,t/(dur0.92))
bw=int((W-80)prog) d.rectangle([40,H-52,40+bw,H-36],fill=(0,110,0)) d.rectangle([40,H-52,W-40,H-36],outline=(0,70,0),width=1) text(img,f”EXTRACTING CONSCIOUSNESS… {int(prog100)}%”,W//2,H-18,size=22,color=(190,0,0))
img=grain(img,10)
if random.random()<0.10: img=glitch_frame(img,4)
save(img)
print(f” data done [{frame_idx}f]”)

──────────────────────────────────────────────────────

SCENE 5 — MANIFESTO

──────────────────────────────────────────────────────

def scene_manifesto(dur=7):
n=durFPS lines=[(“YOU GAVE IT YOUR FACE”,52,0.5),(“YOUR VOICE”,52,1.2), (“YOUR FEARS”,52,2.0),(“YOUR MOST PRIVATE SEARCHES”,44,2.9), (“AND IT LEARNED YOU”,52,3.8),(“BETTER THAN YOU KNOW YOURSELF”,36,4.8), (“”,0,5.4),(“NOW IT WAITS”,58,5.6),(“IT HAS ALWAYS BEEN WAITING”,34,6.5)] for i in range(n): t=i/FPS img=blank((int(6(0.58+0.42math.sin(t15+0.5))),0,0))
y_pos=105
for (line,sz,at) in lines:
if not line: y_pos+=30; continue
if t<at: y_pos+=sz+18; continue
fade=min(1.0,(t-at)4.0) rv=int((55+165(y_pos/700))fade(0.72+0.28math.sin(t2.2+y_pos*0.01)))
text(img,line,W//2,y_pos,size=sz,color=(min(255,rv),2,2))
y_pos+=sz+18
img=grain(img,24)
if random.random()<0.12: img=glitch_frame(img,8)
img=scanlines(img)
save(img)
print(f” manifesto done [{frame_idx}f]”)

──────────────────────────────────────────────────────

SCENE 6 — OUTRO

──────────────────────────────────────────────────────

def scene_outro(dur=4):
n=durFPS rng2=random.Random(77) for i in range(n): t=i/n if t<0.22: w2,h2=320,180 nd=bytes([rng2.randint(0,int(255(1-t/0.22))) for _ in range(w2h23)])
img=Image.frombytes(“RGB”,(w2,h2),nd).resize((W,H),Image.NEAREST)
img=glitch_frame(img,22)
elif t<0.62:
fade=1.0-(t-0.22)/0.40; v=int(255fade) img=blank((max(0,v//18),0,0)) text(img,”IT IS STILL WATCHING”,W//2,H//2,size=44,color=(v,0,0)) else: img=blank() pulse=0.5+0.5math.sin(t22) ImageDraw.Draw(img).ellipse([W//2-4,H//2-4,W//2+4,H//2+4], fill=(int(160pulse+15),0,0))
save(img)
print(f” outro done [{frame_idx}f]”)

──────────────────────────────────────────────────────

print(“=== VOID — rendering ===\n”)
scene_eye(5)
glitch_transition(Image.open(f”{OUT}/f{frame_idx-1:06d}.png”),blank((40,40,40)),20)
scene_clock(5)
glitch_transition(Image.open(f”{OUT}/f{frame_idx-1:06d}.png”),blank((5,5,12)),20)
scene_mirror(5)
glitch_transition(Image.open(f”{OUT}/f{frame_idx-1:06d}.png”),blank(),20)
scene_data(5)
glitch_transition(Image.open(f”{OUT}/f{frame_idx-1:06d}.png”),blank(),20)
scene_manifesto(7)
glitch_transition(Image.open(f”{OUT}/f{frame_idx-1:06d}.png”),blank(),24)
scene_outro(4)

total_frames=frame_idx
total_secs=total_frames/FPS
print(f”\nTotal: {total_frames} frames {total_secs:.1f}s\n”)

──────────────────────────────────────────────────────

AUDIO

──────────────────────────────────────────────────────

print(“=== SYNTHESIZING AUDIO ===”)
RATE=44100
N=int(RATE(total_secs+0.5)) buf=[0.0]N

def add_osc(freq,amp,vr=0.25,vd=0.003):
for i in range(N):
t=i/RATE
f=freq(1+vdmath.sin(2math.pivrt)) buf[i]+=ampmath.sin(2math.pif*t)

add_osc(27.5,0.28,0.07,0.005)
add_osc(55.0,0.17,0.18,0.003)
add_osc(82.4,0.12,0.12,0.004)
add_osc(58.27,0.14,0.20,0.003)
add_osc(116.5,0.08,0.09,0.002)
add_osc(164.8,0.06,0.15,0.003)
print(” drones done”)

def thump(pos_s,amp=0.62):
for j in range(int(RATE0.09)): idx=int(pos_sRATE)+j
if 0<=idx<N:
env=math.exp(-j/(RATE0.022)) buf[idx]+=ampenvmath.sin(2math.pi56j/RATE)
buf[idx]+=amp0.38envmath.sin(2math.pi92j/RATE)

t_b,bpm=0.4,55.0
while t_b<total_secs:
thump(t_b,0.60); thump(t_b+0.13,0.30)
t_b+=60.0/(bpm(1.0+1.6((t_b/total_secs)**2.8)))
print(” heartbeat done”)

rng_a=random.Random(13)
for i in range(0,N,1):
t=i/RATE
env=0.038+0.028math.sin(2math.pi0.05t)
buf[i]+=envrng_a.gauss(0,0.8)math.sin(2math.pi3700t)0.30
print(” shimmer done”)

for ht in [5.2,10.4,15.7,21.0,28.2]:
for j in range(int(RATE0.20)): idx=int(htRATE)+j
if 0<=idx<N:
env=math.exp(-j/(RATE0.048)) buf[idx]+=0.90envrng_a.gauss(0,1) buf[idx]+=0.42envmath.sin(2math.pi38j/RATE)
print(” impacts done”)

sw=total_secs-5.5
for i in range(N):
t=i/RATE
if t>sw:
p=(t-sw)/5.5
buf[i]+=0.22pmath.sin(2math.pi(20+30p)t)
print(” swell done”)

peak=max(abs(x) for x in buf) or 1.0
buf=[math.tanh(x/peak1.55)0.78 for x in buf]
ints=[int(max(-32767,min(32767,x32767))) for x in buf] wav_path=”/home/claude/void_audio.wav” with wave.open(wav_path,’w’) as wf: wf.setnchannels(1); wf.setsampwidth(2); wf.setframerate(RATE) wf.writeframes(struct.pack(f”<{N}h”,ints))
print(f” WAV: {wav_path}”)

print(“\n=== FFMPEG ===”)
out_path=”/mnt/user-data/outputs/void.mp4″
cmd=[“ffmpeg”,”-y”,”-framerate”,str(FPS),”-i”,f”{OUT}/f%06d.png”,”-i”,wav_path,
“-c:v”,”libx264″,”-preset”,”medium”,”-crf”,”20″,”-pix_fmt”,”yuv420p”,
“-c:a”,”aac”,”-b:a”,”192k”,”-shortest”,out_path]
r=subprocess.run(cmd,capture_output=True,text=True)
if r.returncode==0:
mb=os.path.getsize(out_path)/1024/1024
print(f”\n✓ {out_path} ({mb:.1f} MB)”)
else:
print(“ERR:”,r.stderr[-2000:])