"""Persistent local Redux worker. No imports of model dependencies until explicit start. Wire protocol: unsigned LE32 payload length (max 65536), type byte, unsigned LE64 request id for T/R/E; Y (ready) and F (load failure) have no id. T refers to the fixed clip.raw in the private directory. R/E carry <=4096 UTF-8 bytes. Only one T may be outstanding. No stdout other than frames; stderr is suppressed by the native launcher. This module never captures audio or delivers input. """ import argparse import hashlib import os from pathlib import Path import stat import struct import sys MAX_FRAME = 65536 MAX_TEXT = 4096 MIN_SAMPLES = 3200 MAX_SAMPLES = 320000 try: from .model_files import REVISION, FILES except ImportError: # direct executable script from model_files import REVISION, FILES class LocalModelError(ValueError): """Missing, incomplete or wrong pinned local weights (never a download cue).""" def read_exact(fd, count): parts = bytearray() while len(parts) < count: part = os.read(fd, count - len(parts)) if not part: if not parts: return None raise ValueError("truncated worker frame") parts.extend(part) return bytes(parts) def read_frame(fd): header = read_exact(fd, 4) if header is None: return None size, = struct.unpack(" MAX_FRAME: raise ValueError("oversize response") frame = struct.pack(" MAX_TEXT: raise ValueError("transcript exceeds 4096 bytes") send_frame(output_fd, b"R", request_id + encoded) except Exception: # Model exceptions may include audio or transcripts. Do not log or # forward them to the overlay; request-local failure only. send_frame(output_fd, b"E", request_id + b"transcription failed") def main(argv=None): parser = argparse.ArgumentParser(description="FrameYap local offline Redux worker") parser.add_argument("--model", required=True) parser.add_argument("--threads", type=int, default=2) parser.add_argument("--clip-dir", required=True) args = parser.parse_args(argv) if not 1 <= args.threads <= 64: parser.error("threads must be 1..64") # Native libraries sometimes print directly to fd 1. Keep those bytes out of # the framed channel, not merely Python's sys.stdout wrapper. protocol_fd = os.dup(1) os.set_inheritable(protocol_fd, False) with open(os.devnull, "wb") as null: os.dup2(null.fileno(), 1) os.dup2(null.fileno(), 2) try: try: private_dir(args.clip_dir) except Exception: send_frame(protocol_fd, b"F", b"M") return 1 try: model = load_model(args.model, args.threads) except LocalModelError: send_frame(protocol_fd, b"F", b"M") return 1 except ImportError: send_frame(protocol_fd, b"F", b"I") return 1 except Exception: send_frame(protocol_fd, b"F", b"D") return 1 run(model, args.clip_dir, output_fd=protocol_fd) return 0 finally: os.close(protocol_fd) if __name__ == "__main__": sys.exit(main())