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
    )