Skip to content

Add screenshot API endpoint with video frame capture#2668

Open
Alex1981-tech wants to merge 2 commits intoScreenly:masterfrom
Alex1981-tech:feature/screenshot-endpoint
Open

Add screenshot API endpoint with video frame capture#2668
Alex1981-tech wants to merge 2 commits intoScreenly:masterfrom
Alex1981-tech:feature/screenshot-endpoint

Conversation

@Alex1981-tech
Copy link

Summary

Add GET /api/v2/screenshot endpoint that captures what is currently displayed on the screen.

Problem

On Raspberry Pi 4, VLC uses a hardware video overlay that bypasses the Linux framebuffer (/dev/fb0). This means the existing framebuffer-based screenshot approach returns a black image whenever a video asset is playing.

Solution

The new ScreenshotViewV2 endpoint:

  1. Checks viewlog.db for the currently playing asset (written by the viewer on every asset start)
  2. If video is playing: extracts the current frame using ffmpeg -ss <elapsed> -i <file> -frames:v 1 (scaled to 640px width, JPEG quality 60, ~15KB output)
  3. If image/web page: falls back to framebuffer capture (/dev/fb0) as before
  4. 5-second cache prevents excessive captures from rapid requests

API

GET /api/v2/screenshot
Response: image/jpeg (binary)

Dependencies

  • ffmpeg (already available in the server container)
  • viewlog.db in /data/.screenly/ (shared between viewer and server containers via bind mount)

Testing

Tested on Raspberry Pi 4 Model B (8GB) with:

  • Video assets (MP4) — correctly captures current frame via ffmpeg
  • Image assets — correctly captures framebuffer
  • Web page assets — correctly captures framebuffer
  • Cache behavior — second request within 5s returns cached response

Add GET /api/v2/screenshot endpoint that captures what is currently
displayed on the screen. For video assets, VLC on Raspberry Pi uses
a hardware overlay that bypasses the Linux framebuffer, resulting in
black screenshots. This endpoint detects video playback via viewlog.db
and extracts the current frame using ffmpeg. For images and web pages,
it falls back to reading /dev/fb0.

Features:
- Auto-detect video playback from viewlog.db
- Extract video frame via ffmpeg at current elapsed time
- Framebuffer capture (/dev/fb0) fallback for non-video content
- 5-second response cache to prevent excessive captures
- Returns JPEG image (640px width, quality 60)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Alex1981-tech Alex1981-tech requested a review from a team as a code owner February 15, 2026 07:41
except Exception as e:
logging.error(f'Screenshot error: {e}')
return Response(
{'error': str(e)},

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.
@nicomiguelino
Copy link
Contributor

@Alex1981-tech, thank you for opening a pull request. I will test the changes when I get the chance.
In the meantime, please continue testing and fixing failures in checks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Alex1981-tech
Copy link
Author

CI fix update:

  • Python Linter — fixed: applied ruff format to api/views/v2.py
  • ⚠️ Python Tests — the failing test test_add_asset_url (tests/test_app.py:116) is a pre-existing Selenium integration test unrelated to this PR. It tests the web UI form for adding URL assets, while this PR only adds a new GET /api/v2/screenshot endpoint. The test fails intermittently due to browser timing (sleep(3) waits) — it failed in all 5 retry attempts.

This PR changes only api/views/v2.py and api/urls/v2.py — no models, no UI, no asset creation logic.

@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants