Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| # static_noise_fixed.py - Flask generates random noise | |
| import numpy as np | |
| import time | |
| from flask import Flask, Response | |
| app = Flask(__name__) | |
| WIDTH, HEIGHT = 400, 300 | |
| frame_count = 0 | |
| def index(): | |
| return '''<!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Static Noise Animation</title> | |
| <style> | |
| body { margin: 0; padding: 20px; background: #111; color: white; font-family: monospace; text-align: center; } | |
| canvas { border: 3px solid #0af; background: black; display: block; margin: 20px auto; } | |
| .stats { background: #222; padding: 15px; border-radius: 8px; display: inline-block; margin: 10px; } | |
| button { background: #0af; color: white; border: none; padding: 10px 20px; margin: 5px; border-radius: 5px; cursor: pointer; } | |
| </style> | |
| </head> | |
| <body> | |
| <h1 style="color: #0af;">πΊ Static Noise Animation</h1> | |
| <canvas id="canvas" width="400" height="300"></canvas> | |
| <div class="stats"> | |
| <div>Frames: <span id="frameCount">0</span></div> | |
| <div>FPS: <span id="fps">0</span></div> | |
| <div>Status: <span id="status" style="color: #0af;">Loading...</span></div> | |
| </div> | |
| <div> | |
| <button onclick="startNoise()">Start Noise</button> | |
| <button onclick="stopNoise()">Stop Noise</button> | |
| <button onclick="changeColor()">Change Color</button> | |
| </div> | |
| <script> | |
| const canvas = document.getElementById('canvas'); | |
| const ctx = canvas.getContext('2d'); | |
| let noiseInterval = null; | |
| let frames = 0; | |
| let lastTime = Date.now(); | |
| let fps = 0; | |
| let colorMode = 0; | |
| function loadNoiseFrame() { | |
| const startTime = Date.now(); | |
| fetch('/noise') | |
| .then(response => { | |
| if (!response.ok) throw new Error('HTTP ' + response.status); | |
| return response.arrayBuffer(); | |
| }) | |
| .then(buffer => { | |
| const imageData = new ImageData(400, 300); | |
| const rgba = imageData.data; | |
| const rgb = new Uint8Array(buffer); | |
| if (rgb.length !== 400*300*3) { | |
| console.error('Wrong size:', rgb.length); | |
| return; | |
| } | |
| for (let i = 0, j = 0; i < rgba.length; i += 4, j += 3) { | |
| rgba[i] = rgb[j]; | |
| rgba[i + 1] = rgb[j + 1]; | |
| rgba[i + 2] = rgb[j + 2]; | |
| rgba[i + 3] = 255; | |
| } | |
| if (colorMode === 2) { | |
| for (let i = 0; i < rgba.length; i += 4) { | |
| const r = rgba[i]; | |
| const g = rgba[i + 1]; | |
| const b = rgba[i + 2]; | |
| rgba[i] = Math.min(255, (r * 0.393) + (g * 0.769) + (b * 0.189)); | |
| rgba[i + 1] = Math.min(255, (r * 0.349) + (g * 0.686) + (b * 0.168)); | |
| rgba[i + 2] = Math.min(255, (r * 0.272) + (g * 0.534) + (b * 0.131)); | |
| } | |
| } | |
| ctx.putImageData(imageData, 0, 0); | |
| frames++; | |
| const now = Date.now(); | |
| if (now - lastTime >= 1000) { | |
| fps = frames; | |
| frames = 0; | |
| lastTime = now; | |
| document.getElementById('fps').textContent = fps; | |
| } | |
| document.getElementById('frameCount').textContent = parseInt(document.getElementById('frameCount').textContent) + 1; | |
| document.getElementById('status').textContent = 'Streaming β'; | |
| }) | |
| .catch(error => { | |
| console.error('Error:', error); | |
| document.getElementById('status').textContent = 'Error: ' + error.message; | |
| document.getElementById('status').style.color = 'red'; | |
| }); | |
| } | |
| function startNoise() { | |
| if (!noiseInterval) { | |
| noiseInterval = setInterval(loadNoiseFrame, 33); | |
| document.getElementById('status').textContent = 'Noise started β'; | |
| console.log('Noise animation started'); | |
| } | |
| } | |
| function stopNoise() { | |
| if (noiseInterval) { | |
| clearInterval(noiseInterval); | |
| noiseInterval = null; | |
| document.getElementById('status').textContent = 'Stopped'; | |
| console.log('Noise animation stopped'); | |
| } | |
| } | |
| function changeColor() { | |
| colorMode = (colorMode + 1) % 3; | |
| const modes = ['Grayscale', 'Color', 'Sepia']; | |
| console.log('Color mode:', modes[colorMode]); | |
| document.getElementById('status').textContent = 'Mode: ' + modes[colorMode]; | |
| } | |
| setTimeout(startNoise, 1000); | |
| console.log('Static noise page loaded'); | |
| </script> | |
| </body> | |
| </html>''' | |
| def get_noise(): | |
| """Generate random static noise""" | |
| global frame_count | |
| # Create random noise | |
| if frame_count % 3 == 0: | |
| noise = np.random.randint(0, 256, (HEIGHT, WIDTH, 3), dtype=np.uint8) | |
| gray = np.random.randint(0, 256, (HEIGHT, WIDTH, 1), dtype=np.uint8) | |
| noise[:, :, :] = gray | |
| elif frame_count % 3 == 1: | |
| noise = np.random.randint(0, 256, (HEIGHT, WIDTH, 3), dtype=np.uint8) | |
| else: | |
| noise = np.random.randint(0, 256, (HEIGHT, WIDTH, 3), dtype=np.uint8) | |
| noise[::4, :, :] = noise[::4, :, :] // 2 | |
| # Occasionally add a "glitch" | |
| if np.random.random() < 0.02: | |
| glitch_color = np.random.randint(0, 256, 3) | |
| glitch_height = np.random.randint(20, 100) | |
| glitch_y = np.random.randint(0, HEIGHT - glitch_height) | |
| noise[glitch_y:glitch_y + glitch_height, :, :] = glitch_color | |
| # Convert to bytes | |
| raw_bytes = noise.tobytes() | |
| frame_count += 1 | |
| if frame_count % 30 == 0: | |
| print(f"π‘ Generated noise frame {frame_count}") | |
| return Response( | |
| raw_bytes, | |
| mimetype='application/octet-stream', | |
| headers={ | |
| 'Cache-Control': 'no-cache, no-store, must-revalidate', | |
| 'Pragma': 'no-cache', | |
| 'Expires': '0', | |
| 'X-Frame-Count': str(frame_count) | |
| } | |
| ) | |
| def test(): | |
| """Test endpoint - returns simple pattern""" | |
| pixels = np.zeros((HEIGHT, WIDTH, 3), dtype=np.uint8) | |
| pixels[:HEIGHT//2, :, 0] = 255 | |
| pixels[HEIGHT//2:, :, 1] = 255 | |
| for i in range(min(WIDTH, HEIGHT)): | |
| if i < HEIGHT and i < WIDTH: | |
| pixels[i, i, 2] = 255 | |
| return Response( | |
| pixels.tobytes(), | |
| mimetype='application/octet-stream', | |
| headers={'Cache-Control': 'no-cache'} | |
| ) | |
| if __name__ == "__main__": | |
| print("="*60) | |
| print("πΊ STATIC NOISE ANIMATION SERVER") | |
| print("="*60) | |
| print(f"π‘ Port: 7860") | |
| print(f"π¨ Resolution: {WIDTH}x{HEIGHT}") | |
| print(f"π Data per frame: {WIDTH * HEIGHT * 3} bytes") | |
| print("="*60) | |
| app.run(host='0.0.0.0', port=7860, debug=False, threaded=True) |