ScryingGlass¶

Overview¶
ScryingGlass renders scene configs onto a fullscreen window using Pyglet (OpenGL). It provides native hardware acceleration and transparent video support.
Installation¶
# Pyglet is already installed (came with moderngl-window)
./python-env/bin/pip list | grep pyglet
# If not installed:
./python-env/bin/pip install pyglet
Quick Start¶
cd /home/amorgan/GitHub/ScreenSage/ScryingGlass_pyglet
# Run with test config
../python-env/bin/python3 display_engine_pyglet.py test_pyglet.json
# Or use your own config
../python-env/bin/python3 display_engine_pyglet.py ../storage/scrying_glasses/your_config.json
Configuration Format¶
Same as original ScreenSage! Configs are compatible:
{
"screen": {
"width": 1920,
"height": 1080,
"fullscreen": false,
"monitor": 0
},
"background": {
"type": "color",
"color": "#2c3e50"
},
"elements": [
{
"type": "video",
"id": "transparent_video",
"src": "/path/to/transparent.webm",
"x": 100,
"y": 100,
"width": 800,
"height": 450
},
{
"type": "image",
"id": "logo",
"src": "/path/to/image.png",
"x": 500,
"y": 500,
"width": 200,
"height": 200,
"rotation": 45,
"opacity": 0.8
},
{
"type": "text",
"id": "title",
"text": "Welcome to Pyglet!",
"x": 960,
"y": 540,
"font": "Arial",
"size": 48,
"color": "#ffffff",
"alignment": "center"
}
]
}
Supported Elements¶
Currently Implemented¶
- Video Elements
- WebM with alpha channel (native support!)
- MP4, AVI, MOV (any format FFmpeg supports)
- Automatic scaling (width/height or aspect ratio)
-
Hardware-accelerated playback
-
Image Elements
- PNG, JPG, GIF (static)
- Scaling, rotation, opacity
-
Hardware-accelerated rendering
-
Text Elements
- TTF/system fonts
- Color, size, alignment
- Hardware-accelerated text rendering
ALL Features Implemented!¶
- Background videos
- Animated GIFs
- Shape elements (tokens, areas, lines, cones)
- Fog of War (with wall shadows)
- Live config reloading
- Zoom and Pan controls
Documentation¶
- QUICK_START.md - Quick start guide and feature overview
- ZOOM_PAN_GUIDE.md - Complete zoom and pan navigation guide
Controls¶
Keyboard¶
- ESC or Q: Quit application
- R: Reload configuration
- F11: Toggle fullscreen
- C: Clear all fog
- H or HOME: Reset view (zoom and pan)
- +/-: Zoom in/out at center
Mouse¶
- Left Click/Drag: Clear fog at cursor (if fog enabled)
- Right Click/Drag: Pan the view
- Mouse Wheel: Zoom in/out at cursor
Transparent WebM Videos¶
How It Works¶
Pyglet uses FFmpeg internally via pyglet.media, which natively supports WebM alpha channels:
# Just load and play - alpha works automatically!
source = pyglet.media.load('transparent.webm')
player = Player()
player.queue(source)
player.play()
No special flags needed! If your WebM has an alpha channel, Pyglet renders it correctly.
Creating Transparent WebM¶
# Standard VP8 with alpha
ffmpeg -i input.mov -c:v libvpx -pix_fmt yuva420p -auto-alt-ref 0 \
-metadata:s:v:0 alpha_mode="1" output.webm
# VP9 with alpha (better quality)
ffmpeg -i input.mov -c:v libvpx-vp9 -pix_fmt yuva420p \
-metadata:s:v:0 alpha_mode="1" output.webm
Testing Alpha Support¶
# Check if video has alpha
ffprobe -v error -show_entries stream=pix_fmt output.webm
# Should show: pix_fmt=yuva420p
Performance¶
Pyglet offloads everything to the GPU — transparent 1080p video runs at 60 FPS with ~10% CPU usage.
Architecture¶
Pyglet Window (OpenGL)
Video (pyglet.media)
• FFmpeg decode
• OpenGL texture (GPU)
• Alpha blending (GPU)
Images (pyglet.sprite)
• Batched rendering
• GPU transform/rotate
Text (pyglet.text)
• Font rendering (GPU)
• Batched with images
Everything rendered on GPU!
No CPU↔GPU transfers
Current Limitations¶
- No video rotation: Pyglet doesn't support video texture rotation (would need shaders)
- Coordinate origin: Bottom-left — Y increases upward
Extending This Implementation¶
Adding New Element Types¶
def load_shape_element(self, element_id, element):
"""Add a custom shape (circle, rectangle, etc.)"""
x, y = element['x'], element['y']
radius = element.get('radius', 50)
color = self.parse_color(element.get('color', '#ff0000'))
# Use pyglet.shapes (simple shapes) or custom OpenGL drawing
circle = pyglet.shapes.Circle(x, y, radius, color=color, batch=self.batch)
self.sprites[element_id] = circle
Adding Live Reload¶
# Use watchdog (already in project)
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class ConfigHandler(FileSystemEventHandler):
def on_modified(self, event):
if event.src_path == self.config_path:
self.load_config()
self.load_elements()
Troubleshooting¶
"No video formats found"¶
"ImportError: pyglet"¶
Videos don't show transparency¶
- Check video format:
ffprobe -show_streams video.webm - Verify
pix_fmt=yuva420p(with alpha) - Check
alpha_mode="1"in metadata - Try recreating with FFmpeg command above
Performance still slow¶
- Check if using hardware acceleration:
- Look for "Renderer: Intel/AMD/NVIDIA" in console
- If "software rasterizer", GPU drivers not installed
- Try disabling MSAA: Remove
samples=4from window config -
Check video resolution - 4K videos may struggle on older GPUs
-
[ ] Gamepad/controller support
License¶
Same as ScreenSage main project.
Credits¶
- Pyglet: OpenGL-based multimedia library
- FFmpeg: Video codec library (used by Pyglet)
This is the clean, simple solution to transparent videos!