Spaces:
Sleeping
Sleeping
File size: 3,863 Bytes
54b22e0 e98caa2 54b22e0 0f9e483 e98caa2 54b22e0 e98caa2 54b22e0 e98caa2 54b22e0 e98caa2 54b22e0 e98caa2 54b22e0 e98caa2 54b22e0 e98caa2 54b22e0 e98caa2 0f9e483 e98caa2 54b22e0 0f9e483 e98caa2 54b22e0 e98caa2 0f9e483 e98caa2 0f9e483 54b22e0 e98caa2 0f9e483 e98caa2 54b22e0 e98caa2 0f9e483 54b22e0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | import pygame
import time
import threading
import os
from flask import Flask, Response, render_template_string
from io import BytesIO
from PIL import Image
os.environ['SDL_VIDEODRIVER'] = 'dummy'
pygame.init()
WIDTH, HEIGHT = 400, 300
shared = {
"frame_count": 0,
"streaming": True,
"last_filename": None
}
def moving_circle_loop():
screen = pygame.Surface((WIDTH, HEIGHT))
circle_x, circle_y = WIDTH//2, HEIGHT//2
speed_x, speed_y = 5, 4
while shared["streaming"]:
start_time = time.time()
# Move circle
circle_x += speed_x
circle_y += speed_y
if circle_x < 30 or circle_x > WIDTH-30: speed_x *= -1
if circle_y < 30 or circle_y > HEIGHT-30: speed_y *= -1
# Draw
screen.fill((25, 25, 45))
pygame.draw.circle(screen, (255, 80, 80), (int(circle_x), int(circle_y)), 20)
# Create unique filename
shared["frame_count"] += 1
filename = f"frame_{shared['frame_count'] % 100:02d}.jpg"
# Save to file
frame_str = pygame.image.tostring(screen, 'RGB')
img = Image.frombytes('RGB', (WIDTH, HEIGHT), frame_str)
img.save(filename, quality=90, optimize=True)
# Clean old file
if shared["last_filename"] and os.path.exists(shared["last_filename"]):
os.remove(shared["last_filename"])
shared["last_filename"] = filename
# Console log
if shared["frame_count"] % 10 == 0:
print(f"Frame {shared['frame_count']}: {filename} | Pos: ({int(circle_x)},{int(circle_y)})")
# Control FPS
elapsed = time.time() - start_time
if elapsed < 1.0/20:
time.sleep(1.0/20 - elapsed)
app = Flask(__name__)
HTML = '''<html>
<head>
<style>
body { background:#0f172a; color:white; text-align:center; padding:20px; }
#streamImg { border:3px solid #60a5fa; width:400px; height:300px; }
</style>
</head>
<body>
<h1>🌀 Moving Circle</h1>
<img id="streamImg" src="">
<p>Frame: <span id="count">0</span></p>
<script>
function updateStream() {
const img = document.getElementById('streamImg');
fetch('/current_frame')
.then(r => r.json())
.then(data => {
if (data.filename) {
const freshUrl = `/${data.filename}?t=${Date.now()}`;
img.src = freshUrl;
document.getElementById('count').textContent = data.frame_count;
}
});
}
// Poll every 50ms (20 FPS)
setInterval(updateStream, 50);
updateStream();
</script>
</body>
</html>'''
@app.route('/')
def index():
return render_template_string(HTML)
@app.route('/current_frame')
def current_frame():
return {
'frame_count': shared['frame_count'],
'filename': shared.get('last_filename')
}
@app.route('/<filename>')
def serve_frame(filename):
if os.path.exists(filename):
with open(filename, 'rb') as f:
frame_bytes = f.read()
return Response(
frame_bytes,
mimetype='image/jpeg',
headers={
'Cache-Control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache',
'Expires': '0'
}
)
# No fallback - just 404
return Response(status=404)
if __name__ == "__main__":
# Start animation thread
thread = threading.Thread(target=moving_circle_loop, daemon=True)
thread.start()
# Start server
app.run(
host='0.0.0.0',
port=int(os.environ.get('PORT', 7860)),
debug=False,
threaded=True
) |