flaskdockernew / flickapp.py
MySafeCode's picture
Rename app.py to flickapp.py
712bc5c verified
#!/usr/bin/env python3
# pygame_fixed_format.py - Fixed byte order
import pygame,os
import numpy as np
import time
import threading
from flask import Flask, Response
import io
# Setup
os.environ['SDL_VIDEODRIVER'] = 'dummy'
WIDTH, HEIGHT = 400, 300
app = Flask(__name__)
# Shared state
frame_data = {
"jpeg_bytes": None, # Store as JPEG for smaller size
"frame_id": 0,
"lock": threading.Lock()
}
@app.route('/')
def index():
return '''<!DOCTYPE html>
<html>
<head>
<title>PyGame Stream</title>
<meta http-equiv="refresh" content="0.1">
<style>body { margin: 0; padding: 20px; text-align: center; }</style>
</head>
<body>
<h1>Auto-Refresh (10 FPS)</h1>
<img src="/frame" width="400" height="300" style="border:3px solid blue;">
<p>Refreshing every 100ms...</p>
</body>
</html>'''
@app.route('/frame')
def get_frame():
"""Return frame as JPEG (smaller, faster)"""
with frame_data["lock"]:
if frame_data["jpeg_bytes"]:
return Response(
frame_data["jpeg_bytes"],
mimetype='image/jpeg',
headers={'Cache-Control': 'no-cache'}
)
# Return loading image
return create_loading_image()
def create_loading_image():
"""Create a simple loading image"""
from PIL import Image, ImageDraw
import io as imageio
img = Image.new('RGB', (WIDTH, HEIGHT), color='blue')
draw = ImageDraw.Draw(img)
draw.text((150, 140), 'LOADING...', fill='white')
buffer = imageio.BytesIO()
img.save(buffer, 'JPEG')
return Response(buffer.getvalue(), mimetype='image/jpeg')
def pygame_render():
"""PyGame render loop with FIXED format"""
print("🎬 Starting PyGame with fixed format...")
try:
pygame.init()
surface = pygame.Surface((WIDTH, HEIGHT))
print("βœ… PyGame initialized")
except Exception as e:
print(f"❌ PyGame init failed: {e}")
return
# Simple bouncing balls (fewer for clarity)
balls = [
{'x': 100, 'y': 150, 'dx': 3, 'dy': 2, 'r': 20, 'color': (255, 100, 100)},
{'x': 300, 'y': 100, 'dx': -2, 'dy': 3, 'r': 15, 'color': (100, 255, 100)},
{'x': 200, 'y': 200, 'dx': 4, 'dy': -1, 'r': 25, 'color': (100, 100, 255)},
]
print("βœ… Created 3 bouncing balls")
frame_id = 0
while True:
# Clear
surface.fill((30, 30, 50))
# Draw grid background
for x in range(0, WIDTH, 40):
pygame.draw.line(surface, (50, 50, 70), (x, 0), (x, HEIGHT), 1)
for y in range(0, HEIGHT, 40):
pygame.draw.line(surface, (50, 50, 70), (0, y), (WIDTH, y), 1)
# Update and draw balls
for ball in balls:
ball['x'] += ball['dx']
ball['y'] += ball['dy']
if ball['x'] < ball['r'] or ball['x'] > WIDTH - ball['r']:
ball['dx'] = -ball['dx']
if ball['y'] < ball['r'] or ball['y'] > HEIGHT - ball['r']:
ball['dy'] = -ball['dy']
# Draw ball
pygame.draw.circle(surface, ball['color'],
(int(ball['x']), int(ball['y'])), ball['r'])
# Draw outline
pygame.draw.circle(surface, (255, 255, 255),
(int(ball['x']), int(ball['y'])), ball['r'], 2)
# Add text
font = pygame.font.Font(None, 24)
texts = [
f"Frame: {frame_id}",
f"Balls: {len(balls)}",
time.strftime("%H:%M:%S")
]
for i, text in enumerate(texts):
text_surface = font.render(text, True, (255, 255, 255))
surface.blit(text_surface, (10, 10 + i * 25))
# === FIX 1: Convert to JPEG (smaller, browser-friendly) ===
import io
buffer = io.BytesIO()
pygame.image.save(surface, buffer, 'JPEG')
jpeg_bytes = buffer.getvalue()
# Update shared state
with frame_data["lock"]:
frame_data["jpeg_bytes"] = jpeg_bytes
frame_data["frame_id"] = frame_id
frame_id += 1
if frame_id % 30 == 0:
print(f"πŸ“Έ Frame {frame_id} ({len(jpeg_bytes)} bytes)")
# Fixed 30 FPS
time.sleep(1/30)
# Start render thread
threading.Thread(target=pygame_render, daemon=True).start()
# Wait for initialization
time.sleep(2)
print("🌐 Starting Flask...")
app.run(host='0.0.0.0', port=7860, threaded=True, use_reloader=False)