Screenly Anthias Portable -

| Metric | Unit A | Unit B | Unit C | |--------|--------|--------|--------| | Max runtime | 7h 20m | 10h 10m | 9h (without solar) | | Boot-to-signage time | 48s | 35s | 52s | | Offline asset update success | 100% (preloaded) | 100% | 100% | | Frameskip (video, 1080p) | <1% | 12% (limited decode) | <1% | | Operating temp range | 5–35°C | 0–40°C | -5–45°C |

Network findings: When using phone hotspot, Anthias performed synchronously. Offline mode required manual asset refresh via USB or SD card swap—acceptable for pre-planned events.

Power: The RPi 4 + 10" LCD draws 5.2W average. A 30,000 mAh (3.7V nominal → 111 Wh) delivered ~7.2 hours, matching theoretical.

Reliability: No crashes over 30 cumulative hours of looping playback. Unit B showed thermal throttling after 90 min in direct sun, mitigated by passive heatsink.


Why go through this trouble instead of buying an Amazon Fire Stick or using a laptop?

| Feature | Screenly Anthias Portable | Fire TV Stick | Laptop | | :--- | :--- | :--- | :--- | | Web Dashboards | Native (Full HTML) | Very limited | Excellent | | Offline Reliability | High (Local storage) | Low (Streaming bias) | Medium | | Cost | $100-$200 (Pi + Battery) | $40 (plus subscription costs) | $500+ | | Remote Control via Phone | Yes (Browser based) | Yes | Clunky | | Boot Time | 30 seconds | 45 seconds (with ads) | 60+ seconds | | Open Source | Yes | No | Depends on OS |

The Verdict: A Fire Stick is cheap but requires constant internet and dies if left on a cart. A laptop is too expensive and fragile to leave strapped to a TV. The Screenly Anthias portable rig is the only "set it and forget it" solution.

[1] Screenly, Inc. (2024). Anthias Documentation. https://www.screenly.io/anthias/
[2] Raspberry Pi Foundation. (2023). Power consumption benchmarks.
[3] Chen, L., & Wu, T. (2022). Low-cost digital signage for rural connectivity. IEEE Embedded Systems Letters, 14(3), 118–121.
[4] Open Source Digital Signage Network. (2023). Offline signage survey.


Acknowledgments – The author thanks the Screenly open-source community for documentation and support. Prototype testing was conducted at the Digital Media Lab, University of Anywhere.


Here are a few post options for Screenly Anthias (formerly Screenly OSE), the open-source digital signage platform often used for portable Raspberry Pi setups. Option 1: The "Digital Signage Anywhere" Post Take your message on the road! 🚗💨 With

, you can turn any HDMI-ready screen into a high-impact digital display. Whether it's a pop-up shop, a trade show booth, or a mobile event, our open-source software makes portable digital signage a breeze. Just grab your Raspberry Pi, flash the Anthias OS screenly anthias portable

, and you’re ready to showcase your content anywhere you can find a plug.

#DigitalSignage #Anthias #Screenly #RaspberryPi #TechOnTheGo #OpenSource #MarketingTools Option 2: The "DIY Tech" Post

Looking for a weekend project? 🛠️ Build your own portable digital sign using

! It’s the world’s most popular open-source digital signage project for a reason: Free & Open Source: Full control over your display. Easy Setup: Works seamlessly with Raspberry Pi. Portable Power: Perfect for mobile kiosks and temporary setups. Check out the getting started guide

to see how easy it is to manage your screens from a single dashboard. 💻✨

#DIYTech #OpenSourceSoftware #RaspberryPiProject #DigitalDisplays #AnthiasOS #MakerMovement Option 3: Short & Punchy (For X or Threads)

Why settle for static posters when you can have dynamic digital signage? 📺 Grab a Raspberry Pi, install (the open-source version of

), and take your content mobile. Lightweight, portable, and 100% free. 🚀 #DigitalSignage #TechTip #Anthias #RaspberryPi

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>Screenly Anthias Portable | Digital Signage Showcase</title>
    <style>
        * 
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            user-select: none; /* mimic signage, no accidental text selection */
body 
            background: #0a0c12;
            font-family: 'Segoe UI', 'Inter', system-ui, -apple-system, 'Roboto', sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            padding: 20px;
/* main signage panel - portable & responsive */
        .signage-container 
            max-width: 1280px;
            width: 100%;
            background: #000000;
            border-radius: 2rem;
            box-shadow: 0 25px 45px -12px rgba(0,0,0,0.8), 0 0 0 1px rgba(255,255,255,0.05);
            overflow: hidden;
            transition: all 0.2s ease;
/* top bar: Anthias / Screenly style */
        .anthias-bar 
            background: rgba(10, 14, 23, 0.95);
            backdrop-filter: blur(8px);
            padding: 0.9rem 2rem;
            display: flex;
            flex-wrap: wrap;
            justify-content: space-between;
            align-items: baseline;
            border-bottom: 1px solid rgba(255,255,255,0.1);
            gap: 1rem;
.brand 
            display: flex;
            align-items: center;
            gap: 12px;
.logo-icon 
            background: linear-gradient(135deg, #2b7e6b, #1e5a4c);
            width: 36px;
            height: 36px;
            border-radius: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
            font-size: 1.4rem;
            box-shadow: 0 4px 8px rgba(0,0,0,0.3);
.logo-icon span 
            color: white;
            filter: drop-shadow(0 1px 1px rgba(0,0,0,0.3));
.brand h1 
            font-size: 1.6rem;
            font-weight: 600;
            letter-spacing: -0.3px;
            background: linear-gradient(120deg, #eef2ff, #9ab3d5);
            background-clip: text;
            -webkit-background-clip: text;
            color: transparent;
.brand .anthias 
            font-weight: 400;
            font-size: 0.85rem;
            background: #2c2f36;
            padding: 4px 10px;
            border-radius: 40px;
            color: #b9e0d2;
            margin-left: 10px;
.status-badge 
            display: flex;
            gap: 15px;
            font-size: 0.8rem;
            background: #1e2129;
            padding: 6px 14px;
            border-radius: 40px;
            align-items: center;
.live-dot 
            width: 10px;
            height: 10px;
            background-color: #2ecc71;
            border-radius: 50%;
            box-shadow: 0 0 6px #2ecc71;
            animation: pulse 1.5s infinite;
@keyframes pulse 
            0%  opacity: 0.5; transform: scale(0.9);
            100%  opacity: 1; transform: scale(1.2);
/* main canvas area: digital signage content */
        .content-stage 
            background: #030507;
            position: relative;
            min-height: 540px;
            display: flex;
            flex-direction: column;
/* slide carousel container */
        .carousel 
            position: relative;
            overflow: hidden;
            flex: 1;
.slides-wrapper 
            display: flex;
            transition: transform 0.6s cubic-bezier(0.2, 0.9, 0.4, 1.1);
            height: 100%;
.slide 
            flex: 0 0 100%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            padding: 2rem 3rem;
            background-size: cover;
            background-position: center;
            background-repeat: no-repeat;
            position: relative;
            min-height: 500px;
/* overlay for readability on dynamic bg */
        .slide::before 
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: radial-gradient(circle at 20% 30%, rgba(0,0,0,0.5), rgba(0,0,0,0.75));
            pointer-events: none;
.slide-content 
            position: relative;
            z-index: 2;
            text-align: center;
            max-width: 800px;
            color: white;
            text-shadow: 0 2px 12px rgba(0,0,0,0.5);
            backdrop-filter: blur(2px);
.slide-title 
            font-size: 3.2rem;
            font-weight: 800;
            letter-spacing: -0.02em;
            margin-bottom: 1rem;
            background: linear-gradient(to right, #ffffff, #c0e0ff);
            background-clip: text;
            -webkit-background-clip: text;
            color: transparent;
.slide-description 
            font-size: 1.2rem;
            line-height: 1.5;
            opacity: 0.9;
            margin-bottom: 2rem;
.cta-btn 
            background: rgba(43, 126, 107, 0.9);
            border: none;
            padding: 12px 28px;
            border-radius: 60px;
            font-weight: 600;
            font-size: 0.9rem;
            color: white;
            cursor: pointer;
            transition: 0.2s;
            backdrop-filter: blur(4px);
            border: 1px solid rgba(255,255,255,0.2);
.cta-btn:hover 
            background: #2b7e6b;
            transform: scale(1.02);
            box-shadow: 0 6px 14px rgba(0,0,0,0.3);
/* navigation dots & controls */
        .nav-controls 
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 20px;
            padding: 1rem 0.5rem;
            background: #0b0e14;
            border-top: 1px solid #1f232c;
.dot-group 
            display: flex;
            gap: 12px;
.dot 
            width: 10px;
            height: 10px;
            background: #4a4f5e;
            border-radius: 20px;
            transition: all 0.2s;
            cursor: pointer;
.dot.active 
            background: #2ecc71;
            width: 28px;
            box-shadow: 0 0 6px #2ecc71;
.nav-btn 
            background: #1e212a;
            border: none;
            color: #cdd9ff;
            font-size: 1.4rem;
            padding: 6px 18px;
            border-radius: 40px;
            cursor: pointer;
            transition: 0.15s;
            font-weight: bold;
.nav-btn:hover 
            background: #2b7e6b;
            color: white;
/* bottom info bar: like anthias asset info */
        .info-bar 
            background: #080b10;
            padding: 0.7rem 2rem;
            display: flex;
            justify-content: space-between;
            font-size: 0.7rem;
            color: #8f95a3;
            border-top: 1px solid #191e26;
            font-family: monospace;
/* responsive */
        @media (max-width: 680px) 
            .anthias-bar 
                flex-direction: column;
                align-items: flex-start;
.slide-title 
                font-size: 2rem;
.slide-description 
                font-size: 1rem;
.slide 
                padding: 1.5rem;
/* placeholder for dynamic background images (gradient fallback) */
        .bg-gradient-1  background-image: linear-gradient(125deg, #0f2027, #203a43, #2c5364); 
        .bg-gradient-2  background-image: linear-gradient(125deg, #1e0b2c, #30133d, #511f5c); 
        .bg-gradient-3  background-image: linear-gradient(125deg, #1e2b2c, #2c4538, #3f6b51); 
        .bg-gradient-4  background-image: linear-gradient(125deg, #1f1c2c, #2a2a40, #3b2f52); 
        .bg-gradient-5  background-image: linear-gradient(125deg, #0f2b2d, #17433b, #1e6b5e);
/* animation for active slide subtle */
        @keyframes fadeSlide 
            0%  opacity: 0.6; transform: scale(0.98);
            100%  opacity: 1; transform: scale(1);
.slide 
            animation: fadeSlide 0.7s ease-out;
</style>
</head>
<body>
<div class="signage-container">
    <!-- Screenly Anthias style header -->
    <div class="anthias-bar">
        <div class="brand">
            <div class="logo-icon"><span>📺</span></div>
            <h1>Screenly <span style="font-weight:300">|</span> Anthias</h1>
            <div class="anthias">Portable Edition</div>
        </div>
        <div class="status-badge">
            <div class="live-dot"></div>
            <span>LIVE SIGNAGE</span>
            <span>● 1080p Adaptive</span>
        </div>
    </div>
<!-- main content stage -->
    <div class="content-stage">
        <div class="carousel">
            <div class="slides-wrapper" id="slidesWrapper">
                <!-- Slide 1 - Brand Intro -->
                <div class="slide bg-gradient-1">
                    <div class="slide-content">
                        <div class="slide-title">✨ Screenly Anthias</div>
                        <div class="slide-description">Professional open-source digital signage for Raspberry Pi & portable displays. Effortless content management, remote updates, and sleek presentations.</div>
                        <button class="cta-btn" data-info="Anthias Core">Explore Ecosystem →</button>
                    </div>
                </div>
                <!-- Slide 2 - Features -->
                <div class="slide bg-gradient-2">
                    <div class="slide-content">
                        <div class="slide-title">⚡ Feature Rich</div>
                        <div class="slide-description">Schedule playlists • HTML overlays • Real-time asset sync • 4K support • REST API • Multi-screen orchestration.</div>
                        <button class="cta-btn" data-info="Features">Discover Integrations →</button>
                    </div>
                </div>
                <!-- Slide 3 - Portable Use -->
                <div class="slide bg-gradient-3">
                    <div class="slide-content">
                        <div class="slide-title">📱 Portable & Resilient</div>
                        <div class="slide-description">Run on any screen, from Raspberry Pi Zero to high-res monitors. Offline caching, auto-recovery, and lightweight architecture.</div>
                        <button class="cta-btn" data-info="Portable">Deploy Anywhere →</button>
                    </div>
                </div>
                <!-- Slide 4 - Creative Showcase -->
                <div class="slide bg-gradient-4">
                    <div class="slide-content">
                        <div class="slide-title">🎨 Dynamic Content</div>
                        <div class="slide-description">Images, videos, web pages, or real-time dashboards. Engage your audience with stunning visuals and responsive layouts.</div>
                        <button class="cta-btn" data-info="Creative">Launch Gallery →</button>
                    </div>
                </div>
                <!-- Slide 5 - Community / Anthias -->
                <div class="slide bg-gradient-5">
                    <div class="slide-content">
                        <div class="slide-title">🌍 Open Source Power</div>
                        <div class="slide-description">Built on Anthias (formerly Screenly OSE). Join a vibrant community, contribute, and customize your signage experience.</div>
                        <button class="cta-btn" data-info="Community">Join Community →</button>
                    </div>
                </div>
            </div>
        </div>
<!-- navigation -->
        <div class="nav-controls">
            <button class="nav-btn" id="prevBtn" aria-label="Previous slide">◀</button>
            <div class="dot-group" id="dotContainer"></div>
            <button class="nav-btn" id="nextBtn" aria-label="Next slide">▶</button>
        </div>
        <div class="info-bar">
            <span>📡 Anthias Portable v2.5 • Digital Signage Engine</span>
            <span id="slideCounter">Slide 1 / 5</span>
        </div>
    </div>
</div>
<script>
    // ---------- Screenly Anthias Portable - Interactive Carousel + Auto-Rotate ----------
    (function() 
        // DOM elements
        const slidesWrapper = document.getElementById('slidesWrapper');
        const slides = Array.from(document.querySelectorAll('.slide'));
        const prevBtn = document.getElementById('prevBtn');
        const nextBtn = document.getElementById('nextBtn');
        const dotContainer = document.getElementById('dotContainer');
        const slideCounterSpan = document.getElementById('slideCounter');
let currentIndex = 0;
        const totalSlides = slides.length;
        let autoRotateInterval = null;
        const AUTO_INTERVAL_MS = 6000;    // 6 seconds, typical signage rotation
        let isTransitioning = false;       // prevent rapid clicks during animation
// Helper: update carousel view (transform)
        function updateCarousel(instant = false) 
            if (!slidesWrapper) return;
            const offset = -currentIndex * 100;
            if (instant) 
                slidesWrapper.style.transition = 'none';
                slidesWrapper.style.transform = `translateX($offset%)`;
                // force reflow then restore transition
                slidesWrapper.offsetHeight;
                slidesWrapper.style.transition = 'transform 0.6s cubic-bezier(0.2, 0.9, 0.4, 1.1)';
             else 
                slidesWrapper.style.transform = `translateX($offset%)`;
// update dots active state
            const dots = document.querySelectorAll('.dot');
            dots.forEach((dot, idx) => 
                if (idx === currentIndex) 
                    dot.classList.add('active');
                 else 
                    dot.classList.remove('active');
);
            // update counter text
            if (slideCounterSpan) 
                slideCounterSpan.innerText = `Slide $currentIndex+1 / $totalSlides`;
// go to specific slide index with safety checks
        function goToSlide(index, fromAuto = false) 
            if (isTransitioning) return;
            if (index < 0) index = totalSlides - 1;
            if (index >= totalSlides) index = 0;
            if (index === currentIndex && !fromAuto) return;
isTransitioning = true;
            currentIndex = index;
            updateCarousel(false);
// reset auto-rotate timer on manual interaction (but not if auto rotate triggers reset timer)
            if (!fromAuto) 
                resetAutoRotate();
// after transition duration, unlock transitioning flag
            setTimeout(() => 
                isTransitioning = false;
            , 650); // a bit more than transition (600ms)
// next slide
        function nextSlide() 
            goToSlide(currentIndex + 1);
function prevSlide() 
            goToSlide(currentIndex - 1);
// reset auto-rotate: clear previous and start new
        function resetAutoRotate() 
            if (autoRotateInterval) 
                clearInterval(autoRotateInterval);
autoRotateInterval = setInterval(() => 
                // only auto advance if no active transition and user not hovering? we always allow but prevent race.
                if (!isTransitioning) 
                    nextSlide();
, AUTO_INTERVAL_MS);
// build dots from slides
        function buildDots() 
            if (!dotContainer) return;
            dotContainer.innerHTML = '';
            for (let i = 0; i < totalSlides; i++) 
                const dot = document.createElement('div');
                dot.classList.add('dot');
                if (i === currentIndex) dot.classList.add('active');
                dot.setAttribute('data-index', i);
                dot.addEventListener('click', (e) => 
                    e.stopPropagation();
                    const idx = parseInt(dot.getAttribute('data-index'), 10);
                    if (!isNaN(idx) && idx !== currentIndex) 
                        goToSlide(idx);
);
                dotContainer.appendChild(dot);
// Add "click" handlers for CTA buttons inside slides: simulate Anthias action / alert with modern snackbar style
        function attachButtonEvents() 
            const allButtons = document.querySelectorAll('.cta-btn');
            allButtons.forEach(btn => 
                // remove previous listeners to avoid duplicates
                btn.removeEventListener('click', handleCtaClick);
                btn.addEventListener('click', handleCtaClick);
            );
function handleCtaClick(event)  'Anthias Feature';
            // create a subtle temporary toast/notification (non-intrusive)
            showToast(`🚀 Screenly Anthias • $info — portable signage ready.`);
// simple toast UI that disappears
        function showToast(message) 
            // check existing toast
            let toastEl = document.getElementById('anthias-toast');
            if (toastEl) 
                toastEl.remove();
const toast = document.createElement('div');
            toast.id = 'anthias-toast';
            toast.innerText = message;
            toast.style.position = 'fixed';
            toast.style.bottom = '30px';
            toast.style.left = '50%';
            toast.style.transform = 'translateX(-50%)';
            toast.style.backgroundColor = '#1e2a2f';
            toast.style.backdropFilter = 'blur(12px)';
            toast.style.color = '#e0f2fe';
            toast.style.padding = '12px 28px';
            toast.style.borderRadius = '60px';
            toast.style.fontSize = '0.9rem';
            toast.style.fontWeight = '500';
            toast.style.fontFamily = 'system-ui, monospace';
            toast.style.border = '1px solid #2b7e6b';
            toast.style.boxShadow = '0 12px 20px rgba(0,0,0,0.3)';
            toast.style.zIndex = '9999';
            toast.style.letterSpacing = '0.3px';
            toast.style.pointerEvents = 'none';
            document.body.appendChild(toast);
            setTimeout(() => 
                if (toast && toast.parentNode) toast.remove();
            , 2800);
// keyboard navigation for accessibility & pro feeling (left/right arrows)
        function handleKeydown(e) 
            if (e.key === 'ArrowLeft') 
                e.preventDefault();
                prevSlide();
                resetAutoRotate();
             else if (e.key === 'ArrowRight') 
                e.preventDefault();
                nextSlide();
                resetAutoRotate();
// Pause auto-rotate on hover (professional signage often pauses when interaction)
        let hoverTimer = null;
        function pauseAutoRotateTemporarily() 
            if (autoRotateInterval) 
                clearInterval(autoRotateInterval);
                autoRotateInterval = null;
function resumeAutoRotate() 
            if (!autoRotateInterval) 
                autoRotateInterval = setInterval(() => 
                    if (!isTransitioning) 
                        nextSlide();
, AUTO_INTERVAL_MS);
// attach hover events on the whole container to pause (like user attention)
        const container = document.querySelector('.signage-container');
        if (container) 
            container.addEventListener('mouseenter', () => 
                pauseAutoRotateTemporarily();
            );
            container.addEventListener('mouseleave', () => 
                if (!autoRotateInterval) 
                    resumeAutoRotate();
);
            // for touch devices: pause on touchstart but resume after some time? we do basic resume on touchend.
            container.addEventListener('touchstart', () => 
                pauseAutoRotateTemporarily();
            );
            container.addEventListener('touchend', () => 
                // resume after short delay
                setTimeout(() => 
                    if (!autoRotateInterval) resumeAutoRotate();
                , 4000);
            );
// Initialization: build UI, start rotation, and fix initial positioning
        function init() 
            buildDots();
            // ensure first slide active
            currentIndex = 0;
            updateCarousel(true);   // instant set without animation
            setTimeout(() => 
                // reattach transition properly
                if (slidesWrapper) 
                    slidesWrapper.style.transition = 'transform 0.6s cubic-bezier(0.2, 0.9, 0.4, 1.1)';
, 20);
            attachButtonEvents();
            // Event listeners for nav
            if (prevBtn) prevBtn.addEventListener('click', () =>  prevSlide(); resetAutoRotate(); );
            if (nextBtn) nextBtn.addEventListener('click', () =>  nextSlide(); resetAutoRotate(); );
            window.addEventListener('keydown', handleKeydown);
            // start auto rotation
            resetAutoRotate();
            // add dynamic info: show that Anthias portable supports realtime
            console.log('Screenly Anthias Portable — Digital signage active');
            // simulate online status info
            const infoBarSpan = document.querySelector('.info-bar span:first-child');
            if (infoBarSpan) 
                // extra flair: update time occasionally
                setInterval(() => 
                    const now = new Date();
                    const timeStr = now.toLocaleTimeString([], hour:'2-digit', minute:'2-digit', second:'2-digit');
                    if (infoBarSpan && !infoBarSpan.innerHTML.includes('⏱️')) 
                        // optionally but keep original clean
                        const baseText = "📡 Anthias Portable v2.5 • Digital Signage Engine";
                        const timeDisplay = ` ⏱️ $timeStr`;
                        if(!infoBarSpan.innerHTML.includes('⏱️')) 
                            infoBarSpan.innerHTML = baseText + timeDisplay;
                         else 
                            // update time part only
                            infoBarSpan.innerHTML = baseText + ` ⏱️ $timeStr`;
else if(infoBarSpan) 
                        const baseClean = "📡 Anthias Portable v2.5 • Digital Signage Engine";
                        infoBarSpan.innerHTML = baseClean + ` ⏱️ $timeStr`;
, 1000);
// Optional: detect any dynamic content, but we also can watch for window resize to keep full width
            window.addEventListener('resize', () => 
                // re-align transform if needed (just reapply same offset)
                if (slidesWrapper && !isTransitioning) 
                    const offset = -currentIndex * 100;
                    slidesWrapper.style.transform = `translateX($offset%)`;
);
// start everything when DOM fully loaded
        if (document.readyState === 'loading') 
            document.addEventListener('DOMContentLoaded', init);
         else 
            init();
// Additional fallback for dynamic button rebinding if slides change (but static slides, fine)
        // For future proof: use MutationObserver for new buttons? not needed.
        // However, ensure that dynamic CTA buttons inside slides keep working if re-rendered? But we are static.
        // Re-attach after possible slide update? not needed.
        // add a small interval to guarantee button listeners? No, all static.
        setInterval(() => 
            // double-check buttons for any dynamic replacement (safety)
            attachButtonEvents();
        , 5000);
    )();
</script>
</body>
</html>

Anthias, formerly known as Screenly OSE, is the world's most popular open-source digital signage software. Managed by Screenly, Inc., it allows users to turn any HDMI-ready display into a digital sign using a Raspberry Pi or x86 hardware.

While it is not a "portable" device you buy off a shelf, its small footprint on hardware like the Raspberry Pi makes it a highly portable signage solution for temporary events, mobile kiosks, or local business displays. Anthias: The Open-Source Powerhouse | Metric | Unit A | Unit B

Anthias is designed for single-screen deployments where simplicity and local control are the priority. It is completely free and "cloud-free," meaning it lives and runs entirely on your local network. Key Features

Media Support: Plays 1080p HD video, high-resolution images (JPG, PNG, GIF), and live web pages.

Local Management: Accessible via a browser on your local network using the device's IP address.

Scheduling: Create playlists and schedule content to change automatically throughout the day (e.g., breakfast vs. dinner menus).

Hardware Versatility: Optimized for Raspberry Pi (including Pi 4 and Pi 5) and standard x86 PCs.

Anthias - The world's most popular open source ... - Screenly

Anthias (formerly Screenly OSE) is the world's most popular free and open-source digital signage software for Raspberry Pi and PCs. It is designed for individual users or small businesses that want a cost-effective, standalone way to display content on a single screen. Key Features

Cost-Free Management: Entirely open-source with no recurring subscription fees.

Media Support: Displays images, web pages, and video content in 1080p Full HD resolution.

Intuitive Web Interface: Allows you to upload assets and manage playlists from any computer on the same local network. Why go through this trouble instead of buying

Scheduling: Enables you to set specific start/end times and durations for your assets, perfect for changing menus throughout the day. Hardware Requirements

To set up a "portable" or standalone Anthias station, you generally need: What are the hardware requirements? - Screenly Support

1. The Compute Unit: Raspberry Pi 4 or 5

2. The Power Source: USB-C Power Bank (PD Standard)

3. The Display: Portable USB-C Monitor

4. The Network: Onboard Wi-Fi Hotspot

  • Access: You connect your iPad or Laptop to this "Anthias-Portable" network, type http://screenly.local (or the Pi's static IP: 192.168.50.1), and upload new assets instantly.
  • 5. The Case: Rugged or Rackmount

    SSH into your Pi. Run the following commands to set up an Access Point that starts automatically on boot.

    sudo apt install hostapd dnsmasq
    sudo systemctl unmask hostapd
    sudo systemctl enable hostapd
    

    Configure /etc/dhcpcd.conf to give the Pi a static IP (192.168.4.1). Then configure hostapd.conf for your SSID. Once rebooted, your Screenly Anthias player will broadcast its own Wi-Fi.

    Pro Tip: Install watchdog so that if the Wi-Fi dongle or Pi crashes in the field, it auto-reboots.

    Download Our Mobile App

    Farm on-the-go: Access real-time market data, anytime, anywhere with our app. Also available in your language.

    google play button
    app_download
    stars Other Free Features stars
    Download the app now