diff options
| author | yum <yum.food.vr@gmail.com> | 2025-10-13 19:17:26 -0700 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2025-10-28 17:19:35 -0700 |
| commit | c3fa121f1a3ec74c5980bc8981e4836ca3a708f2 (patch) | |
| tree | 9a481e6d5a25ea59055724fb089ceeca43a00f42 | |
| parent | 8aca05a7e644f3d4aff6bcf636514882dd2ae934 (diff) | |
shart attack
| -rw-r--r-- | README.md | 4 | ||||
| -rw-r--r-- | etc/nginx/sites-available/yummers.dev | 170 | ||||
| -rwxr-xr-x | opt/obsproxy/server.py | 24 | ||||
| -rwxr-xr-x | push.sh | 1 |
4 files changed, 104 insertions, 95 deletions
@@ -4,11 +4,11 @@ Shitty service to proxy data from OBS into a low-latency MPEG-DASH stream VRChat 1. Configure OBS with a custom server pointing at `rtmp://<your-domain>/live` and the pre-shared key stored in `STREAM_PSK`. 2. Start the Python service (see `etc/systemd/system/obsproxy.service` for a sample unit). -3. Share `https://<your-domain>/dash/manifest.mpd` with your VRChat video player. Multiple viewers can consume the feed concurrently. +3. When the service starts it prints a session-specific manifest URL like `https://<your-domain>/dash/<session-hex>/manifest.mpd`; share that exact URL with your VRChat video player. Multiple viewers can consume the feed concurrently. Environmental knobs: - `STREAM_PSK`: required PSK for the single ingest client. - `DASH_SEGMENT_TIME` / `DASH_FRAGMENT_TIME`: tweak DASH segment/fragment durations to balance latency vs resilience. -The server seeds a fresh 128-bit session ID on every restart and writes DASH fragments under `<STREAM_DIR>/live/<session-hex>`. The public manifest route stays fixed at `/dash/manifest.mpd`. +The server seeds a fresh 128-bit session ID on every restart and writes DASH fragments under `<STREAM_DIR>/live/<session-hex>`. The manifest and segments are only exposed under `/dash/<session-hex>/`, making it infeasible to guess a live session path. diff --git a/etc/nginx/sites-available/yummers.dev b/etc/nginx/sites-available/yummers.dev index 4f34ff7..0fddcfe 100644 --- a/etc/nginx/sites-available/yummers.dev +++ b/etc/nginx/sites-available/yummers.dev @@ -1,95 +1,95 @@ server { - root /var/www/html; - - # Add index.php to the list if you are using PHP - index index.html index.htm index.nginx-debian.html; - - server_name yummers.dev www.yummers.dev; - - location / { - # First attempt to serve request as file, then - # as directory, then fall back to displaying a 404. - try_files $uri $uri/ =404; - } - - # Add WebSocket proxy for HR proxy server - location /hrproxy { - proxy_pass https://127.0.0.1:2096; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_read_timeout 300s; - proxy_send_timeout 300s; - proxy_buffering off; - } - - # OBS Proxy API endpoints - location /api/ { - proxy_pass http://127.0.0.1:5000; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - # OBS Proxy DASH manifest + segments - location /dash/ { - proxy_pass http://127.0.0.1:5000; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - - # Disable buffering/caching so DASH clients see fresh segments immediately - proxy_buffering off; - add_header Cache-Control "no-cache" always; - add_header Access-Control-Allow-Origin "*" always; - - proxy_connect_timeout 1h; - proxy_send_timeout 1h; - proxy_read_timeout 1h; - } - - # OBS Proxy health check - location /health { - proxy_pass http://127.0.0.1:5000/health; - proxy_set_header Host $host; - } - - # Add RTMP callbacks route - location /rtmp_callbacks/ { - proxy_pass http://127.0.0.1:5000; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } - - listen [::]:443 ssl ipv6only=on; # managed by Certbot - listen 443 ssl; # managed by Certbot - ssl_certificate /etc/letsencrypt/live/yummers.dev/fullchain.pem; # managed by Certbot - ssl_certificate_key /etc/letsencrypt/live/yummers.dev/privkey.pem; # managed by Certbot - include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot - ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot + root /var/www/html; + + # Add index.php to the list if you are using PHP + index index.html index.htm index.nginx-debian.html; + + server_name yummers.dev www.yummers.dev; + + location / { + # First attempt to serve request as file, then + # as directory, then fall back to displaying a 404. + try_files $uri $uri/ =404; + } + + # Add WebSocket proxy for HR proxy server + location /hrproxy { + proxy_pass https://127.0.0.1:2096; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + proxy_buffering off; + } + + # OBS Proxy API endpoints + location /api/ { + proxy_pass http://127.0.0.1:5000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # OBS Proxy DASH manifest + segments + location /dash/ { + proxy_pass http://127.0.0.1:5000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # Disable buffering/caching so DASH clients see fresh segments immediately + proxy_buffering off; + add_header Cache-Control "no-cache" always; + add_header Access-Control-Allow-Origin "*" always; + + proxy_connect_timeout 1h; + proxy_send_timeout 1h; + proxy_read_timeout 1h; + } + + # OBS Proxy health check + location /health { + proxy_pass http://127.0.0.1:5000/health; + proxy_set_header Host $host; + } + + # Add RTMP callbacks route + location /rtmp_callbacks/ { + proxy_pass http://127.0.0.1:5000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + listen [::]:443 ssl ipv6only=on; # managed by Certbot + listen 443 ssl; # managed by Certbot + ssl_certificate /etc/letsencrypt/live/yummers.dev/fullchain.pem; # managed by Certbot + ssl_certificate_key /etc/letsencrypt/live/yummers.dev/privkey.pem; # managed by Certbot + include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot } server { - if ($host = www.yummers.dev) { - return 301 https://$host$request_uri; - } # managed by Certbot + if ($host = www.yummers.dev) { + return 301 https://$host$request_uri; + } # managed by Certbot - if ($host = yummers.dev) { - return 301 https://$host$request_uri; - } # managed by Certbot + if ($host = yummers.dev) { + return 301 https://$host$request_uri; + } # managed by Certbot - listen 80; - listen [::]:80; + listen 80; + listen [::]:80; - server_name yummers.dev www.yummers.dev; - return 404; # managed by Certbot + server_name yummers.dev www.yummers.dev; + return 404; # managed by Certbot } diff --git a/opt/obsproxy/server.py b/opt/obsproxy/server.py index 8191d30..242e223 100755 --- a/opt/obsproxy/server.py +++ b/opt/obsproxy/server.py @@ -22,6 +22,7 @@ BASE_DIR = Path(os.environ.get('STREAM_DIR', '/var/www/streams')) SERVER_DOMAIN = os.environ.get('SERVER_DOMAIN', 'yummers.dev') STREAM_HEX = secrets.token_hex(16) STREAM_PATH = BASE_DIR / 'live' / STREAM_HEX +DASH_ROUTE_PREFIX = f"/dash/{STREAM_HEX}" # Setup logging logging.basicConfig( @@ -74,7 +75,7 @@ def start_ffmpeg_process(): '-map', '0:v:0?', '-map', '0:a:0?', '-c:v', 'copy', - '-c:a', 'aac', '-b:a', '192k', + '-c:a', 'copy', '-f', 'dash', '-seg_duration', str(DASH_SEGMENT_TIME), '-frag_duration', str(DASH_FRAGMENT_TIME), @@ -158,16 +159,20 @@ def cleanup_stream(): # Routes -@app.route('/dash/manifest.mpd') +@app.route(f"{DASH_ROUTE_PREFIX}/manifest.mpd") def serve_dash_manifest(): """Serve the MPEG-DASH manifest""" if not stream_active: return "Stream not found", 404 + manifest_file = STREAM_PATH / "manifest.mpd" + if not manifest_file.exists(): + return "Manifest not ready", 503 + return send_from_directory(str(STREAM_PATH), "manifest.mpd") -@app.route('/dash/<path:filename>') +@app.route(f"{DASH_ROUTE_PREFIX}/<path:filename>") def serve_dash_segments(filename): """Serve the MPEG-DASH segment files""" if not stream_active: @@ -194,8 +199,11 @@ def on_publish(): if not start_ffmpeg_process(): return "Failed to start stream", 500 - logger.info("Stream started successfully") - logger.info(f"Access stream at https://{SERVER_DOMAIN}/dash/manifest.mpd") + logger.info( + "Stream active; manifest available at https://%s%s/manifest.mpd", + SERVER_DOMAIN, + DASH_ROUTE_PREFIX + ) return "OK" @@ -229,15 +237,15 @@ def health_check(): def print_instructions(): """Print usage instructions""" obs_url = f"rtmp://{SERVER_DOMAIN}/live" - vrc_url = f"rtmp://{SERVER_DOMAIN}/live/{STREAM_HEX}" + dash_url = f"https://{SERVER_DOMAIN}{DASH_ROUTE_PREFIX}/manifest.mpd" print("\n" + "="*80) print(f"{'OBS TO VRCHAT STREAMING PROXY':^80}") print("="*80) print("\n[URLS]") - print(f" OBS: {obs_url}") - print(f" VRChat: {vrc_url}") + print(f" OBS ingest: {obs_url}") + print(f" DASH: {dash_url}") print("\n[STATUS]") print(f" Stream is {'ACTIVE' if ffmpeg_process else 'INACTIVE'}") @@ -23,6 +23,7 @@ sudo cp etc/nginx/modules-available/rtmp.conf /etc/nginx/modules-available/ sudo cp etc/nginx/sites-available/yummers.dev /etc/nginx/sites-available/ sudo ln -sf /etc/nginx/sites-available/yummers.dev /etc/nginx/sites-enabled/yummers.dev sudo cp opt/obsproxy/server.py /opt/obsproxy/ +sudo rm -rf /var/www/streams/* # Reload systemd daemon and restart obsproxy service sudo systemctl daemon-reload |
