AkurAI Build
Menu

cosmic-mobile

public

Latest 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()