from flask import Flask, render_template, request, jsonify import os import json from mediascan import scan_medialib, load_config, save_config, list_media_files, filter_media_files, human_readable_size, get_media_info_with_ffprobe, media_get_from_cache, media_create_cache, media_remove_cache, get_single_media_by_path from urllib.parse import unquote from flask_socketio import SocketIO import shutil from transcodate import transcode_file app = Flask(__name__) socketio = SocketIO(app) # Load configuration CONFIG_FILE = 'config.json' config = load_config(CONFIG_FILE) GStorage = { "scaning_state": "inaction", # values: inaction, inprogress "outdated_cache": [] } transcoding_tasks = {} # ROUTING @app.route('/') def index(): return render_template('index.html') @app.route("/single") def single_media(): path = request.args.get("path", "") if not path: return "Path not provided", 400 path_to_mediafile = unquote(path) media_file = get_single_media_by_path(path_to_mediafile) return render_template('single.html', file=media_file) @app.route("/single-json") def single_media_json(): path = request.args.get("path", "") if not path: return "Path not provided", 400 path_to_mediafile = unquote(path) return jsonify(get_single_media_by_path(path_to_mediafile)) @app.route('/media-list/clear-cache') def media_list_clear_cache(): if GStorage["scaning_state"] == "inprogress": return jsonify({"status": True}) media_remove_cache(config["cache_dir"], GStorage) scan_medialib(config, GStorage, socketio) return jsonify({"status": True}) @app.route('/media-list', methods=['GET']) def media_list(): filtered_files = media_get_from_cache(config["cache_dir"]) if filtered_files == None: filtered_files = scan_medialib(config, GStorage, socketio) if GStorage["scaning_state"] == "inprogress" and not len(filtered_files): response = {"status": "scaning", "data": []}; else: response = {"status": True, "data": filtered_files} return jsonify(response) @app.route('/process-media', methods=['POST']) def process_media(): data = request.json file_path = data.get('path') codec = data.get('codec') resolution = data.get('resolution') crf = data.get('crf') preset = data.get('preset-libx') cpu_used = data.get('preset-vp9') if codec == "libaom-av1": cpu_used = data.get('preset-av1') if not file_path or not os.path.exists(file_path): return jsonify({"error": "File path is invalid or file does not exist"}), 400 # Step 1: Copy the file to the transcoded directory dest_dir = config.get('transcoded_directory', 'transcoded_files') os.makedirs(dest_dir, exist_ok=True) dest_path = os.path.join(dest_dir, os.path.basename(file_path)) socketio.emit("progress", { "task": { "file": file_path }, "message": f"Copying the original file to {dest_path}. Waiting" }) shutil.copy(file_path, dest_path) # Step 2: Start transcoding socketio.start_background_task( target=transcode_file, transcoding_tasks=transcoding_tasks, socketio=socketio, file_path=file_path, codec=codec, resolution=resolution, crf=crf, preset=preset, cpu_used=cpu_used ) return jsonify({"status": "processing started", "file": file_path}), 202 @app.route('/stop-transcoding', methods=['GET']) def stop_transcoding(): task_id = request.args.get("task_id") if task_id in transcoding_tasks: task = transcoding_tasks.pop(task_id, None) if task: task["process"].terminate() return jsonify({"status": "stopped", "task_id": task_id}) return jsonify({"status": "error", "message": "Task not found"}), 404 @app.route('/configure', methods=['GET', 'POST']) def configure(): if request.method == 'POST': directories = request.json.get('directories', []) allowed_formats = request.json.get('allowed_formats', []) config['directories'] = directories config['allowed_formats'] = allowed_formats save_config(CONFIG_FILE, config) return jsonify({"status": "success"}) return jsonify(config) if __name__ == '__main__': app.run(debug=True)