Vesion Fonctionnelle
This commit is contained in:
4
check_video_authenticity.bat
Normal file
4
check_video_authenticity.bat
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
@echo off
|
||||||
|
call .venv\Scripts\activate.bat
|
||||||
|
python "%~n0.py" %*
|
||||||
|
|
||||||
167
check_video_authenticity.py
Normal file
167
check_video_authenticity.py
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import filedialog
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.progress import Progress, SpinnerColumn, TextColumn
|
||||||
|
from rich.panel import Panel
|
||||||
|
from rich.table import Table
|
||||||
|
from rich import print
|
||||||
|
|
||||||
|
# --- CONFIGURATION ---
|
||||||
|
# TODO: Replace with your actual Sightengine API credentials
|
||||||
|
API_USER = "1020608869"
|
||||||
|
API_SECRET = "M7WF4mAXwSs2gs869LC9PecvYCBQyBSz"
|
||||||
|
|
||||||
|
API_ENDPOINT = "https://api.sightengine.com/1.0/video/check-sync.json"
|
||||||
|
|
||||||
|
console = Console()
|
||||||
|
|
||||||
|
def select_video_file():
|
||||||
|
"""Opens a file dialog to select a video file using Tkinter."""
|
||||||
|
root = tk.Tk()
|
||||||
|
root.withdraw() # Hide the main window
|
||||||
|
|
||||||
|
file_path = filedialog.askopenfilename(
|
||||||
|
title="Select a video file to analyze",
|
||||||
|
filetypes=[
|
||||||
|
("Video Files", "*.mp4 *.mov *.avi *.mkv *.webm *.flv *.wmv"),
|
||||||
|
("All Files", "*.*")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return file_path
|
||||||
|
|
||||||
|
def check_video(file_path):
|
||||||
|
"""Checks the video using Sightengine API."""
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
console.print(f"[bold red]Error:[/bold red] File not found: {file_path}")
|
||||||
|
return
|
||||||
|
|
||||||
|
params = {
|
||||||
|
'models': 'genai',
|
||||||
|
'api_user': API_USER,
|
||||||
|
'api_secret': API_SECRET
|
||||||
|
}
|
||||||
|
|
||||||
|
files = {
|
||||||
|
'media': open(file_path, 'rb')
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
with Progress(
|
||||||
|
SpinnerColumn(),
|
||||||
|
TextColumn("[progress.description]{task.description}"),
|
||||||
|
transient=True
|
||||||
|
) as progress:
|
||||||
|
progress.add_task(description="Uploading and analyzing video...", total=None)
|
||||||
|
response = requests.post(API_ENDPOINT, files=files, data=params)
|
||||||
|
|
||||||
|
response_data = json.loads(response.text)
|
||||||
|
|
||||||
|
if response_data['status'] == 'success':
|
||||||
|
display_results(file_path, response_data)
|
||||||
|
else:
|
||||||
|
error_msg = response_data.get('error', {}).get('message', 'Unknown error')
|
||||||
|
console.print(f"[bold red]API Error:[/bold red] {error_msg}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
console.print(f"[bold red]System Error:[/bold red] {e}")
|
||||||
|
finally:
|
||||||
|
files['media'].close()
|
||||||
|
|
||||||
|
def display_results(file_path, data):
|
||||||
|
"""Displays the analysis results using Rich."""
|
||||||
|
|
||||||
|
# Calculate aggregate score (average of all frames for simplicity in this demo)
|
||||||
|
frames = data.get('data', {}).get('frames', [])
|
||||||
|
if not frames:
|
||||||
|
console.print("[yellow]No frames analyzed.[/yellow]")
|
||||||
|
return
|
||||||
|
|
||||||
|
total_ai_score = 0
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
# Create detailed table for frames (showing first few or high scores)
|
||||||
|
table = Table(title="Frame Analysis (Sample)")
|
||||||
|
table.add_column("Time (s)", justify="right", style="cyan", no_wrap=True)
|
||||||
|
table.add_column("AI Probability", justify="right", style="magenta")
|
||||||
|
table.add_column("Verdict", justify="center")
|
||||||
|
|
||||||
|
max_ai_score = 0
|
||||||
|
|
||||||
|
for frame in frames:
|
||||||
|
ai_score = frame.get('type', {}).get('ai_generated', 0)
|
||||||
|
total_ai_score += ai_score
|
||||||
|
count += 1
|
||||||
|
if ai_score > max_ai_score:
|
||||||
|
max_ai_score = ai_score
|
||||||
|
|
||||||
|
# Add to table if it's a significant score or just to show some data
|
||||||
|
# Showing only frames with > 0.1 score or every 10th frame to keep it clean if many frames
|
||||||
|
if ai_score > 0.5 or count % 10 == 1:
|
||||||
|
verdict = "[red]FAKE[/red]" if ai_score > 0.8 else ("[yellow]SUSPICIOUS[/yellow]" if ai_score > 0.4 else "[green]REAL[/green]")
|
||||||
|
# Assuming 1 frame per second roughly? API documentation says 'position' is likely offset
|
||||||
|
position = frame.get('info', {}).get('position', 0)
|
||||||
|
# Provide string formatting for score
|
||||||
|
table.add_row(str(position), f"{ai_score:.2%}", verdict)
|
||||||
|
|
||||||
|
avg_ai_score = total_ai_score / count if count else 0
|
||||||
|
|
||||||
|
# Final Verdict Panel
|
||||||
|
final_verdict = "UNCERTAIN"
|
||||||
|
color = "yellow"
|
||||||
|
if max_ai_score > 0.85:
|
||||||
|
final_verdict = "AI GENERATED"
|
||||||
|
color = "red"
|
||||||
|
elif max_ai_score < 0.2:
|
||||||
|
final_verdict = "AUTHENTIC"
|
||||||
|
color = "green"
|
||||||
|
|
||||||
|
request_info = data.get('request', {})
|
||||||
|
req_id = request_info.get('id', 'N/A')
|
||||||
|
ops = request_info.get('operations', 0)
|
||||||
|
|
||||||
|
panel_content = f"""
|
||||||
|
[bold]File:[/bold] {os.path.basename(file_path)}
|
||||||
|
[bold]Request ID:[/bold] {req_id}
|
||||||
|
[bold]Operations Cost:[/bold] {ops}
|
||||||
|
|
||||||
|
[bold]Max AI Score:[/bold] {max_ai_score:.2%}
|
||||||
|
[bold]Average AI Score:[/bold] {avg_ai_score:.2%}
|
||||||
|
|
||||||
|
[bold size=20 style={color}]VERDICT: {final_verdict}[/bold size=20 style={color}]
|
||||||
|
"""
|
||||||
|
|
||||||
|
console.print(Panel(panel_content, title="Analysis Result", expand=False))
|
||||||
|
console.print(table)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if API_USER == "CHANGE_ME" or API_SECRET == "CHANGE_ME":
|
||||||
|
console.print("[bold red]Configuration Error:[/bold red] Please set API_USER and API_SECRET in the script.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
video_path = sys.argv[1]
|
||||||
|
else:
|
||||||
|
console.print(Panel(
|
||||||
|
"[bold green]AI Video Authenticity Check[/bold green]\n\n"
|
||||||
|
"This script analyzes a video to detect AI-generated content using Sightengine.\n"
|
||||||
|
"Please select a video file in the window that opens...",
|
||||||
|
title="Welcome",
|
||||||
|
border_style="green"
|
||||||
|
))
|
||||||
|
video_path = select_video_file()
|
||||||
|
if not video_path:
|
||||||
|
console.print("[yellow]No file selected. Exiting.[/yellow]")
|
||||||
|
return
|
||||||
|
|
||||||
|
console.print(f"[blue]Analyzing:[/blue] {video_path}")
|
||||||
|
check_video(video_path)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
main()
|
||||||
|
finally:
|
||||||
|
input("Press Enter to continue...")
|
||||||
Reference in New Issue
Block a user