feat: Initial commit of existing overlay files

This commit is contained in:
2025-10-31 09:39:07 +01:00
commit d8bc68c7b5
9 changed files with 486 additions and 0 deletions

15
Other overlay ideas.md Normal file
View File

@@ -0,0 +1,15 @@
The overlays are to be posted to https://gitea.ramforth.net/ramforth/Overlays
That way, the webpage on https://overlays.ramforth.net/ will be updated.
Also, the web page structure for https://overlays.ramforth.net/ needs an overhaul, and needs more style and fun. Graphics, and pictures.
Basic ideas:
* An overlay that can take RSS feeds and make a ticker style horizontal scroller for the headlines
* A What's playing on Spotify overlay
* Overlay for Youtube music "now playing"
New Suggestions:
* **Live Chat Overlay:** Display chat messages from a YouTube or Twitch stream in real-time.
* **Goals & Countdown Overlay:** Show stream goals (followers, subs, etc.) with a progress bar, or a countdown to a specific event.
* **Social Media Feed:** Display a live feed of posts from a Twitter/X hashtag or account.
* **System Monitor:** Show real-time PC stats like CPU/GPU temperature and usage.
* **Weather Overlay:** Display the current weather for a specified location.

8
README.md Normal file
View File

@@ -0,0 +1,8 @@
# Overlays
This repository serves as a collection of various overlays for streaming and other purposes.
Each subdirectory contains overlays for a specific service or project.
## Available Overlays
* **Azuracast:** Overlays for displaying "Now Playing" information from an Azuracast radio station.

51
azuracast_readme.md Normal file
View File

@@ -0,0 +1,51 @@
# Azuracast Overlays
This directory contains browser source overlays specifically designed for displaying "Now Playing" information from an Azuracast radio station.
## Important Note
The files hosted on `https://overlays.ramforth.net/azuracast/` are for **reference and demonstration purposes only**. For the latest versions, deployment instructions, and to customize these overlays for your own use, please clone the main `Overlays` Gitea repository. Users are expected to deploy these files themselves.
## Features
* **Two Overlay Variants:**
* `overlay-text-only.html`: A clean, text-only overlay showing the current song title and artist.
* `overlay-with-album-art.html`: An overlay that includes the album art for the current song.
## Usage
### OBS Studio: Browser Source Setup
To add one of the overlays to your OBS Studio scene, follow these steps:
1. **Choose an Overlay:** Decide whether you want to use the text-only overlay or the one with album art.
* **Text-only URL (Reference):** `https://overlays.ramforth.net/azuracast/overlay-text-only.html`
* **With Album Art URL (Reference):** `https://overlays.ramforth.net/azuracast/overlay-with-album-art.html`
2. **Add a Browser Source:** In OBS Studio, right-click in the "Sources" panel and select "Add" -> "Browser".
3. **Configure the Source:**
* Give the source a name (e.g., "Azuracast Overlay").
* In the "URL" field, paste the URL of the overlay you chose.
* Set the "Width" and "Height" to your desired dimensions (e.g., 400x150).
* Click "OK".
4. **Position the Overlay:** You can now resize and position the overlay within your scene as needed.
### OBS Studio: Media Source Setup
To add the radio stream itself to your OBS scene, you can use a "Media Source". This will allow you to play the radio audio directly in your stream.
1. **Add a Media Source:** In OBS Studio, right-click in the "Sources" panel and select "Add" -> "Media Source".
2. **Configure the Source:**
* Give the source a name (e.g., "Radio Stream").
* Uncheck the "Local File" box.
* In the "Input" field, paste the following URL: `https://radio.ramforth.net/listen/lo-fi/radio.mp3`
* Click "OK".
3. **Manage Audio:** You can now control the volume of the radio stream from the "Audio Mixer" panel in OBS.
## Customization
To customize the overlays, you can fork this repository and edit the HTML and CSS files directly. You can change the fonts, colors, layout, and more to match your stream's branding.

116
index.html Normal file
View File

@@ -0,0 +1,116 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ramforth Overlays (Reference)</title>
<style>
body {
font-family: sans-serif;
color: white;
background-color: #222;
margin: 0;
padding: 40px;
line-height: 1.6;
}
.container {
max-width: 800px;
margin: 0 auto;
background-color: #333;
padding: 30px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
h1 {
color: #4CAF50;
}
h2 {
color: #FFC107;
border-bottom: 1px solid #4CAF50;
padding-bottom: 5px;
margin-top: 30px;
}
a {
color: #2196F3;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
ul {
list-style-type: none;
padding: 0;
}
li {
margin-bottom: 10px;
}
.important-note {
background-color: #555;
padding: 15px;
border-left: 5px solid #FFC107;
margin-top: 20px;
}
.footer-info {
margin-top: 30px;
font-size: 0.8em;
color: #aaa;
}
</style>
</head>
<body>
<div class="container">
<h1>Ramforth Overlays (Reference)</h1>
<p>This page provides a reference and overview of various streaming overlays developed by Ramforth. The files hosted here are for demonstration and reference purposes only.</p>
<div class="important-note">
<strong>Important:</strong> For the latest versions, deployment instructions, and to customize these overlays for your own use, please clone the official Gitea repository. We do not provide hosting for convenience; users are expected to deploy these files themselves.
</div>
<h2>Repository</h2>
<p>All source code and comprehensive documentation for these overlays can be found on our Gitea instance:</p>
<p><a href="https://gitea.ramforth.net/ramforth/Overlays">https://gitea.ramforth.net/ramforth/Overlays</a></p>
<h2>Available Overlays (Reference Files)</h2>
<p>Below are links to the current reference versions of the overlays hosted on this server:</p>
<h3>Azuracast Radio Overlays</h3>
<ul>
<li><a href="/azuracast/overlay-text-only.html">Text-only Now Playing Overlay</a></li>
<li><a href="/azuracast/overlay-with-album-art.html">Now Playing Overlay with Album Art</a></li>
</ul>
<p>For detailed usage instructions and to understand how to deploy these overlays, please refer to the <a href="https://gitea.ramforth.net/ramforth/Overlays/src/branch/main/azuracast/README.md">Azuracast README.md</a> within the Gitea repository.</p>
<div class="footer-info">
<p>Current Time: <span id="current-time"></span></p>
<p>Last Gitea Update: <span id="last-gitea-update"></span></p>
</div>
</div>
<script>
// Update current time
function updateCurrentTime() {
const now = new Date();
document.getElementById('current-time').textContent = now.toLocaleString();
}
setInterval(updateCurrentTime, 1000);
updateCurrentTime();
// Fetch last Gitea update
const giteaApiUrl = 'https://gitea.ramforth.net/api/v1/repos/ramforth/Overlays/commits?limit=1';
fetch(giteaApiUrl)
.then(response => response.json())
.then(data => {
if (data && data.length > 0) {
const lastCommitDate = new Date(data[0].commit.committer.date);
document.getElementById('last-gitea-update').textContent = lastCommitDate.toLocaleString();
} else {
document.getElementById('last-gitea-update').textContent = 'N/A';
}
})
.catch(error => {
console.error('Error fetching Gitea commit info:', error);
document.getElementById('last-gitea-update').textContent = 'Error fetching data';
});
</script>
</body>
</html>

66
overlay-text-only.html Normal file
View File

@@ -0,0 +1,66 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Now Playing (Text Only)</title>
<style>
body {
font-family: sans-serif;
color: white;
background-color: rgba(0, 0, 0, 0.5);
margin: 0;
padding: 20px;
border-radius: 10px;
}
#song-info {
display: flex;
flex-direction: column;
}
#title {
font-size: 24px;
font-weight: bold;
}
#artist {
font-size: 18px;
}
#annotation {
font-size: 12px;
margin-top: 10px;
color: #ccc;
}
</style>
</head>
<body>
<div id="song-info">
<div id="title"></div>
<div id="artist"></div>
<div id="annotation">radio.ramforth.net</div>
</div>
<script>
const nowPlayingUrl = 'https://radio.ramforth.net/api/nowplaying/1';
function updateNowPlaying() {
fetch(nowPlayingUrl)
.then(response => response.json())
.then(data => {
const song = data.now_playing.song;
document.getElementById('title').textContent = song.title;
document.getElementById('artist').textContent = song.artist;
})
.catch(error => {
console.error('Error fetching Now Playing data:', error);
document.getElementById('title').textContent = 'Error';
document.getElementById('artist').textContent = 'Could not fetch data';
});
}
// Update every 5 seconds
setInterval(updateNowPlaying, 5000);
// Initial update
updateNowPlaying();
</script>
</body>
</html>

View File

@@ -0,0 +1,80 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Now Playing</title>
<style>
body {
font-family: sans-serif;
color: white;
background-color: rgba(0, 0, 0, 0.5);
margin: 0;
padding: 20px;
border-radius: 10px;
}
#now-playing {
display: flex;
align-items: center;
}
#album-art {
width: 100px;
height: 100px;
margin-right: 20px;
border-radius: 5px;
}
#song-info {
display: flex;
flex-direction: column;
}
#title {
font-size: 24px;
font-weight: bold;
}
#artist {
font-size: 18px;
}
#annotation {
font-size: 12px;
margin-top: 10px;
color: #ccc;
}
</style>
</head>
<body>
<div id="now-playing">
<img id="album-art" src="" alt="Album Art">
<div id="song-info">
<div id="title"></div>
<div id="artist"></div>
<div id="annotation">radio.ramforth.net</div>
</div>
</div>
<script>
const nowPlayingUrl = 'https://radio.ramforth.net/api/nowplaying/1';
function updateNowPlaying() {
fetch(nowPlayingUrl)
.then(response => response.json())
.then(data => {
const song = data.now_playing.song;
document.getElementById('title').textContent = song.title;
document.getElementById('artist').textContent = song.artist;
document.getElementById('album-art').src = song.art;
})
.catch(error => {
console.error('Error fetching Now Playing data:', error);
document.getElementById('title').textContent = 'Error';
document.getElementById('artist').textContent = 'Could not fetch data';
});
}
// Update every 5 seconds
setInterval(updateNowPlaying, 5000);
// Initial update
updateNowPlaying();
</script>
</body>
</html>

View File

@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>System Monitor</title>
<style>
body {
font-family: sans-serif;
color: white;
background-color: rgba(0, 0, 0, 0.5);
padding: 20px;
border-radius: 10px;
}
</style>
</head>
<body>
<h1>System Monitor</h1>
<div>
<h2>CPU Usage</h2>
<p id="cpu-usage"></p>
</div>
<div>
<h2>Memory Usage</h2>
<p id="memory-usage"></p>
</div>
<script>
function fetchStats() {
fetch('http://localhost:8000/stats')
.then(response => response.json())
.then(data => {
document.getElementById('cpu-usage').textContent = `${data.cpu_percent}%`;
document.getElementById('memory-usage').textContent = `${data.memory_percent}%`;
})
.catch(error => console.error('Error fetching system stats:', error));
}
// Fetch stats every 2 seconds
setInterval(fetchStats, 2000);
// Initial fetch
fetchStats();
</script>
</body>
</html>

View File

@@ -0,0 +1,25 @@
import psutil
import http.server
import socketserver
import json
PORT = 8000
class SystemInfoHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == '/stats':
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
stats = {
'cpu_percent': psutil.cpu_percent(interval=1),
'memory_percent': psutil.virtual_memory().percent
}
self.wfile.write(json.dumps(stats).encode('utf-8'))
else:
super().do_GET()
with socketserver.TCPServer(('', PORT), SystemInfoHandler) as httpd:
print("serving at port", PORT)
httpd.serve_forever()

View File

@@ -0,0 +1,79 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Weather Overlay</title>
<style>
body {
font-family: sans-serif;
color: white;
background-color: rgba(0, 0, 0, 0.5);
padding: 20px;
border-radius: 10px;
}
#weather-container {
display: flex;
align-items: center;
}
#weather-icon {
width: 50px;
height: 50px;
margin-right: 20px;
}
</style>
</head>
<body>
<div id="weather-container">
<img id="weather-icon" src="" alt="Weather Icon">
<div>
<h1 id="temperature"></h1>
<p id="weather-description"></p>
</div>
</div>
<script>
const latitude = 40.71;
const longitude = -74.01;
const apiUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current_weather=true`;
fetch(apiUrl)
.then(response => response.json())
.then(data => {
const temperature = data.current_weather.temperature;
const weatherCode = data.current_weather.weathercode;
document.getElementById('temperature').textContent = `${temperature}°C`;
document.getElementById('weather-description').textContent = getWeatherDescription(weatherCode);
document.getElementById('weather-icon').src = getWeatherIcon(weatherCode);
})
.catch(error => console.error('Error fetching weather data:', error));
function getWeatherDescription(code) {
// This is a simplified mapping. You can expand it for more detailed descriptions.
if (code === 0) return "Clear sky";
if (code > 0 && code < 4) return "Partly cloudy";
if (code > 44 && code < 49) return "Fog";
if (code > 50 && code < 58) return "Drizzle";
if (code > 60 && code < 68) return "Rain";
if (code > 70 && code < 78) return "Snow";
if (code > 80 && code < 83) return "Rain showers";
if (code > 94) return "Thunderstorm";
return "Cloudy";
}
function getWeatherIcon(code) {
// This is a simplified mapping. You can expand it with more icons.
if (code === 0) return "https://openweathermap.org/img/wn/01d@2x.png"; // Clear sky
if (code > 0 && code < 4) return "https://openweathermap.org/img/wn/02d@2x.png"; // Partly cloudy
if (code > 44 && code < 49) return "https://openweathermap.org/img/wn/50d@2x.png"; // Fog
if (code > 50 && code < 58) return "https://openweathermap.org/img/wn/09d@2x.png"; // Drizzle
if (code > 60 && code < 68) return "https://openweathermap.org/img/wn/10d@2x.png"; // Rain
if (code > 70 && code < 78) return "https://openweathermap.org/img/wn/13d@2x.png"; // Snow
if (code > 80 && code < 83) return "https://openweathermap.org/img/wn/09d@2x.png"; // Rain showers
if (code > 94) return "https://openweathermap.org/img/wn/11d@2x.png"; // Thunderstorm
return "https://openweathermap.org/img/wn/03d@2x.png"; // Cloudy
}
</script>
</body>
</html>