import pygame import time import threading import numpy as np import base64 import zlib import os from flask import Flask, render_template_string from flask_socketio import SocketIO, emit # ===== PYGAME SETUP ===== os.environ['SDL_VIDEODRIVER'] = 'dummy' pygame.init() print("โœ… PyGame initialized with surfarray") WIDTH, HEIGHT = 400, 300 # Create surface screen = pygame.Surface((WIDTH, HEIGHT)) print(f"โœ… Surface: {WIDTH}x{HEIGHT}") # Test surfarray print("๐Ÿงช Testing surfarray...") test_arr = pygame.surfarray.array3d(screen) print(f"โœ… Surfarray works! Shape: {test_arr.shape}, Type: {test_arr.dtype}") # ===== FLASK/SOCKETIO ===== app = Flask(__name__) app.config['SECRET_KEY'] = 'surfarray_stream' socketio = SocketIO(app, async_mode='threading', cors_allowed_origins="*") # Shared state shared = { "running": True, "x": 200, "frame_count": 0, "clients": 0 } # ===== SURFARRAY THREAD ===== def surfarray_thread(): """Send raw pixel arrays via WebSocket""" print("๐Ÿ“Š Surfarray thread STARTED") x, speed = 200, 5 fps_counter = 0 last_log = time.time() while shared["running"]: try: start_time = time.time() # 1. UPDATE POSITION x += speed if x < 30 or x > WIDTH-30: speed *= -1 # 2. DRAW screen.fill((25, 25, 45)) # Dark blue pygame.draw.circle(screen, (255, 80, 80), (int(x), 150), 20) pygame.draw.circle(screen, (255, 255, 255), (int(x), 150), 20, 2) # 3. GET PIXEL ARRAY (FAST!) pixel_array = pygame.surfarray.array3d(screen) # Shape: (400, 300, 3) # 4. COMPRESS (optional but recommended) # Flatten and compress the array flat_data = pixel_array.flatten().tobytes() compressed = zlib.compress(flat_data, level=1) # Fast compression encoded = base64.b64encode(compressed).decode('utf-8') # 5. BROADCAST shared["x"] = x shared["frame_count"] += 1 socketio.emit('pixel_data', { 'pixels': encoded, 'shape': [WIDTH, HEIGHT, 3], # Send dimensions 'frame': shared["frame_count"], 'x': x, 'compressed': True }) # 6. LOGGING fps_counter += 1 current_time = time.time() if current_time - last_log >= 1.0: print(f"๐Ÿ“Š Sent {fps_counter} frames | Frame {shared['frame_count']} | X={x}") fps_counter = 0 last_log = current_time # 7. FRAME RATE elapsed = time.time() - start_time if elapsed < 1.0/30: time.sleep(1.0/30 - elapsed) except Exception as e: print(f"โŒ Surfarray thread error: {e}") import traceback traceback.print_exc() break print("๐Ÿ›‘ Surfarray thread STOPPED") # ===== START THREAD ===== thread = threading.Thread(target=surfarray_thread, daemon=True) thread.start() print(f"โœ… Thread alive: {thread.is_alive()}") # ===== FLASK ROUTES ===== @app.route('/') def index(): return render_template_string('''

๐Ÿ“Š Surfarray Stream

Frame: 0
Circle X: 200
Status: Connecting...
FPS: 0
Data size: 0 KB
''') @socketio.on('connect') def handle_connect(): shared['clients'] += 1 print(f"๐Ÿ‘ค Client connected. Total: {shared['clients']}") @socketio.on('disconnect') def handle_disconnect(): shared['clients'] -= 1 print(f"๐Ÿ‘ค Client disconnected. Total: {shared['clients']}") if __name__ == '__main__': print("๐Ÿš€ Starting surfarray server...") # Wait for thread time.sleep(1) print(f"๐Ÿ“Š Initial: Thread alive={thread.is_alive()}, Frames={shared['frame_count']}") socketio.run( app, host='0.0.0.0', port=int(os.environ.get('PORT', 7860)), debug=False, use_reloader=False, allow_unsafe_werkzeug=True )