[READ-ONLY] Mirror of https://github.com/aaronateataco/SonicBridge. proxy for web radios sonicradio.vercel.app
0

Configure Feed

Select the types of activity you want to include in your feed.

Create app.py

authored by

Aaronateataco and committed by
GitHub
(Jul 15, 2026, 4:56 PM UTC) 3e9f24e6 475a27e6

+72
+72
app.py
··· 1 + import asyncio 2 + import os 3 + from fastapi import FastAPI, HTTPException 4 + from fastapi.responses import StreamingResponse, HTMLResponse 5 + from fastapi.middleware.cors import CORSMiddleware 6 + 7 + app = FastAPI() 8 + 9 + # Enable CORS so other apps/websites can access your streams if needed 10 + app.add_middleware( 11 + CORSMiddleware, 12 + allow_origins=["*"], 13 + allow_credentials=True, 14 + allow_methods=["*"], 15 + allow_headers=["*"], 16 + ) 17 + 18 + # Active BBC Radio station slugs for global Akamai streams 19 + STATIONS = { 20 + "radio1": {"name": "BBC Radio 1", "slug": "bbc_radio_one"}, 21 + "radio1xtra": {"name": "BBC Radio 1Xtra", "slug": "bbc_1xtra"}, 22 + "radio2": {"name": "BBC Radio 2", "slug": "bbc_radio_two"}, 23 + "radio3": {"name": "BBC Radio 3", "slug": "bbc_radio_three"}, 24 + "radio4": {"name": "BBC Radio 4", "slug": "bbc_radio_fourfm"}, 25 + "radio4extra": {"name": "BBC Radio 4 Extra", "slug": "bbc_radio_four_extra"}, 26 + "radio5": {"name": "BBC Radio 5 Live", "slug": "bbc_radio_five_live"}, 27 + "6music": {"name": "BBC Radio 6 Music", "slug": "bbc_6music"} 28 + } 29 + 30 + @app.get("/", response_class=HTMLResponse) 31 + async def root(): 32 + return "<h1>📻 BBC Radio FLAC Proxy Online</h1><p>Append /radio1.flac to the URL to stream.</p>" 33 + 34 + @app.get("/{station_token}.flac") 35 + async def stream_radio(station_token: str): 36 + token = station_token.lower() 37 + if token not in STATIONS: 38 + raise HTTPException(status_code=404, detail=f"Station '{station_token}' not found") 39 + 40 + slug = STATIONS[token]["slug"] 41 + 42 + # Live Akamai high-quality streams 43 + hls_url = f"http://as-hls-ww-live.akamaized.net/pool_904/live/ww/{slug}/{slug}.isml/{slug}-audio=96000.norewind.m3u8" 44 + 45 + # ffmpeg command to convert incoming stream directly into FLAC on the fly 46 + cmd = ['ffmpeg', '-i', hls_url, '-c:a', 'flac', '-f', 'flac', 'pipe:1'] 47 + 48 + async def generate_chunks(): 49 + process = await asyncio.create_subprocess_exec( 50 + *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.DEVNULL 51 + ) 52 + try: 53 + while True: 54 + chunk = await process.stdout.read(4096) 55 + if not chunk: 56 + break 57 + yield chunk 58 + await asyncio.sleep(0) # keeps the event loop non-blocking 59 + except Exception: 60 + pass 61 + finally: 62 + try: 63 + process.terminate() 64 + await process.wait() 65 + except: 66 + pass 67 + 68 + return StreamingResponse( 69 + generate_chunks(), 70 + media_type="audio/flac", 71 + headers={"Cache-Control": "no-cache", "Connection": "keep-alive"} 72 + )