From 8c465b9734ff3c2bcf34fa9d6990380c153727c8 Mon Sep 17 00:00:00 2001 From: ThisBirchWood Date: Mon, 3 Mar 2025 21:01:53 +0000 Subject: [PATCH 1/4] UPDATE: Changed NGINX to use an auth module --- nginx/nginx.conf | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/nginx/nginx.conf b/nginx/nginx.conf index f3d97e7..2a46181 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -87,6 +87,8 @@ http { ## Cacheable HLS files, ts location ~ ^/stream/(.+)/(.+\.ts)$ { + # Call backend to check permission + auth_request /auth_stream/$1; alias /user_data/$1/stream/$2; # Let the MPEG-TS video chunks be cacheable @@ -112,6 +114,16 @@ http { expires -1d; } + ## Auth request for HLS + location = /auth_stream/$1 { + internal; + proxy_pass http://web_server:5000/stream/$1/direct_live_status; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + location ~ ^/\?token=.*$ { proxy_pass http://frontend:5173; proxy_http_version 1.1; From 03decdcede351e36fd012f7dfc3aab1e8832bda8 Mon Sep 17 00:00:00 2001 From: ThisBirchWood Date: Mon, 3 Mar 2025 21:03:21 +0000 Subject: [PATCH 2/4] REFACTOR: made custom nginx module instead of prebuilt --- nginx/Dockerfile | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/nginx/Dockerfile b/nginx/Dockerfile index 7830c79..d4440c5 100644 --- a/nginx/Dockerfile +++ b/nginx/Dockerfile @@ -1,7 +1,36 @@ -FROM tiangolo/nginx-rtmp +FROM debian:bullseye -COPY nginx.conf /etc/nginx/nginx.conf +# Install dependencies +RUN apt update && apt install -y \ + build-essential \ + libpcre3 libpcre3-dev \ + zlib1g zlib1g-dev \ + libssl-dev \ + curl wget git + +# Define versions +ENV NGINX_VERSION=1.24.0 +ENV NGINX_RTMP_MODULE_VERSION=1.2.2 + +# Download and compile NGINX with RTMP & auth_request module +RUN wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz && \ + tar -zxvf nginx-${NGINX_VERSION}.tar.gz && \ + git clone https://github.com/arut/nginx-rtmp-module.git && \ + cd nginx-${NGINX_VERSION} && \ + ./configure --with-http_auth_request_module --add-module=../nginx-rtmp-module && \ + make -j$(nproc) && \ + make install + +# Create required directories for logs +RUN mkdir -p /var/log/nginx && \ + touch /var/log/nginx/error.log && \ + touch /var/log/nginx/access.log + +# Copy custom NGINX config +COPY nginx.conf /usr/local/nginx/conf/nginx.conf + +# Expose necessary ports EXPOSE 1935 8080 -# Start the Nginx server -CMD [ "nginx", "-g", "daemon off;" ] +# Start NGINX +CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"] \ No newline at end of file From 43f3b54e22a86cda676182285dd4672ca270edaa Mon Sep 17 00:00:00 2001 From: ThisBirchWood Date: Mon, 3 Mar 2025 21:41:50 +0000 Subject: [PATCH 3/4] PATCH: Fixed old .ts files still being present after stream end --- web_server/celery_tasks/streaming.py | 6 ------ web_server/utils/stream_utils.py | 11 +++++++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/web_server/celery_tasks/streaming.py b/web_server/celery_tasks/streaming.py index c7df437..37f276b 100644 --- a/web_server/celery_tasks/streaming.py +++ b/web_server/celery_tasks/streaming.py @@ -50,12 +50,6 @@ def combine_ts_stream(stream_path, vods_path, vod_file_name): subprocess.run(vod_command) - # Remove ts files - for ts_file in ts_files: - remove(f"{stream_path}/{ts_file}") - # Remove m3u8 file - remove(f"{stream_path}/index.m3u8") - @shared_task def convert_image_to_png(image_path, png_path): """ diff --git a/web_server/utils/stream_utils.py b/web_server/utils/stream_utils.py index 119f745..5f9537a 100644 --- a/web_server/utils/stream_utils.py +++ b/web_server/utils/stream_utils.py @@ -80,6 +80,9 @@ def end_user_stream(stream_key, user_id, username): stream_info = db.fetchone("""SELECT * FROM streams WHERE user_id = ?""", (user_id,)) + + # Remove HLS files, even if user is not streaming + remove_hls_files(path_manager.get_stream_path(username)) # If user is not streaming, just return if not stream_info: @@ -194,6 +197,14 @@ def generate_thumbnail(stream_file: str, thumbnail_file: str) -> None: except subprocess.CalledProcessError as e: print(f"No information available for {stream_file}, aborting thumbnail generation") +def remove_hls_files(stream_path: str) -> None: + """ + Removes all hls files in a stream directory + """ + for file in os.listdir(stream_path): + if file.endswith(".ts") or file.endswith(".m3u8"): + os.remove(os.path.join(stream_path, file)) + def get_stream_tags(user_id: int) -> Optional[List[str]]: """ Given a stream return tags associated with the user's stream From fc4dcd3359e9bbfcad96896319571cb689092cd9 Mon Sep 17 00:00:00 2001 From: ThisBirchWood Date: Mon, 3 Mar 2025 21:42:24 +0000 Subject: [PATCH 4/4] UPDATE: Attempting to add authentication to .ts route (WIP, not working) --- nginx/nginx.conf | 13 ++----------- web_server/blueprints/streams.py | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/nginx/nginx.conf b/nginx/nginx.conf index 2a46181..50f1068 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -88,8 +88,8 @@ http { ## Cacheable HLS files, ts location ~ ^/stream/(.+)/(.+\.ts)$ { # Call backend to check permission - auth_request /auth_stream/$1; - alias /user_data/$1/stream/$2; + auth_request http://web_server:5000/stream/$1/direct_live_status; + root /user_data/$1/stream/$2; # Let the MPEG-TS video chunks be cacheable expires max; @@ -113,15 +113,6 @@ http { # The profile pictures should not be cacheable expires -1d; } - - ## Auth request for HLS - location = /auth_stream/$1 { - internal; - proxy_pass http://web_server:5000/stream/$1/direct_live_status; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } location ~ ^/\?token=.*$ { diff --git a/web_server/blueprints/streams.py b/web_server/blueprints/streams.py index b5eb858..3696c67 100644 --- a/web_server/blueprints/streams.py +++ b/web_server/blueprints/streams.py @@ -159,6 +159,25 @@ def user_live_status(username): "user_id": user_id }) +@stream_bp.route('/user//direct_live_status') +def user_live_status_direct(username): + """ + Returns a streamer's status, if they are live or not + Returns: + { + "is_live": bool, + "user_id": int + } + """ + + user_id = get_user_id(username) + is_live = True if get_streamer_live_status(user_id)['is_live'] else False + + if is_live: + return 'ok', 200 + else: + return 'not live', 404 + # VOD Routes @stream_bp.route('/vods/')