make a nice web interface for this. make it where I can see who is online, which creator. and make me see the downloaded videos on there and so on. make it usefull. and please. and please make mee add creators and manage them on that. also make it that it checks every 5 minutes each creator (3 at the time) if they are online, and if they are it should record them.

output all the code:
import os
import json
import subprocess
import sys
import time
import threading
from datetime import datetime
from glob import glob  # Imported glob to use glob patterns

from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.firefox.options import Options as FirefoxOptions
from selenium.common.exceptions import NoSuchElementException, TimeoutException
from selenium.webdriver.common.by import By

# ---------------------- Configuration Loading ---------------------- #

def load_config(config_path='config.json'):
    """Load and parse the configuration file."""
    if not os.path.exists(config_path):
        print(f"[{datetime.now()}] ERROR: Configuration file '{config_path}' not found.")
        sys.exit(1)
    with open(config_path, 'r') as f:
        return json.load(f)

# ---------------------- FFmpeg Command Builder ---------------------- #

def build_ffmpeg_command(m3u8_url, segment_duration, segment_pattern):
    """Construct the FFmpeg command based on the provided parameters."""
    return [
        'ffmpeg',
        '-i', m3u8_url,
        '-c', 'copy',
        '-f', 'segment',
        '-segment_time', str(segment_duration),
        '-reset_timestamps', '1',
        '-loglevel', 'error',  # Suppress FFmpeg logs for cleaner output
        segment_pattern
    ]

# ---------------------- Selenium WebDriver Setup ---------------------- #

def setup_webdriver(browser_type='chrome', driver_path=None):
    """Initialize and return a Selenium WebDriver."""
    if browser_type.lower() == 'chrome':
        options = ChromeOptions()
        # options.add_argument('--headless')  # Run in headless mode
        options.add_argument('--disable-gpu')
        options.add_argument('--no-sandbox')
        options.add_argument('--disable-infobars')
        options.add_argument('--disable-extensions')
        try:
            driver = webdriver.Chrome(options=options) if driver_path else webdriver.Chrome(options=options)
        except Exception as e:
            print(f"[{datetime.now()}] ERROR: Failed to initialize Chrome WebDriver. Exception: {e}")
            return None
    elif browser_type.lower() == 'firefox':
        options = FirefoxOptions()
        options.add_argument('--headless')
        try:
            driver = webdriver.Firefox(executable_path=driver_path, options=options) if driver_path else webdriver.Firefox(options=options)
        except Exception as e:
            print(f"[{datetime.now()}] ERROR: Failed to initialize Firefox WebDriver. Exception: {e}")
            return None
    else:
        print(f"[{datetime.now()}] ERROR: Unsupported browser type '{browser_type}'. Supported types: 'chrome', 'firefox'.")
        return None
    return driver

# ---------------------- Stream Recorder Class ---------------------- #

class StreamRecorder(threading.Thread):
    """Thread class to handle recording of a single stream."""

    def __init__(self, stream_config):
        threading.Thread.__init__(self)
        self.stream_config = stream_config
        self.stop_event = threading.Event()

    def run(self):
        name = self.stream_config.get('name')
        url = self.stream_config.get('url')
        segment_duration = self.stream_config.get('segment_duration_seconds', 30)
        segments_per_clip = self.stream_config.get('segments_per_clip', 5)
        output_dir = self.stream_config.get('output_dir', f"downloads/{name}")
        browser = self.stream_config.get('browser', 'chrome')
        driver_path = self.stream_config.get('driver_path', None)

        print(f"[{datetime.now()}] INFO: Starting recorder for stream '{name}'.")

        # Ensure output directories exist
        segments_dir = os.path.join(output_dir, 'segments')
        os.makedirs(segments_dir, exist_ok=True)

        # Retrieve M3U8 URL
        m3u8_url = self.get_m3u8_url(url, browser, driver_path)
        if not m3u8_url:
            print(f"[{datetime.now()}] WARN: Marking stream '{name}' as offline due to missing M3U8 URL.")
            return  # Exit the thread if m3u8_url is not found

        # Define FFmpeg segmentation pattern
        # Use forward slashes to avoid issues with FFmpeg on Windows
        segment_pattern = os.path.join(segments_dir, f"{name}_%03d.ts").replace('\\', '/')

        # Build FFmpeg command
        ffmpeg_command = build_ffmpeg_command(m3u8_url, segment_duration, segment_pattern)

        # Start FFmpeg subprocess
        try:
            ffmpeg_process = subprocess.Popen(ffmpeg_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            print(f"[{datetime.now()}] INFO: FFmpeg started for stream '{name}'.")
        except Exception as e:
            print(f"[{datetime.now()}] ERROR: Failed to start FFmpeg for stream '{name}'. Exception: {e}")
            return

        # Initialize variables for compilation
        segments_collected = []
        compiled_clip_count = 0

        while not self.stop_event.is_set():
            time.sleep(segment_duration + 5)  # Wait enough time for a segment to be recorded

            # Gather all segment files
            segment_files = sorted(glob(os.path.join(segments_dir, f"{name}_*.ts")))

            # Identify new segments
            new_segments = [seg for seg in segment_files if seg not in segments_collected]

            for seg in new_segments:
                segments_collected.append(seg)
                print(f"[{datetime.now()}] INFO: New segment recorded: {seg}")

                # Check if enough segments have been collected for compilation
                if len(segments_collected) >= segments_per_clip:
                    # Define output clip name
                    final_clip_name = datetime.now().strftime(f"{name}_%Y%m%d_%H%M%S.mp4")
                    final_clip_path = os.path.join(output_dir, final_clip_name)

                    # Create a temporary list file for FFmpeg concat
                    list_file_path = os.path.join(output_dir, f"segments_list_{compiled_clip_count}.txt")
                    try:
                        with open(list_file_path, 'w') as list_file:
                            for segment in segments_collected[:segments_per_clip]:
                                # Convert backslashes to forward slashes for FFmpeg compatibility
                                segment_relative_path = os.path.relpath(segment, start=segments_dir)
                                segment_forward_slash = segment_relative_path.replace('\\', '/')
                                list_file.write(f"file 'segments/{segment_forward_slash}'\n")
                        print(f"[{datetime.now()}] INFO: Created list file '{list_file_path}'.")
                    except Exception as e:
                        print(f"[{datetime.now()}] ERROR: Failed to create list file '{list_file_path}'. Exception: {e}")
                        continue  # Skip compilation if list file creation failed

                    # FFmpeg concat command
                    concat_command = [
                        'ffmpeg',
                        '-f', 'concat',
                        '-safe', '0',
                        '-i', list_file_path,
                        '-c', 'copy',
                        final_clip_path
                    ]

                    # Execute FFmpeg concat
                    try:
                        subprocess.run(concat_command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                        print(f"[{datetime.now()}] INFO: Compiled clip saved as '{final_clip_path}'.")
                    except subprocess.CalledProcessError as e:
                        print(f"[{datetime.now()}] ERROR: FFmpeg concat failed for stream '{name}'. Exception: {e}")
                        continue  # Skip deletion if compilation failed

                    # Clean up: Remove compiled segments
                    for segment in segments_collected[:segments_per_clip]:
                        try:
                            os.remove(segment)
                            print(f"[{datetime.now()}] INFO: Deleted segment '{segment}'.")
                        except Exception as e:
                            print(f"[{datetime.now()}] ERROR: Failed to delete segment '{segment}'. Exception: {e}")

                    # Remove the used segments from the list
                    segments_collected = segments_collected[segments_per_clip:]
                    compiled_clip_count += 1

        # Terminate FFmpeg subprocess
        try:
            ffmpeg_process.terminate()
            ffmpeg_process.wait(timeout=5)
            print(f"[{datetime.now()}] INFO: FFmpeg terminated for stream '{name}'.")
        except subprocess.TimeoutExpired:
            ffmpeg_process.kill()
            print(f"[{datetime.now()}] WARN: FFmpeg did not terminate gracefully for stream '{name}'. Killed the process.")

    def get_m3u8_url(self, stream_url, browser_type, driver_path):
        """Navigate to the stream URL, handle pop-ups, and retrieve the M3U8 URL."""
        driver = setup_webdriver(browser_type, driver_path)
        if not driver:
            print(f"[{datetime.now()}] ERROR: WebDriver setup failed for stream '{self.stream_config.get('name')}'.")
            return None

        try:
            driver.get(stream_url)
            print(f"[{datetime.now()}] INFO: Navigated to '{stream_url}'.")

            # Wait for the page to load and handle potential pop-ups
            timeout = 60  # seconds
            start_time = time.time()
            m3u8_url = None

            while time.time() - start_time < timeout:
                # Attempt to close the "I AGREE" popup if present
                try:
                    agree_button = driver.find_element(By.ID, "close_entrance_terms")
                    agree_button.click()
                    print(f"[{datetime.now()}] INFO: Clicked on 'I AGREE' popup.")
                    # Give some time after clicking the popup
                    time.sleep(2)
                except NoSuchElementException:
                    pass  # Popup not present

                # Check network requests for M3U8 URL
                for request in driver.requests:
                    if request.response:
                        url = request.url
                        if url.endswith('.m3u8'):
                            m3u8_url = url
                            print(f"[{datetime.now()}] INFO: M3U8 URL found: {m3u8_url}")
                            driver.quit()
                            return m3u8_url

                time.sleep(2)  # Wait before checking again

            # If M3U8 URL not found within timeout
            print(f"[{datetime.now()}] WARN: M3U8 URL not found for stream '{self.stream_config.get('name')}' within {timeout} seconds.")
            driver.quit()
            return None

        except Exception as e:
            print(f"[{datetime.now()}] ERROR: Exception occurred while retrieving M3U8 URL for stream '{self.stream_config.get('name')}': {e}")
            driver.quit()
            return None

# ---------------------- Main Execution ---------------------- #

def main():
    config = load_config()
    streams = config.get('streams', [])

    if not streams:
        print(f"[{datetime.now()}] ERROR: No streams found in configuration.")
        sys.exit(1)

    # Initialize and start StreamRecorder threads
    recorders = []
    for stream in streams:
        recorder = StreamRecorder(stream)
        recorder.start()
        recorders.append(recorder)
        print(f"[{datetime.now()}] INFO: Recorder thread started for stream '{stream.get('name')}'.")

    try:
        while True:
            time.sleep(1)  # Keep the main thread alive
    except KeyboardInterrupt:
        print(f"\n[{datetime.now()}] INFO: KeyboardInterrupt received. Stopping all recorders...")
        for recorder in recorders:
            recorder.stop_event.set()
        for recorder in recorders:
            recorder.join()
        print(f"[{datetime.now()}] INFO: All recorders have been stopped.")

if __name__ == "__main__":
    main()