diff --git a/nginx/nginx.conf b/nginx/nginx.conf index a1d0c1d..1ea292d 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -11,13 +11,26 @@ rtmp { application live { live on; + # No RTMP playback + deny play all; + push rtmp://127.0.0.1:1935/hls-live; + + on_publish http://web_server:5000/publish_stream; + + } + + application hls-live { + live on; + + hls on; + hls_path /tmp/hls; + + allow publish 127.0.0.1; + deny publish all; - # HLS Configuration (optional) - hls on; # Enable HLS conversion - hls_path /tmp/hls; # Path to store HLS files (use an absolute path) hls_nested on; - hls_fragment 5s; # Duration of each HLS segment - hls_playlist_length 15s; # Length of HLS playlist (total duration) + hls_fragment 5s; + hls_playlist_length 60s; } } } @@ -26,16 +39,22 @@ http { # Enable HLS server { listen 8080; + root /var/www; - location /hls/ { - types { - application/vnd.apple.mpegurl m3u8; - video/mp2t ts; - } - add_header Access-Control-Allow-Origin *; + # The MPEG-TS video chunks are stored in /tmp/hls + location ~ ^/stream/user/(.+\.ts)$ { + alias /tmp/hls/$1; - root /tmp/; - autoindex on; + # Let the MPEG-TS video chunks be cacheable + expires max; + } + + # The M3U8 playlists location + location ~ ^/stream/user/(.+\.m3u8)$ { + alias /tmp/hls/$1; + + # The M3U8 playlists should not be cacheable + expires -1d; } location /api/ { @@ -43,12 +62,12 @@ http { proxy_pass http://web_server:5000; # flask-app is the name of the Flask container in docker-compose } - location / { - proxy_pass http://frontend:5173; # frontend is the name of the React container in docker-compose - } - location /socket.io/ { proxy_pass http://web_server:5000/socket.io/; } + + location / { + proxy_pass http://frontend:5173; # frontend is the name of the React container in docker-compose + } } } diff --git a/web_server/blueprints/streams.py b/web_server/blueprints/streams.py index e5cff8d..6ca82ed 100644 --- a/web_server/blueprints/streams.py +++ b/web_server/blueprints/streams.py @@ -1,4 +1,4 @@ -from flask import Blueprint, session, jsonify, g +from flask import Blueprint, session, jsonify, g, request, redirect from utils.stream_utils import streamer_live_status, streamer_most_recent_stream, user_stream, followed_live_streams, followed_streamers from utils.user_utils import get_user_id from blueprints.utils import login_required @@ -170,3 +170,22 @@ def stream_thumbnail_snapshot(streamer_id): will be saved as a png stream_id.streamer_id.png or similar to create a unique image """ return + +@stream_bp.route("/publish_stream", methods=["POST"]) +def publish_stream(): + """ + Authenticates stream from streamer and publishes it to the site + """ + stream_key = request.form.get("name") + + # Check if stream key is valid + db = Database() + db.create_connection() + stream = db.fetchone("SELECT username FROM users WHERE stream_key = ?", (stream_key,)) + + ## TODO: Add stream to database + + if not stream: + return "Unauthorized", 403 + + return redirect(f"/{stream['username']}")