ayloll commited on
Commit
ff027b3
·
verified ·
1 Parent(s): 4c07346

Upload 3 files

Browse files
Files changed (3) hide show
  1. app.py +154 -0
  2. dockerfile.dockerfile +26 -0
  3. requirements.txt +8 -0
app.py ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from transformers import pipeline
3
+ import yt_dlp
4
+ import whisper
5
+ import os
6
+ import uuid
7
+ import re
8
+
9
+ # Delete temporary files
10
+ def clean_temp_files():
11
+ temp_files = ["temp_video.mp4", "temp_audio.mp3"]
12
+ for file in temp_files:
13
+ if os.path.exists(file):
14
+ os.remove(file)
15
+
16
+ # Download YouTube video
17
+ def download_video(video_url):
18
+ try:
19
+ ydl_opts = {
20
+ 'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]',
21
+ 'outtmpl': 'temp_video.mp4',
22
+ 'quiet': True,
23
+ 'no_warnings': True,
24
+ }
25
+
26
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
27
+ ydl.download([video_url])
28
+ return "temp_video.mp4"
29
+ except Exception as e:
30
+ print(f"Download error: {e}")
31
+ return None
32
+
33
+ # Extract audio (temporary)
34
+ def extract_audio(video_path):
35
+ os.system(f"ffmpeg -i \"{video_path}\" -vn -acodec libmp3lame -q:a 3 \"temp_audio.mp3\" -y")
36
+ return "temp_audio.mp3" if os.path.exists("temp_audio.mp3") else None
37
+
38
+ # Transcribe audio
39
+ def transcribe_audio(audio_path):
40
+ try:
41
+ model = whisper.load_model("base")
42
+ result = model.transcribe(audio_path)
43
+ return result['text']
44
+ except Exception as e:
45
+ print(f"Transcription error: {e}")
46
+ return None
47
+
48
+ # Classify content
49
+ def classify_content(text):
50
+ try:
51
+ if not text or len(text.strip()) == 0:
52
+ return None, None
53
+
54
+ classifier = pipeline("zero-shot-classification",
55
+ model="facebook/bart-large-mnli")
56
+
57
+ labels = ["educational", "entertainment", "news", "political",
58
+ "religious", "technical", "advertisement", "social"]
59
+
60
+ result = classifier(text,
61
+ candidate_labels=labels,
62
+ hypothesis_template="This text is about {}.")
63
+
64
+ return result['labels'][0], result['scores'][0]
65
+ except Exception as e:
66
+ print(f"Classification error: {e}")
67
+ return None, None
68
+
69
+ # Main processing function
70
+ def process_video(video_url):
71
+ clean_temp_files()
72
+
73
+ if not video_url or len(video_url.strip()) == 0:
74
+ return "Please enter a valid YouTube URL", ""
75
+
76
+ if "youtube.com" not in video_url and "youtu.be" not in video_url:
77
+ return "Please enter a valid YouTube URL", ""
78
+
79
+ # Download video
80
+ video_path = download_video(video_url)
81
+ if not video_path:
82
+ return "Failed to download video", ""
83
+
84
+ # Extract audio
85
+ audio_path = extract_audio(video_path)
86
+ if not audio_path:
87
+ clean_temp_files()
88
+ return "Failed to extract audio", ""
89
+
90
+ # Transcribe
91
+ transcription = transcribe_audio(audio_path)
92
+ if not transcription:
93
+ clean_temp_files()
94
+ return "Failed to transcribe audio", ""
95
+
96
+ # Classify
97
+ category, confidence = classify_content(transcription)
98
+ if not category:
99
+ clean_temp_files()
100
+ return transcription, "Failed to classify content"
101
+
102
+ # Clean up
103
+ clean_temp_files()
104
+
105
+ # Format classification result
106
+ classification_result = f"{category} (confidence: {confidence:.2f})"
107
+ return transcription, classification_result
108
+
109
+ # Gradio interface
110
+ with gr.Blocks(title="YouTube Content Analyzer") as demo:
111
+ gr.Markdown("""
112
+ # ▶️ YouTube Content Analyzer
113
+ Enter a YouTube video URL to get transcription and content classification
114
+ """)
115
+
116
+ with gr.Row():
117
+ url_input = gr.Textbox(
118
+ label="YouTube URL",
119
+ placeholder="Enter YouTube video URL here..."
120
+ )
121
+
122
+ with gr.Row():
123
+ transcription_output = gr.Textbox(
124
+ label="Transcription",
125
+ interactive=True,
126
+ lines=10,
127
+ max_lines=20
128
+ )
129
+
130
+ with gr.Row():
131
+ category_output = gr.Textbox(
132
+ label="Content Category",
133
+ interactive=False
134
+ )
135
+
136
+ submit_btn = gr.Button("Analyze Video", variant="primary")
137
+
138
+ # Examples
139
+ gr.Examples(
140
+ examples=[
141
+ ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],
142
+ ["https://youtu.be/dQw4w9WgXcQ"]
143
+ ],
144
+ inputs=url_input
145
+ )
146
+
147
+ submit_btn.click(
148
+ fn=process_video,
149
+ inputs=url_input,
150
+ outputs=[transcription_output, category_output]
151
+ )
152
+
153
+ if __name__ == "__main__":
154
+ demo.launch(server_name="0.0.0.0", server_port=7860)
dockerfile.dockerfile ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use official Python image
2
+ FROM python:3.9-slim
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Install system dependencies
8
+ RUN apt-get update && \
9
+ apt-get install -y --no-install-recommends ffmpeg && \
10
+ rm -rf /var/lib/apt/lists/*
11
+
12
+ # Copy requirements first to leverage Docker cache
13
+ COPY requirements.txt .
14
+ RUN pip install --no-cache-dir -r requirements.txt
15
+
16
+ # Copy the rest of the application
17
+ COPY . .
18
+
19
+ # Download Whisper model during build (optional)
20
+ # RUN python -c "import whisper; whisper.load_model('base')"
21
+
22
+ # Expose port
23
+ EXPOSE 7860
24
+
25
+ # Run the application
26
+ CMD ["python", "app.py"]
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ gradio>=3.0
2
+ yt-dlp>=2023.7.6
3
+ openai-whisper>=2023.6.14
4
+ pydub>=0.25.1
5
+ ffmpeg-python>=0.2.0
6
+ transformers>=4.30.0
7
+ requests>=2.28.0
8
+ python-dotenv>=0.21.0