Menu
cosmic-mobile
publicLatest change d22956783f74f68f3d7eff1dd31f885aaf0fbe3e - Checkpoint BúiOS prototype and document clean-worktree workflow by AkurAI Build
#!/usr/bin/env python3
"""Record live guest screenshots, tap Terminal, stop once it opens."""
import json
import socket
import subprocess
import time
from pathlib import Path
from emu import call
ROOT = Path(__file__).resolve().parent
OUT = ROOT / 'runtime/captures'
def main():
call('home')
time.sleep(.5)
before = {w['id'] for w in call('windows')}
frames = []
opened = None
with socket.socket(socket.AF_UNIX) as sock:
sock.settimeout(10)
sock.connect(str(ROOT / 'runtime/qmp.sock'))
stream = sock.makefile('rwb')
def qmp(command, arguments=None):
stream.write((json.dumps({'execute': command, 'arguments': arguments or {}})+'\n').encode())
stream.flush()
while True:
result = json.loads(stream.readline())
if 'error' in result:
raise RuntimeError(result['error'])
if 'return' in result:
return result['return']
stream.readline()
qmp('qmp_capabilities')
start = time.monotonic()
tapped = False
while time.monotonic() - start < 20:
name = f'record-terminal-{len(frames):04d}'
path = OUT / (name + '.png')
path.unlink(missing_ok=True)
call('shot', name)
deadline = time.monotonic() + 3
while not path.is_file() and time.monotonic() < deadline:
time.sleep(.02)
assert path.is_file(), path
frames.append((path, time.monotonic()))
elapsed = time.monotonic() - start
if elapsed >= 2 and not tapped:
qmp('input-send-event', {'events': [
{'type': 'abs', 'data': {'axis': 'x', 'value': round(372 / 899 * 32767)}},
{'type': 'abs', 'data': {'axis': 'y', 'value': round(948 / 1979 * 32767)}}]})
qmp('input-send-event', {'events': [{'type': 'btn', 'data': {'down': True, 'button': 'left'}}]})
qmp('input-send-event', {'events': [{'type': 'btn', 'data': {'down': False, 'button': 'left'}}]})
tapped = True
if tapped and opened is None:
windows = call('windows')
terminal = next((w for w in windows if w.get('app_id') == 'Alacritty' and w.get('is_focused')), None)
if terminal:
opened = time.monotonic()
if opened and time.monotonic() - opened >= 2:
break
time.sleep(.05)
assert opened is not None, 'Terminal did not open; recording not declared successful'
manifest = OUT / 'terminal-recording.txt'
lines = []
for i, (path, timestamp) in enumerate(frames):
duration = frames[i+1][1] - timestamp if i+1 < len(frames) else .2
lines.extend([f"file '{path}'", f'duration {duration:.6f}'])
lines.append(f"file '{frames[-1][0]}'")
manifest.write_text('\n'.join(lines)+'\n')
video = OUT / 'terminal-opening.mp4'
subprocess.run(['ffmpeg','-hide_banner','-loglevel','error','-y','-f','concat','-safe','0','-i',str(manifest),'-vf','fps=15','-c:v','libx264','-pix_fmt','yuv420p','-movflags','+faststart',str(video)], check=True)
print(json.dumps({'video': str(video), 'frames': len(frames), 'last_frame': str(frames[-1][0]), 'terminal_opened': True}))
if __name__ == '__main__':
main()