szili2011 commited on
Commit
0c6346c
·
verified ·
1 Parent(s): b2c607c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +24 -29
app.py CHANGED
@@ -8,46 +8,42 @@ import os
8
  import logging
9
  from datetime import datetime
10
 
11
- # --- Configuration ---
12
- # These paths are relative to the root of your Hugging Face Space repo
13
- MODEL_PATH = 'model/model.h5'
14
- OUTPUT_DIR = 'output/'
15
- os.makedirs(OUTPUT_DIR, exist_ok=True) # Create output dir if it doesn't exist
16
-
17
- # --- Setup Logging ---
18
- # This will help you debug issues in the Hugging Face logs
19
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
20
 
21
  # --- Load Model ---
22
  if not os.path.exists(MODEL_PATH):
23
- error_msg = f"Model file not found at {MODEL_PATH}. Make sure you have uploaded your 'model.h5' to a 'model' directory in your Space."
24
  logging.error(error_msg)
25
  raise FileNotFoundError(error_msg)
26
 
27
  model = tf.keras.models.load_model(MODEL_PATH)
28
  logging.info("AI model loaded successfully.")
29
 
30
- # We need to know which index corresponds to 'jumpscare'.
31
- # Based on your training code, LabelBinarizer sorts alphabetically.
32
- # "jumpscare" comes before "normal", so it's likely index 0.
33
- # If it's the other way, change this to 1.
34
  JUMPSCARE_CLASS_INDEX = 0
35
- logging.info(f"Assuming 'jumpscare' is class index {JUMPSCARE_CLASS_INDEX}. If predictions are wrong, change this value.")
36
 
37
 
38
  def predict_frame_is_jumpscare(frame, threshold):
39
  """Analyzes a single video frame and predicts if it's a jumpscare."""
40
- # Preprocess the frame for the model
41
  rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
42
  resized_frame = cv2.resize(rgb_frame, (128, 128))
43
  img_array = np.array(resized_frame) / 255.0
44
  img_array = np.expand_dims(img_array, axis=0)
45
 
46
- # Make a prediction. This will return a list of probabilities, e.g., [[0.9, 0.1]]
47
  prediction = model.predict(img_array, verbose=0)
48
 
49
- #_CRITICAL_FIX_HERE_
50
- # Instead of checking prediction[0][0], we get the probability for the specific "jumpscare" class.
51
  jumpscare_probability = prediction[0][JUMPSCARE_CLASS_INDEX]
52
 
53
  return jumpscare_probability > threshold
@@ -59,8 +55,8 @@ def generate_jumpscare_compilation(video_path, sensitivity, progress=gr.Progress
59
  # --- Initialization ---
60
  threshold = sensitivity / 100.0
61
  analysis_fps = 10
62
- pre_scare_buffer = 1.0 # seconds to include before the scare
63
- post_scare_buffer = 1.5 # seconds to include after the scare
64
 
65
  logging.info(f"Starting analysis for video: {os.path.basename(video_path)}")
66
  logging.info(f"Settings: Sensitivity={sensitivity}, Threshold={threshold}")
@@ -78,35 +74,34 @@ def generate_jumpscare_compilation(video_path, sensitivity, progress=gr.Progress
78
 
79
  if predict_frame_is_jumpscare(frame, threshold):
80
  jumpscare_times.append(current_time)
81
- logging.info(f"Jumpscare detected at timestamp: {current_time:.2f}s")
82
 
83
- # --- Segment Merging ---
84
  if not jumpscare_times:
85
  msg = "No jumpscares detected. Try a lower sensitivity value."
86
  logging.warning(msg)
87
  raise gr.Error(msg)
88
 
89
- logging.info(f"Merging {len(jumpscare_times)} detected frames into continuous clips...")
 
90
  merged_segments = []
91
  if jumpscare_times:
92
  start_time = end_time = jumpscare_times[0]
93
  for t in jumpscare_times[1:]:
94
  if t <= end_time + post_scare_buffer:
95
- end_time = t # Extend the segment
96
  else:
97
  merged_segments.append((max(0, start_time - pre_scare_buffer), end_time + post_scare_buffer))
98
  start_time = end_time = t
99
  merged_segments.append((max(0, start_time - pre_scare_buffer), end_time + post_scare_buffer))
100
 
101
- # --- Video Creation ---
102
  progress(0.9, desc="Stitching clips together...")
103
  final_clips = [original_clip.subclip(start, min(end, original_clip.duration)) for start, end in merged_segments]
104
 
105
  final_video = concatenate_videoclips(final_clips, method="compose")
106
 
 
107
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
108
- output_filename = f"jumpscare_compilation_{timestamp}.mp4"
109
- output_path = os.path.join(OUTPUT_DIR, output_filename)
110
 
111
  logging.info(f"Writing final video to {output_path}")
112
  final_video.write_videofile(output_path, codec="libx264", audio_codec="aac")
@@ -121,7 +116,7 @@ def generate_jumpscare_compilation(video_path, sensitivity, progress=gr.Progress
121
  logging.error(f"An error occurred: {e}", exc_info=True)
122
  raise gr.Error(f"An unexpected error occurred. Check the logs for details. Error: {e}")
123
 
124
- # --- Gradio Interface ---
125
  iface = gr.Interface(
126
  fn=generate_jumpscare_compilation,
127
  inputs=[
@@ -131,7 +126,7 @@ iface = gr.Interface(
131
  ],
132
  outputs=gr.Video(label="Jumpscare Compilation"),
133
  title="🤖 AI FNAF Jumpscare Dump Generator",
134
- description="Upload a video, and the AI will find all jumpscares and compile them. This app runs on a trained model.",
135
  allow_flagging="never"
136
  )
137
 
 
8
  import logging
9
  from datetime import datetime
10
 
11
+ # --- IMPORTANT CHANGE: No folders needed ---
12
+ # The code now assumes 'model.h5' is in the same root directory as this app.py file.
13
+ MODEL_PATH = 'model.h5'
14
+
15
+ # --- Setup Basic Logging ---
16
+ # This will print helpful info to the Hugging Face logs for debugging.
 
 
17
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
18
 
19
  # --- Load Model ---
20
  if not os.path.exists(MODEL_PATH):
21
+ error_msg = f"Model file not found at '{MODEL_PATH}'. Make sure you have uploaded your 'model.h5' to the root of your Space."
22
  logging.error(error_msg)
23
  raise FileNotFoundError(error_msg)
24
 
25
  model = tf.keras.models.load_model(MODEL_PATH)
26
  logging.info("AI model loaded successfully.")
27
 
28
+ # Based on your training code, LabelBinarizer sorts class names alphabetically.
29
+ # "jumpscare" comes before "normal", so the model's output for the "jumpscare" class
30
+ # will be at index 0. If this is wrong, change this to 1.
 
31
  JUMPSCARE_CLASS_INDEX = 0
32
+ logging.info(f"Using class index {JUMPSCARE_CLASS_INDEX} for 'jumpscare' probability.")
33
 
34
 
35
  def predict_frame_is_jumpscare(frame, threshold):
36
  """Analyzes a single video frame and predicts if it's a jumpscare."""
37
+ # Preprocess the frame
38
  rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
39
  resized_frame = cv2.resize(rgb_frame, (128, 128))
40
  img_array = np.array(resized_frame) / 255.0
41
  img_array = np.expand_dims(img_array, axis=0)
42
 
43
+ # Get the model's prediction (e.g., [[0.9, 0.1]])
44
  prediction = model.predict(img_array, verbose=0)
45
 
46
+ # Get the specific probability for the 'jumpscare' class
 
47
  jumpscare_probability = prediction[0][JUMPSCARE_CLASS_INDEX]
48
 
49
  return jumpscare_probability > threshold
 
55
  # --- Initialization ---
56
  threshold = sensitivity / 100.0
57
  analysis_fps = 10
58
+ pre_scare_buffer = 1.0 # seconds before the scare
59
+ post_scare_buffer = 1.5 # seconds after the scare
60
 
61
  logging.info(f"Starting analysis for video: {os.path.basename(video_path)}")
62
  logging.info(f"Settings: Sensitivity={sensitivity}, Threshold={threshold}")
 
74
 
75
  if predict_frame_is_jumpscare(frame, threshold):
76
  jumpscare_times.append(current_time)
 
77
 
 
78
  if not jumpscare_times:
79
  msg = "No jumpscares detected. Try a lower sensitivity value."
80
  logging.warning(msg)
81
  raise gr.Error(msg)
82
 
83
+ # --- Merge close detections into continuous segments ---
84
+ logging.info(f"Merging {len(jumpscare_times)} detected frames into clips...")
85
  merged_segments = []
86
  if jumpscare_times:
87
  start_time = end_time = jumpscare_times[0]
88
  for t in jumpscare_times[1:]:
89
  if t <= end_time + post_scare_buffer:
90
+ end_time = t
91
  else:
92
  merged_segments.append((max(0, start_time - pre_scare_buffer), end_time + post_scare_buffer))
93
  start_time = end_time = t
94
  merged_segments.append((max(0, start_time - pre_scare_buffer), end_time + post_scare_buffer))
95
 
96
+ # --- Create Final Video ---
97
  progress(0.9, desc="Stitching clips together...")
98
  final_clips = [original_clip.subclip(start, min(end, original_clip.duration)) for start, end in merged_segments]
99
 
100
  final_video = concatenate_videoclips(final_clips, method="compose")
101
 
102
+ # Save the output video to the root with a unique name
103
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
104
+ output_path = f"jumpscare_compilation_{timestamp}.mp4"
 
105
 
106
  logging.info(f"Writing final video to {output_path}")
107
  final_video.write_videofile(output_path, codec="libx264", audio_codec="aac")
 
116
  logging.error(f"An error occurred: {e}", exc_info=True)
117
  raise gr.Error(f"An unexpected error occurred. Check the logs for details. Error: {e}")
118
 
119
+ # --- Gradio Interface (Simplified) ---
120
  iface = gr.Interface(
121
  fn=generate_jumpscare_compilation,
122
  inputs=[
 
126
  ],
127
  outputs=gr.Video(label="Jumpscare Compilation"),
128
  title="🤖 AI FNAF Jumpscare Dump Generator",
129
+ description="Upload a video, and the AI will find all jumpscares and compile them. All files are in the root directory.",
130
  allow_flagging="never"
131
  )
132