aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md7
-rw-r--r--kpop.radio (renamed from links.radio)0
-rw-r--r--yt_radio.py11
3 files changed, 18 insertions, 0 deletions
diff --git a/README.md b/README.md
index aa3ed80..ed97d00 100644
--- a/README.md
+++ b/README.md
@@ -15,3 +15,10 @@ uv run gunicorn yt_radio:app --bind 0.0.0.0:8000 -k gthread --threads 50 --worke
## Example Landing Page
<img width="936" height="992" alt="image" src="https://github.com/user-attachments/assets/e70879ad-bdff-46b0-8018-130211d950a1" />
+
+## Local Playlist
+In case when fetching from YouTube takes too long for some reason, you can also specify a local `.radio` file. An example file has been included in this repo.
+
+The radio code will parse links from this file as the playlist instead. Set `PLAYLIST_URL="PATH_TO_.RADIO_FILE"`
+
+The file must end with `.radio`
diff --git a/links.radio b/kpop.radio
index 91f61a0..91f61a0 100644
--- a/links.radio
+++ b/kpop.radio
diff --git a/yt_radio.py b/yt_radio.py
index 5740d3f..234e84b 100644
--- a/yt_radio.py
+++ b/yt_radio.py
@@ -44,6 +44,7 @@ SUBSCRIBERS = {} # sid -> Queue[bytes]
SUBSCRIBERS_LOCK = threading.Lock()
RADIO_THREAD = None
RADIO_STOP = threading.Event()
+SUBSCRIBER_EVENT = threading.Event()
CHUNK_SIZE = 8192
QUEUE_MAX_CHUNKS = 256
@@ -271,6 +272,7 @@ def add_subscriber():
sid = uuid.uuid4().hex
with SUBSCRIBERS_LOCK:
SUBSCRIBERS[sid] = q
+ SUBSCRIBER_EVENT.set()
logger.info("Subscriber added sid=%s (total=%d)", sid, len(SUBSCRIBERS))
return sid, q
@@ -280,6 +282,8 @@ def remove_subscriber(sid):
if sid in SUBSCRIBERS:
SUBSCRIBERS.pop(sid, None)
logger.info("Subscriber removed sid=%s (total=%d)", sid, len(SUBSCRIBERS))
+ if not SUBSCRIBERS:
+ SUBSCRIBER_EVENT.clear()
def broadcast_chunk(chunk: bytes):
@@ -300,6 +304,9 @@ def broadcast_chunk(chunk: bytes):
def _radio_loop():
played = []
while not RADIO_STOP.is_set():
+ if not SUBSCRIBER_EVENT.wait(timeout=1):
+ continue
+
if not PLAYLIST:
logger.error("Playlist is empty, cannot stream")
time.sleep(1)
@@ -316,6 +323,10 @@ def _radio_loop():
for chunk in _stream_track(index):
if RADIO_STOP.is_set():
break
+ with SUBSCRIBERS_LOCK:
+ if not SUBSCRIBERS:
+ logger.info("No subscribers remaining; stopping track early")
+ break
broadcast_chunk(chunk)
except Exception:
logger.exception("Error in radio producer, skipping track")
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage