Plex Transcode Monitor
Helps monitor Plex transcodes and stops the user's stream if they are either using a web browser and transcoding, or transcoding using the native Plex app.unknown
python
6 months ago
4.3 kB
163
No Index
import time import requests import logging from flask import Flask, request TAUTULLI_API_URL = "http://<ENDPOINT>:8181/api/v2" TAUTULLI_API_KEY = "<API KEY>" RETRY_WINDOW = 3600 # 1 hour MAX_RETRIES = 1 BROWSER_CLIENTS = set(["plex web", "chrome", "firefox", "edge", "safari"]) user_retry_tracker = {} # { "user_id": {"retries": int, "last_attempt": float}} app = Flask(__name__) logging.basicConfig( filename='Plex Transcode Monitor/plex_transcode_monitor.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s', ) def stop_transcoding_session(session_id, user, message): """Send a command to stop the transcoding session.""" try: response = requests.get( TAUTULLI_API_URL, params={ "apikey": TAUTULLI_API_KEY, "cmd": "terminate_session", "session_id": session_id, "message": message, }, ) response.raise_for_status() logging.info(f"Stream stopped: {session_id}, User: {user} Message: {message}") except requests.RequestException as e: logging.error(f"Error stopping stream: {e}") def should_allow_retry(user_id): """Check if the user is within the retry window and track retries.""" current_time = time.time() # Initialize and block the first attempt if user_id not in user_retry_tracker: user_retry_tracker[user_id] = {"last_attempt": current_time, "retries": 0} return False user_data = user_retry_tracker[user_id] last_attempt_time = user_data["last_attempt"] retries = user_data["retries"] # Check if we're within the retry window and within max allowed retries, # or reset retries if outside the retry window. if current_time - last_attempt_time <= RETRY_WINDOW: if retries < MAX_RETRIES: user_retry_tracker[user_id]["retries"] += 1 user_retry_tracker[user_id]["last_attempt"] = current_time return False else: return True else: user_retry_tracker[user_id] = {"last_attempt": current_time, "retries": 1} return False # Block since it's the first attempt after the retry window @app.route("/webhook", methods=["POST"]) def webhook(): """Handle Tautulli webhook.""" try: data = request.json user = data.get("user") session_id = data.get("session_id") transcode_decision = data.get("transcode_decision") platform = data.get("platform") if not user or not session_id or not transcode_decision or not platform: logging.error("Invalid data received") return "Invalid data", 400 if transcode_decision.lower() == "transcode": if platform.lower() in BROWSER_CLIENTS: message = ( "You are using a web browser to watch this video. This slows down your video stream " "and the server as it has to convert the video to a compatible format. Please download " "the native Plex application for your device and update the settings to stream videos in 'Original' " "or 'Maximum' quality. If you really need to watch in a web browser, you can retry playing this video." ) else: message = ( "You are not playing the current video in full quality. This slows down your video stream " "and the server as it has to convert the original video to a different size. Please update your " "Plex application settings to stream videos in 'Original' or 'Maximum' quality. If you really need to " "watch in lower quality than the original file, you can retry playing this video." ) if should_allow_retry(user): logging.info(f"User {user} allowed to play transcoding video after {user_retry_tracker[user]['retries']} retries.") else: stop_transcoding_session(session_id, user, message) return "OK", 200 except Exception as e: logging.error(f"Error processing webhook: {e}") return "Internal Server Error", 500 if __name__ == "__main__": app.run(host="0.0.0.0", port=2000)
Editor is loading...