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 diff --git a/nginx/nginx.conf b/nginx/nginx.conf index f3d97e7..50f1068 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -87,7 +87,9 @@ http { ## Cacheable HLS files, ts location ~ ^/stream/(.+)/(.+\.ts)$ { - alias /user_data/$1/stream/$2; + # Call backend to check permission + 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; @@ -111,6 +113,7 @@ http { # The profile pictures should not be cacheable expires -1d; } + location ~ ^/\?token=.*$ { proxy_pass http://frontend:5173; 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/') 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