Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6681a89

Browse files
Add files via upload
1 parent 1a92214 commit 6681a89

File tree

9 files changed

+369
-0
lines changed

9 files changed

+369
-0
lines changed

app.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from flask import Flask, render_template, request, jsonify
2+
import os
3+
import subprocess
4+
5+
app = Flask(__name__)
6+
7+
@app.route('/')
8+
def index():
9+
return render_template('index.html')
10+
11+
@app.route('/analyze', methods=['POST'])
12+
def analyze():
13+
youtube_url = request.form['youtube_url']
14+
15+
# Call the YouTube frame extractor script
16+
subprocess.run(['python', 'youtube_frame_extractor.py', youtube_url])
17+
18+
# Run analysis scripts
19+
subprocess.run(['python', 'color_analysis.py'])
20+
subprocess.run(['python', 'face_detection.py'])
21+
subprocess.run(['python', 'scene_change_detection.py'])
22+
23+
# Prepare results
24+
results = {
25+
'color_analysis': get_file_content('results/color_analysis/color_analysis_results.txt'),
26+
'face_detection': get_file_content('results/face_detection/face_detection_results.txt'),
27+
'scene_change': get_file_content('results/scene_change/scene_change_results.txt')
28+
}
29+
30+
return render_template('results.html', results=results)
31+
32+
def get_file_content(file_path):
33+
if os.path.exists(file_path):
34+
with open(file_path, 'r') as file:
35+
return file.read()
36+
return "Analysis results not available."
37+
38+
if __name__ == '__main__':
39+
app.run(debug=True)

color_analysis.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import os
2+
import cv2
3+
from collections import Counter
4+
5+
# Function to get the dominant color
6+
def get_dominant_color(frame):
7+
img = cv2.resize(frame, (100, 100))
8+
pixels = img.reshape(-1, 3)
9+
10+
color_count = Counter(map(tuple, pixels))
11+
dominant_color = color_count.most_common(1)[0][0]
12+
13+
return dominant_color
14+
15+
# Analyze frames and categorize by dominant color
16+
def analyze_frames():
17+
frame_folder = 'frames'
18+
result_dir = 'results/color_analysis'
19+
os.makedirs(result_dir, exist_ok=True) # Create results directory if it doesn't exist
20+
21+
color_categorized_frames = {}
22+
23+
for filename in os.listdir(frame_folder):
24+
if filename.endswith('.jpg'):
25+
frame_path = os.path.join(frame_folder, filename)
26+
frame = cv2.imread(frame_path)
27+
28+
# Get dominant color
29+
dominant_color = get_dominant_color(frame)
30+
31+
if dominant_color not in color_categorized_frames:
32+
color_categorized_frames[dominant_color] = []
33+
color_categorized_frames[dominant_color].append(frame_path)
34+
35+
# Save results to a text file in the specific results folder
36+
with open(os.path.join(result_dir, 'color_analysis_results.txt'), 'w') as f:
37+
for color, frames in color_categorized_frames.items():
38+
f.write(f"Color (RGB): {color}, Number of Frames: {len(frames)}\n")
39+
40+
if __name__ == "__main__":
41+
analyze_frames()

face_detection.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import os
2+
import cv2
3+
4+
# Load the pre-trained Haar Cascade model for face detection
5+
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
6+
7+
# Function to detect faces in a frame
8+
def detect_faces(frame):
9+
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
10+
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)
11+
return len(faces) > 0 # Return True if faces are detected
12+
13+
# Analyze frames based on face detection
14+
def analyze_frames():
15+
frame_folder = 'frames'
16+
result_dir = 'results/face_detection'
17+
os.makedirs(result_dir, exist_ok=True) # Create results directory if it doesn't exist
18+
19+
face_categorized_frames = {'with_faces': [], 'without_faces': []}
20+
21+
for filename in os.listdir(frame_folder):
22+
if filename.endswith('.jpg'):
23+
frame_path = os.path.join(frame_folder, filename)
24+
frame = cv2.imread(frame_path)
25+
26+
# Check for faces in the frame
27+
if detect_faces(frame):
28+
face_categorized_frames['with_faces'].append(frame_path)
29+
else:
30+
face_categorized_frames['without_faces'].append(frame_path)
31+
32+
# Save results to a text file in the specific results folder
33+
with open(os.path.join(result_dir, 'face_detection_results.txt'), 'w') as f:
34+
for category, frames in face_categorized_frames.items():
35+
f.write(f"Category: {category}, Number of Frames: {len(frames)}\n")
36+
37+
if __name__ == "__main__":
38+
analyze_frames()

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Youtube-Frame-Extraction

requirements.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
yt-dlp
2+
opencv-python
3+
selenium
4+
selenium
5+
yt-dlp
6+
opencv-python
7+
webdriver-manager
8+
flask

scene_change_detection.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import cv2
2+
import os
3+
4+
def scene_change_detection():
5+
frame_folder = 'frames'
6+
result_dir = 'results/scene_change'
7+
os.makedirs(result_dir, exist_ok=True)
8+
9+
previous_frame = None
10+
scene_changes = []
11+
12+
for filename in sorted(os.listdir(frame_folder)):
13+
if filename.endswith('.jpg'):
14+
frame_path = os.path.join(frame_folder, filename)
15+
frame = cv2.imread(frame_path)
16+
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
17+
18+
if previous_frame is not None:
19+
diff = cv2.absdiff(previous_frame, gray_frame)
20+
non_zero_count = cv2.countNonZero(diff)
21+
22+
# Threshold for significant scene change
23+
if non_zero_count > 10000: # Adjust threshold as needed
24+
scene_changes.append(frame_path)
25+
26+
previous_frame = gray_frame
27+
28+
with open(os.path.join(result_dir, 'scene_change_results.txt'), 'w') as f:
29+
for scene in scene_changes:
30+
f.write(f"Scene Change Detected: {scene}\n")
31+
32+
if __name__ == "__main__":
33+
scene_change_detection()

templates/index.html

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>YouTube Video Analysis</title>
7+
<style>
8+
body {
9+
font-family: Arial, sans-serif;
10+
line-height: 1.6;
11+
margin: 0;
12+
padding: 20px;
13+
background-color: #f4f4f4;
14+
}
15+
.container {
16+
max-width: 800px;
17+
margin: auto;
18+
background: white;
19+
padding: 20px;
20+
border-radius: 5px;
21+
box-shadow: 0 0 10px rgba(0,0,0,0.1);
22+
}
23+
h1 {
24+
color: #333;
25+
}
26+
input[type="text"] {
27+
width: 100%;
28+
padding: 10px;
29+
margin-bottom: 10px;
30+
}
31+
button {
32+
background-color: #4CAF50;
33+
color: white;
34+
padding: 10px 15px;
35+
border: none;
36+
cursor: pointer;
37+
}
38+
button:hover {
39+
background-color: #45a049;
40+
}
41+
</style>
42+
</head>
43+
<body>
44+
<div class="container">
45+
<h1>YouTube Video Analysis</h1>
46+
<form action="{{ url_for('analyze') }}" method="post">
47+
<input type="text" name="youtube_url" placeholder="Enter YouTube video URL" required>
48+
<button type="submit">Start Analysis</button>
49+
</form>
50+
</div>
51+
</body>
52+
</html>

templates/results.html

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Analysis Results</title>
7+
<style>
8+
body {
9+
font-family: Arial, sans-serif;
10+
line-height: 1.6;
11+
margin: 0;
12+
padding: 20px;
13+
background-color: #f4f4f4;
14+
}
15+
.container {
16+
max-width: 800px;
17+
margin: auto;
18+
background: white;
19+
padding: 20px;
20+
border-radius: 5px;
21+
box-shadow: 0 0 10px rgba(0,0,0,0.1);
22+
}
23+
h1, h2 {
24+
color: #333;
25+
}
26+
.result-section {
27+
background-color: #e9e9e9;
28+
padding: 10px;
29+
margin-bottom: 20px;
30+
border-radius: 3px;
31+
}
32+
pre {
33+
white-space: pre-wrap;
34+
word-wrap: break-word;
35+
}
36+
</style>
37+
</head>
38+
<body>
39+
<div class="container">
40+
<h1>Analysis Results</h1>
41+
42+
<div class="result-section">
43+
<h2>Color Analysis</h2>
44+
<pre>{{ results.color_analysis }}</pre>
45+
</div>
46+
47+
<div class="result-section">
48+
<h2>Face Detection</h2>
49+
<pre>{{ results.face_detection }}</pre>
50+
</div>
51+
52+
<div class="result-section">
53+
<h2>Scene Change Detection</h2>
54+
<pre>{{ results.scene_change }}</pre>
55+
</div>
56+
57+
<a href="{{ url_for('index') }}">Analyze Another Video</a>
58+
</div>
59+
</body>
60+
</html>

youtube_frame_extractor.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import os
2+
import cv2
3+
import time
4+
import yt_dlp as youtube_dl
5+
from selenium import webdriver
6+
from selenium.webdriver.chrome.service import Service
7+
from selenium.webdriver.common.by import By
8+
from selenium.webdriver.chrome.options import Options
9+
from webdriver_manager.chrome import ChromeDriverManager
10+
11+
# Function to set up Selenium and handle ads on YouTube
12+
def setup_selenium_and_skip_ads(youtube_url):
13+
# Configure Selenium options (headless for background operation)
14+
chrome_options = Options()
15+
chrome_options.add_argument("--headless")
16+
chrome_options.add_argument("--disable-gpu")
17+
chrome_options.add_argument("--no-sandbox")
18+
chrome_options.add_argument("--disable-dev-shm-usage")
19+
20+
# Set up Selenium WebDriver (automatically downloads the correct ChromeDriver)
21+
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=chrome_options)
22+
23+
# Open YouTube URL
24+
driver.get(youtube_url)
25+
26+
# Wait for ads (you can adjust this wait time depending on the network speed)
27+
time.sleep(10)
28+
29+
# Check if there is a "Skip Ad" button
30+
try:
31+
skip_button = driver.find_element(By.CLASS_NAME, "ytp-ad-skip-button")
32+
if skip_button:
33+
skip_button.click()
34+
print("Ad skipped")
35+
except:
36+
print("No skippable ad found or already skipped")
37+
38+
# Get the current URL after ads (if redirected)
39+
current_url = driver.current_url
40+
41+
# Close the browser after handling the ad
42+
driver.quit()
43+
44+
return current_url
45+
46+
# Function to download the video using yt-dlp
47+
def download_youtube_video(youtube_url):
48+
ydl_opts = {
49+
'format': 'best', # Get the best quality video
50+
'outtmpl': 'video.mp4', # Name of the downloaded video
51+
}
52+
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
53+
ydl.download([youtube_url])
54+
55+
# Function to extract frames using OpenCV
56+
def extract_frames(video_path, output_folder):
57+
if not os.path.exists(output_folder):
58+
os.makedirs(output_folder)
59+
60+
cap = cv2.VideoCapture(video_path)
61+
frame_count = 0
62+
63+
while True:
64+
ret, frame = cap.read()
65+
if not ret:
66+
break
67+
68+
# Save each frame as an image
69+
frame_path = os.path.join(output_folder, f"frame_{frame_count:05d}.jpg")
70+
cv2.imwrite(frame_path, frame)
71+
72+
frame_count += 1
73+
74+
cap.release()
75+
print(f"Extracted {frame_count} frames.")
76+
77+
# Main flow
78+
def main(youtube_url):
79+
print("Processing YouTube video...")
80+
81+
# Step 1: Handle YouTube ads and get the final video URL
82+
processed_url = setup_selenium_and_skip_ads(youtube_url)
83+
84+
# Step 2: Download the video using yt-dlp
85+
print(f"Downloading video from: {processed_url}")
86+
download_youtube_video(processed_url)
87+
88+
# Step 3: Extract frames from the downloaded video
89+
print("Extracting frames from video...")
90+
extract_frames('video.mp4', 'frames')
91+
92+
print("Process completed.")
93+
94+
# Example usage
95+
if __name__ == "__main__":
96+
youtube_video_url = "https://www.youtube.com/watch?v=7Y5q41D8_hs" # Replace with your video URL
97+
main(youtube_video_url)

0 commit comments

Comments
 (0)