leeksang commited on
Commit
9c06d0f
·
verified ·
1 Parent(s): 28543c7

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +104 -0
app.py ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import subprocess
3
+ import sys
4
+ import requests
5
+ import gradio as gr
6
+ from urllib.parse import urlparse
7
+ from moviepy.editor import VideoFileClip
8
+ from transformers import pipeline
9
+ import yt_dlp as youtube_dl
10
+
11
+ # Ensure required packages are installed
12
+ def install_package(package):
13
+ try:
14
+ __import__(package)
15
+ except ImportError:
16
+ print(f"Installing {package}...")
17
+ subprocess.check_call([sys.executable, "-m", "pip", "install", package])
18
+ __import__(package)
19
+
20
+ install_package("torch")
21
+ install_package("tensorflow")
22
+ install_package("transformers")
23
+ install_package("gradio")
24
+ install_package("yt-dlp")
25
+ install_package("moviepy")
26
+
27
+ # Check if URL is a direct video file
28
+ def is_direct_video_link(url: str) -> bool:
29
+ parsed = urlparse(url)
30
+ path = parsed.path.lower()
31
+ return any(path.endswith(ext) for ext in (".mp4", ".mov", ".avi", ".mkv", ".wmv", ".flv"))
32
+
33
+ # Download functions
34
+ def download_video_direct(video_url: str, filename: str = "video"):
35
+ ext = os.path.splitext(urlparse(video_url).path)[1]
36
+ if ext == "":
37
+ raise ValueError("Cannot determine file extension.")
38
+ filename_with_ext = filename + ext
39
+ print(f"Downloading: {video_url}")
40
+ resp = requests.get(video_url, stream=True)
41
+ resp.raise_for_status()
42
+ with open(filename_with_ext, "wb") as f:
43
+ for chunk in resp.iter_content(chunk_size=8192):
44
+ f.write(chunk)
45
+ return filename_with_ext
46
+
47
+ def download_video_via_yt_dlp(video_url: str, filename: str = "video.mp4"):
48
+ ydl_opts = {
49
+ "format": "best[ext=mp4]/best",
50
+ "outtmpl": filename,
51
+ "noplaylist": True,
52
+ "quiet": True
53
+ }
54
+ print(f"Downloading (yt-dlp): {video_url}")
55
+ with youtube_dl.YoutubeDL(ydl_opts) as ydl:
56
+ ydl.download([video_url])
57
+ return filename
58
+
59
+ # Extract audio via MoviePy (Supports ALL video formats)
60
+ def extract_audio(video_filename: str, audio_filename: str = "audio.wav") -> str:
61
+ try:
62
+ video = VideoFileClip(video_filename)
63
+ audio = video.audio
64
+ audio.write_audiofile(audio_filename)
65
+ return audio_filename
66
+ except Exception as e:
67
+ raise Exception(f"Audio extraction failed: {e}")
68
+
69
+ # Hugging Face accent classifier
70
+ def classify_accent(audio_file: str, model_name: str = "superb/wav2vec2-base-superb-sid") -> str:
71
+ classifier = pipeline("audio-classification", model=model_name)
72
+ results = classifier(audio_file)
73
+ if results:
74
+ top = results[0]
75
+ return f"Accent: {top['label']} (Confidence: {top['score'] * 100:.2f}%)"
76
+ return "No classification result."
77
+
78
+ # Full pipeline for Gradio
79
+ def accent_classifier(video_url: str) -> str:
80
+ tmp_video, tmp_audio = None, None
81
+ try:
82
+ tmp_video = download_video_direct(video_url) if is_direct_video_link(video_url) else download_video_via_yt_dlp(video_url)
83
+ tmp_audio = extract_audio(tmp_video)
84
+ result = classify_accent(tmp_audio)
85
+ except Exception as e:
86
+ result = f"Error: {e}"
87
+ finally:
88
+ if tmp_video and os.path.exists(tmp_video):
89
+ os.remove(tmp_video)
90
+ if tmp_audio and os.path.exists(tmp_audio):
91
+ os.remove(tmp_audio)
92
+ return result
93
+
94
+ # Gradio UI setup
95
+ iface = gr.Interface(
96
+ fn=accent_classifier,
97
+ inputs=gr.Textbox(label="Video URL", placeholder="Enter a direct video or streaming link"),
98
+ outputs="text",
99
+ title="🎤 Accent Classifier",
100
+ description="Paste any video URL (MP4/MOV/AVI/MKV/WMV/FLV, YouTube, Vimeo, etc.). This will download, extract audio, and classify the speaker's accent."
101
+ )
102
+
103
+ if __name__ == "__main__":
104
+ iface.launch()