import os import shutil import certifi from flask import Flask, request, render_template, redirect, url_for, session, flash from authlib.integrations.flask_client import OAuth from flask_pymongo import PyMongo from werkzeug.security import generate_password_hash, check_password_hash from frame_extractor import FrameExtractor # --- IMPORT DETECTORS --- from video_detect import VideoDeepfakeDetector from image_detect import ImageDeepfakeDetector from audio_detect import AudioDeepfakeDetector from combined_detect import CombinedDeepfakeDetector # 👈 NEW FEATURE app = Flask(__name__) app.secret_key = 'super_secret_key_change_this_for_production' app.config['GOOGLE_CLIENT_ID'] = os.environ.get("GOOGLE_CLIENT_ID") app.config['GOOGLE_CLIENT_SECRET'] = os.environ.get("GOOGLE_CLIENT_SECRET") app.config["MONGO_URI"] =os.environ.get("MONGO_URI") app.config['SESSION_COOKIE_SECURE'] = False app.config['SESSION_COOKIE_SAMESITE'] = 'Lax' oauth = OAuth(app) mongo = PyMongo(app, tls=True, tlsAllowInvalidCertificates=True) google = oauth.register( name='google', client_id=app.config['GOOGLE_CLIENT_ID'], client_secret=app.config['GOOGLE_CLIENT_SECRET'], server_metadata_url='https://accounts.google.com/.well-known/openid-configuration', client_kwargs={'scope': 'openid email profile'}, ) UPLOAD_FOLDER = 'uploads' if os.path.exists(UPLOAD_FOLDER): shutil.rmtree(UPLOAD_FOLDER) os.makedirs(UPLOAD_FOLDER) # ============================ # ⚡ GLOBALLY LOAD AI MODELS # ============================ print("⚡ Starting Server & Pre-loading Audio Model...") audio_detector = AudioDeepfakeDetector() video_detector = None image_detector = None extractor = None def get_video_detector(): global video_detector, extractor if video_detector is None: print("⚡ Loading Video AI Model...") video_detector = VideoDeepfakeDetector() extractor = FrameExtractor() return video_detector, extractor def get_image_detector(): global image_detector if image_detector is None: print("⚡ Loading Image AI Model...") image_detector = ImageDeepfakeDetector() return image_detector # ============================ # 🔐 AUTHENTICATION ROUTES # ============================ @app.route('/login', methods=['GET', 'POST']) def login_page(): if session.get('logged_in'): return redirect(url_for('index')) if request.method == 'POST': email = request.form.get('email') password = request.form.get('password') try: user = mongo.db.users.find_one({"email": email}) except Exception as e: return f"❌ Database Connection Error: {e}" if user and check_password_hash(user['password'], password): session['logged_in'] = True session['user_name'] = user['name'] session['user_email'] = user['email'] return redirect(url_for('index')) else: flash("Invalid email or password.") return render_template('login.html') @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': name = request.form.get('name') email = request.form.get('email') password = request.form.get('password') try: existing_user = mongo.db.users.find_one({"email": email}) if existing_user: flash("Email already registered. Please login.") return redirect(url_for('login_page')) hashed_password = generate_password_hash(password) mongo.db.users.insert_one({ "name": name, "email": email, "password": hashed_password, "auth_type": "manual" }) except Exception as e: return f"❌ Database Error: {e}" flash("Account created! Please login.") return redirect(url_for('login_page')) return render_template('register.html') @app.route('/login/google') def google_login(): redirect_uri = url_for('authorize', _external=True) return google.authorize_redirect(redirect_uri) @app.route('/authorize') def authorize(): try: token = google.authorize_access_token() user_info = token.get('userinfo') existing_user = mongo.db.users.find_one({"email": user_info['email']}) if not existing_user: mongo.db.users.insert_one({ "name": user_info['name'], "email": user_info['email'], "picture": user_info['picture'], "auth_type": "google", "password": "" }) session['logged_in'] = True session['user_email'] = user_info['email'] session['user_name'] = user_info['name'] session['profile_pic'] = user_info.get('picture') return redirect(url_for('index')) except Exception as e: return f"Login failed: {e}" @app.route('/logout') def logout(): session.clear() return redirect(url_for('login_page')) # ============================ # 🏠 MAIN APP ROUTE # ============================ @app.route('/', methods=['GET', 'POST']) def index(): if not session.get('logged_in'): return redirect(url_for('login_page')) user_name = session.get('user_name', 'User') if request.method == 'POST': if 'file' not in request.files: return redirect(request.url) file = request.files['file'] mode = request.form.get('mode') if file.filename == '': return redirect(request.url) if mode == 'audio': filename = "input_audio.mp3" file_path = os.path.join(UPLOAD_FOLDER, filename) file.save(file_path) verdict, confidence = audio_detector.predict(file_path) css_class = "fake" if verdict == "DEEPFAKE DETECTED" else "real" return render_template('result.html', result=verdict, css_class=css_class, confidence=f"{confidence*100:.1f}", type="Audio Only", extra_info="
Audio Analysis Complete
") elif mode == 'image': filename = "input_image.jpg" file_path = os.path.join(UPLOAD_FOLDER, filename) file.save(file_path) detector = get_image_detector() verdict, confidence = detector.predict(file_path) css_class = "fake" if verdict == "DEEPFAKE DETECTED" else "real" return render_template('result.html', result=verdict, css_class=css_class, confidence=f"{confidence*100:.1f}", type="Image", extra_info="Image Analysis Complete
") # 👇 THE NEW COMBINED ROUTE 👇 elif mode == 'combined': filename = "input_combined.mp4" video_path = os.path.join(UPLOAD_FOLDER, filename) file.save(video_path) v_detector, v_extractor = get_video_detector() a_detector = audio_detector combined_detector = CombinedDeepfakeDetector(a_detector, v_detector, v_extractor) final_result, details = combined_detector.predict(video_path) css_class = "fake" if final_result == "DEEPFAKE DETECTED" else "real" return render_template('result.html', result=final_result, css_class=css_class, confidence="N/A", type="Video + Audio Combined", extra_info=details) else: # Video Only Mode (Frames) filename = "input_video.mp4" video_path = os.path.join(UPLOAD_FOLDER, filename) file.save(video_path) v_detector, v_extractor = get_video_detector() image_paths = v_extractor.extract(video_path) if not image_paths: return "Error: Could not extract frames." fake_votes = 0 for img_path in image_paths: result, _ = v_detector.predict(img_path) if result == "DEEPFAKE DETECTED": fake_votes += 1 final_result = "DEEPFAKE DETECTED" if fake_votes > (len(image_paths) * 0.51) else "REAL" css_class = "fake" if final_result == "DEEPFAKE DETECTED" else "real" return render_template('result.html', result=final_result, css_class=css_class, confidence="N/A", type="Video (Frames Only)", extra_info=f"Analyzed {len(image_paths)} visual frames.
") return render_template('index.html', user_name=user_name) if __name__ == '__main__': # Binds to 0.0.0.0 and port 7860 for Hugging Face Spaces app.run(host='0.0.0.0', port=7860)