MySafeCode commited on
Commit
0a14bc2
Β·
verified Β·
1 Parent(s): dcc2634

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +215 -136
app.py CHANGED
@@ -3,191 +3,270 @@ import time
3
  import threading
4
  import base64
5
  import os
 
6
  from flask import Flask, render_template_string
7
  from flask_socketio import SocketIO, emit
8
  from io import BytesIO
9
 
 
 
 
 
10
  os.environ['SDL_VIDEODRIVER'] = 'dummy'
11
 
12
  try:
13
  pygame.init()
14
- print("βœ… PyGame initialized successfully")
15
  except Exception as e:
16
- print(f"❌ PyGame init failed: {e}")
17
- # Create a fallback mode
18
 
 
 
19
  app = Flask(__name__)
20
- app.config['SECRET_KEY'] = 'simple_stream_key'
21
-
22
- # Use threading mode - avoids eventlet issues
23
- socketio = SocketIO(app, async_mode='threading', cors_allowed_origins="*")
24
 
 
 
25
  WIDTH, HEIGHT = 400, 300
26
  shared = {
27
  "streaming": True,
28
  "x": 200,
29
  "frame_count": 0,
30
- "clients": 0
 
31
  }
32
 
 
33
  def game_loop():
34
- """Simple PyGame loop"""
35
- print("🎬 Starting PyGame loop")
 
 
 
 
 
 
 
 
 
 
36
 
37
- # Test PyGame drawing
38
- test_screen = pygame.Surface((100, 100))
39
- test_screen.fill((255, 0, 0))
40
- pygame.draw.circle(test_screen, (0, 255, 0), (50, 50), 30)
41
- test_pixel = test_screen.get_at((50, 50))
42
- print(f"πŸ§ͺ PyGame test - Pixel at (50,50): {test_pixel}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
- if test_pixel != (0, 255, 0, 255):
45
- print("⚠️ WARNING: PyGame drawing might not work correctly")
46
 
47
- # Main game surface
48
  screen = pygame.Surface((WIDTH, HEIGHT))
49
  x, speed = 200, 5
50
-
51
- frame_counter = 0
52
- last_log_time = time.time()
53
 
54
  while shared["streaming"]:
55
- start_time = time.time()
56
-
57
- # Update
58
- x += speed
59
- if x < 30 or x > WIDTH-30:
60
- speed *= -1
61
-
62
- # Draw
63
- screen.fill((25, 25, 45))
64
- pygame.draw.circle(screen, (255, 80, 80), (int(x), 150), 20)
65
-
66
- # Convert to JPEG
67
- buf = BytesIO()
68
- pygame.image.save(screen, buf, format='JPEG', quality=85)
69
- frame_b64 = base64.b64encode(buf.getvalue()).decode('utf-8')
70
-
71
- # Broadcast frame
72
- socketio.emit('new_frame', {
73
- 'frame': frame_b64,
74
- 'count': shared['frame_count'],
75
- 'x': x,
76
- 'timestamp': time.time()
77
- })
78
-
79
- # Update shared state
80
- shared['x'] = x
81
- shared['frame_count'] += 1
82
- frame_counter += 1
83
-
84
- # Log every second
85
- current_time = time.time()
86
- if current_time - last_log_time >= 1.0:
87
- print(f"πŸ“Š FPS: {frame_counter} | Total: {shared['frame_count']} | Clients: {shared['clients']}")
88
- frame_counter = 0
89
- last_log_time = current_time
90
-
91
- # Frame rate control
92
- elapsed = time.time() - start_time
93
- if elapsed < 1.0/30:
94
- time.sleep(1.0/30 - elapsed)
95
 
96
- print("πŸ›‘ PyGame loop stopped")
 
 
 
 
 
 
 
 
 
 
 
 
97
 
98
  @app.route('/')
99
  def index():
100
  return render_template_string('''
101
  <!DOCTYPE html>
102
- <html>
103
- <head>
104
- <script src="https://cdn.socket.io/4.5.0/socket.io.min.js"></script>
105
- <style>
106
- body { background: #0f172a; color: white; text-align: center; padding: 20px; }
107
- #streamImg { border: 3px solid #60a5fa; width: 400px; height: 300px; }
108
- .stats { background: #1e293b; padding: 15px; border-radius: 10px; margin: 20px auto; width: 400px; }
109
- </style>
110
- </head>
111
- <body>
112
- <h1>πŸ”„ Working PyGame Stream</h1>
113
-
114
- <img id="streamImg">
115
-
116
- <div class="stats">
117
- <div>Frame: <span id="counter">0</span></div>
118
- <div>Position: X=<span id="pos">200</span></div>
119
- <div>Status: <span id="status">Connecting...</span></div>
120
- <div>Clients: <span id="clients">0</span></div>
121
- </div>
122
-
123
- <script>
124
- const socket = io();
125
- let streamFrames = 0;
126
- let lastFpsUpdate = Date.now();
127
 
128
- socket.on('connect', () => {
129
- console.log('βœ… Connected to server');
130
- document.getElementById('status').textContent = 'Connected';
131
- document.body.style.background = '#1a5c1a';
132
- });
133
 
134
- socket.on('new_frame', (data) => {
135
- // Update image
136
- document.getElementById('streamImg').src =
137
- 'data:image/jpeg;base64,' + data.frame;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
 
139
- // Update stats
140
- document.getElementById('counter').textContent = data.count;
141
- document.getElementById('pos').textContent = data.x;
 
 
 
142
 
143
- // Calculate stream FPS
144
- streamFrames++;
145
- const now = Date.now();
146
- if (now - lastFpsUpdate >= 1000) {
147
- document.title = `Stream FPS: ${streamFrames}`;
148
- streamFrames = 0;
149
- lastFpsUpdate = now;
 
150
  }
151
- });
152
-
153
- socket.on('client_count', (count) => {
154
- document.getElementById('clients').textContent = count;
155
- });
156
-
157
- socket.on('disconnect', () => {
158
- document.getElementById('status').textContent = 'Disconnected';
159
- document.body.style.background = '#5c1a1a';
160
- });
161
-
162
- console.log('SocketIO client started');
163
- </script>
164
- </body>
165
- </html>
 
 
 
166
  ''')
167
 
168
  @socketio.on('connect')
169
  def handle_connect():
170
  shared['clients'] += 1
171
- print(f"Client connected. Total: {shared['clients']}")
172
- socketio.emit('client_count', shared['clients'])
 
 
 
173
 
174
  @socketio.on('disconnect')
175
  def handle_disconnect():
176
  shared['clients'] -= 1
177
- print(f"Client disconnected. Total: {shared['clients']}")
178
- socketio.emit('client_count', shared['clients'])
 
 
 
 
 
 
 
 
179
 
 
 
 
 
 
 
 
 
 
 
 
180
  if __name__ == '__main__':
181
- print("πŸš€ Starting server...")
182
-
183
- # Start PyGame thread
184
- game_thread = threading.Thread(target=game_loop, daemon=True)
185
- game_thread.start()
186
-
187
- # Give it a moment
188
- time.sleep(1)
189
-
190
- # Start server
191
  socketio.run(
192
  app,
193
  host='0.0.0.0',
 
3
  import threading
4
  import base64
5
  import os
6
+ import sys
7
  from flask import Flask, render_template_string
8
  from flask_socketio import SocketIO, emit
9
  from io import BytesIO
10
 
11
+ print("πŸ” [START] Script loading", file=sys.stderr)
12
+
13
+ # ===== 1. PYGAME INIT =====
14
+ print("πŸ” [1/5] Setting up PyGame", file=sys.stderr)
15
  os.environ['SDL_VIDEODRIVER'] = 'dummy'
16
 
17
  try:
18
  pygame.init()
19
+ print("βœ… [1/5] PyGame initialized", file=sys.stderr)
20
  except Exception as e:
21
+ print(f"❌ [1/5] PyGame failed: {e}", file=sys.stderr)
22
+ sys.exit(1)
23
 
24
+ # ===== 2. FLASK/SOCKETIO INIT =====
25
+ print("πŸ” [2/5] Creating Flask app", file=sys.stderr)
26
  app = Flask(__name__)
27
+ app.config['SECRET_KEY'] = 'debug_key'
28
+ socketio = SocketIO(app, async_mode='threading', cors_allowed_origins="*", logger=True, engineio_logger=True)
 
 
29
 
30
+ # ===== 3. SHARED STATE =====
31
+ print("πŸ” [3/5] Setting up shared state", file=sys.stderr)
32
  WIDTH, HEIGHT = 400, 300
33
  shared = {
34
  "streaming": True,
35
  "x": 200,
36
  "frame_count": 0,
37
+ "clients": 0,
38
+ "thread_alive": False
39
  }
40
 
41
+ # ===== 4. PYGAME THREAD =====
42
  def game_loop():
43
+ print("🎬 [THREAD START] PyGame thread entered", file=sys.stderr)
44
+ shared["thread_alive"] = True
45
+
46
+ # TEST 1: Can we create a surface?
47
+ try:
48
+ test_screen = pygame.Surface((100, 100))
49
+ test_screen.fill((255, 0, 0))
50
+ print("βœ… [TEST 1] Surface created", file=sys.stderr)
51
+ except Exception as e:
52
+ print(f"❌ [TEST 1] Surface failed: {e}", file=sys.stderr)
53
+ shared["thread_alive"] = False
54
+ return
55
 
56
+ # TEST 2: Can we draw?
57
+ try:
58
+ pygame.draw.circle(test_screen, (0, 255, 0), (50, 50), 30)
59
+ pixel = test_screen.get_at((50, 50))
60
+ print(f"βœ… [TEST 2] Drawing test - Pixel: {pixel}", file=sys.stderr)
61
+
62
+ if pixel == (0, 255, 0, 255):
63
+ print("🎯 [TEST 2] PyGame drawing WORKS!", file=sys.stderr)
64
+ else:
65
+ print(f"⚠️ [TEST 2] Unexpected pixel color: {pixel}", file=sys.stderr)
66
+ except Exception as e:
67
+ print(f"❌ [TEST 2] Drawing failed: {e}", file=sys.stderr)
68
+ shared["thread_alive"] = False
69
+ return
70
+
71
+ # TEST 3: Can we save to JPEG?
72
+ try:
73
+ buf = BytesIO()
74
+ pygame.image.save(test_screen, buf, format='JPEG')
75
+ test_frame = base64.b64encode(buf.getvalue()).decode('utf-8')
76
+ print(f"βœ… [TEST 3] JPEG save works - Frame size: {len(test_frame)}", file=sys.stderr)
77
+ except Exception as e:
78
+ print(f"❌ [TEST 3] JPEG save failed: {e}", file=sys.stderr)
79
+ shared["thread_alive"] = False
80
+ return
81
 
82
+ # If all tests pass, start main loop
83
+ print("πŸš€ [THREAD READY] Starting main game loop", file=sys.stderr)
84
 
 
85
  screen = pygame.Surface((WIDTH, HEIGHT))
86
  x, speed = 200, 5
87
+ frame_log_counter = 0
 
 
88
 
89
  while shared["streaming"]:
90
+ try:
91
+ # Update
92
+ x += speed
93
+ if x < 30 or x > WIDTH-30:
94
+ speed *= -1
95
+
96
+ # Draw
97
+ screen.fill((25, 25, 45))
98
+ pygame.draw.circle(screen, (255, 80, 80), (int(x), 150), 20)
99
+
100
+ # Save
101
+ buf = BytesIO()
102
+ pygame.image.save(screen, buf, format='JPEG', quality=85)
103
+ frame_b64 = base64.b64encode(buf.getvalue()).decode('utf-8')
104
+
105
+ # Emit
106
+ socketio.emit('new_frame', {
107
+ 'frame': frame_b64,
108
+ 'count': shared['frame_count'],
109
+ 'x': x,
110
+ 'timestamp': time.time()
111
+ })
112
+
113
+ # Update state
114
+ shared['x'] = x
115
+ shared['frame_count'] += 1
116
+ frame_log_counter += 1
117
+
118
+ # Log every 10 frames
119
+ if frame_log_counter >= 10:
120
+ print(f"πŸ“¦ [THREAD LOOP] Frame {shared['frame_count']}, X={x}", file=sys.stderr)
121
+ frame_log_counter = 0
122
+
123
+ # Sleep for FPS
124
+ time.sleep(1.0/30)
125
+
126
+ except Exception as e:
127
+ print(f"❌ [THREAD ERROR] {e}", file=sys.stderr)
128
+ break
 
129
 
130
+ print("πŸ›‘ [THREAD END] PyGame thread exiting", file=sys.stderr)
131
+ shared["thread_alive"] = False
132
+
133
+ print("πŸ” [4/5] Starting PyGame thread", file=sys.stderr)
134
+ game_thread = threading.Thread(target=game_loop, daemon=True, name="PyGameThread")
135
+ game_thread.start()
136
+
137
+ # Wait a moment to see if thread starts
138
+ time.sleep(1)
139
+ print(f"πŸ“Š [4/5] Thread status - Alive: {game_thread.is_alive()}, Shared alive: {shared['thread_alive']}", file=sys.stderr)
140
+
141
+ # ===== 5. FLASK ROUTES =====
142
+ print("πŸ” [5/5] Setting up Flask routes", file=sys.stderr)
143
 
144
  @app.route('/')
145
  def index():
146
  return render_template_string('''
147
  <!DOCTYPE html>
148
+ <html>
149
+ <head>
150
+ <script src="https://cdn.socket.io/4.5.0/socket.io.min.js"></script>
151
+ <style>
152
+ body { background: #0f172a; color: white; text-align: center; padding: 20px; }
153
+ #streamImg { border: 3px solid #60a5fa; width: 400px; height: 300px; }
154
+ .debug { background: #1e293b; padding: 15px; border-radius: 10px; margin: 20px auto; width: 400px; text-align: left; }
155
+ </style>
156
+ </head>
157
+ <body>
158
+ <h1>πŸ› Debug Stream</h1>
159
+
160
+ <div class="debug">
161
+ <div>Server Time: <span id="server_time">--:--:--</span></div>
162
+ <div>Thread Alive: <span id="thread_status">Checking...</span></div>
163
+ <div>Frames Sent: <span id="frames_sent">0</span></div>
164
+ <div>Last Frame: <span id="last_frame">Never</span></div>
165
+ <div>Connection: <span id="conn_status">Connecting...</span></div>
166
+ </div>
 
 
 
 
 
 
167
 
168
+ <img id="streamImg">
 
 
 
 
169
 
170
+ <div style="margin-top: 20px;">
171
+ <button onclick="manualCheck()">πŸ” Check Status</button>
172
+ <button onclick="forceFrame()">πŸ”„ Force Frame</button>
173
+ </div>
174
+
175
+ <script>
176
+ const socket = io();
177
+ let lastFrameTime = 0;
178
+
179
+ socket.on('connect', () => {
180
+ console.log('βœ… Socket connected');
181
+ document.getElementById('conn_status').textContent = 'Connected';
182
+ document.getElementById('conn_status').style.color = '#10b981';
183
+
184
+ // Request initial status
185
+ socket.emit('get_status');
186
+ });
187
+
188
+ socket.on('new_frame', (data) => {
189
+ console.log('πŸ“₯ Frame received:', data.count);
190
+ document.getElementById('streamImg').src =
191
+ 'data:image/jpeg;base64,' + data.frame;
192
+ document.getElementById('frames_sent').textContent = data.count;
193
+ document.getElementById('last_frame').textContent =
194
+ new Date().toLocaleTimeString();
195
+ lastFrameTime = Date.now();
196
+ });
197
 
198
+ socket.on('status_update', (data) => {
199
+ document.getElementById('thread_status').textContent =
200
+ data.thread_alive ? 'βœ… Alive' : '❌ Dead';
201
+ document.getElementById('server_time').textContent =
202
+ new Date(data.timestamp * 1000).toLocaleTimeString();
203
+ });
204
 
205
+ socket.on('disconnect', () => {
206
+ document.getElementById('conn_status').textContent = 'Disconnected';
207
+ document.getElementById('conn_status').style.color = '#ef4444';
208
+ });
209
+
210
+ function manualCheck() {
211
+ console.log('Manual check');
212
+ socket.emit('get_status');
213
  }
214
+
215
+ function forceFrame() {
216
+ console.log('Requesting test frame');
217
+ socket.emit('request_frame');
218
+ }
219
+
220
+ // Auto-check every 5 seconds
221
+ setInterval(() => {
222
+ if (Date.now() - lastFrameTime > 2000) {
223
+ console.log('No frames for 2 seconds, checking...');
224
+ socket.emit('get_status');
225
+ }
226
+ }, 5000);
227
+
228
+ console.log('Debug client ready');
229
+ </script>
230
+ </body>
231
+ </html>
232
  ''')
233
 
234
  @socketio.on('connect')
235
  def handle_connect():
236
  shared['clients'] += 1
237
+ print(f"πŸ‘€ [CLIENT] Connected - Total: {shared['clients']}", file=sys.stderr)
238
+ socketio.emit('status_update', {
239
+ 'thread_alive': shared['thread_alive'],
240
+ 'timestamp': time.time()
241
+ })
242
 
243
  @socketio.on('disconnect')
244
  def handle_disconnect():
245
  shared['clients'] -= 1
246
+ print(f"πŸ‘€ [CLIENT] Disconnected - Total: {shared['clients']}", file=sys.stderr)
247
+
248
+ @socketio.on('get_status')
249
+ def handle_status():
250
+ print(f"πŸ“‘ [STATUS REQ] Thread alive: {shared['thread_alive']}, Frames: {shared['frame_count']}", file=sys.stderr)
251
+ socketio.emit('status_update', {
252
+ 'thread_alive': shared['thread_alive'],
253
+ 'frame_count': shared['frame_count'],
254
+ 'timestamp': time.time()
255
+ })
256
 
257
+ @socketio.on('request_frame')
258
+ def handle_frame_request():
259
+ print(f"πŸ“‘ [FRAME REQ] Client requested frame", file=sys.stderr)
260
+ # Send the current frame if we have one
261
+ if shared['frame_count'] > 0:
262
+ # We'd need to store the last frame to send it
263
+ pass
264
+
265
+ print("βœ… [SETUP COMPLETE] Flask app ready", file=sys.stderr)
266
+
267
+ # ===== START SERVER =====
268
  if __name__ == '__main__':
269
+ print("πŸš€ [MAIN] Starting server on port 7860", file=sys.stderr)
 
 
 
 
 
 
 
 
 
270
  socketio.run(
271
  app,
272
  host='0.0.0.0',