Ubuntu
commited on
Commit
Β·
9d177c3
1
Parent(s):
e19e95a
add application file
Browse files
app.py
ADDED
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import requests
|
3 |
+
from yt_dlp import YoutubeDL
|
4 |
+
import os
|
5 |
+
import tempfile
|
6 |
+
from typing import Optional
|
7 |
+
import json
|
8 |
+
import subprocess
|
9 |
+
|
10 |
+
# Define the FastAPI URL
|
11 |
+
API_URL = "http://localhost:9998"
|
12 |
+
|
13 |
+
def download_youtube_audio(url: str, output_dir: Optional[str] = None) -> str:
|
14 |
+
if output_dir is None:
|
15 |
+
output_dir = tempfile.gettempdir()
|
16 |
+
|
17 |
+
yt_dlp_command = [
|
18 |
+
"/home/ubuntu/miniconda3/envs/gradio_whisper/bin/yt-dlp",
|
19 |
+
"-f", "bestaudio/best",
|
20 |
+
"-x", # Extract audio
|
21 |
+
"--audio-format", "mp3",
|
22 |
+
"--audio-quality", "192K",
|
23 |
+
"-o", os.path.join(output_dir, "%(id)s.%(ext)s"),
|
24 |
+
"-v",
|
25 |
+
"--print", "after_move:filepath", # Print the output filepath
|
26 |
+
"--username", "oauth2",
|
27 |
+
"--password", "",
|
28 |
+
"--no-playlist",
|
29 |
+
"--print-json",
|
30 |
+
url
|
31 |
+
]
|
32 |
+
|
33 |
+
try:
|
34 |
+
print(' '.join(yt_dlp_command))
|
35 |
+
result = subprocess.run(yt_dlp_command, capture_output=True, text=True, check=True)
|
36 |
+
|
37 |
+
# Parse the JSON output to get video information
|
38 |
+
video_info = json.loads(result.stdout.splitlines()[-2]) # The last line is the filepath
|
39 |
+
|
40 |
+
# Get the output filepath from the last line of stdout
|
41 |
+
audio_file = result.stdout.splitlines()[-1].strip()
|
42 |
+
|
43 |
+
print(f"Successfully downloaded: {video_info['title']}")
|
44 |
+
return audio_file
|
45 |
+
except subprocess.CalledProcessError as e:
|
46 |
+
raise Exception(f"Error downloading YouTube audio: {e.stderr}")
|
47 |
+
except json.JSONDecodeError:
|
48 |
+
raise Exception("Error parsing video information")
|
49 |
+
except Exception as e:
|
50 |
+
raise Exception(f"Unexpected error: {str(e)}")
|
51 |
+
|
52 |
+
|
53 |
+
def run_asr(audio_file, youtube_url):
|
54 |
+
temp_file = None
|
55 |
+
try:
|
56 |
+
if youtube_url:
|
57 |
+
# It's a YouTube URL
|
58 |
+
audio_file = download_youtube_audio(youtube_url)
|
59 |
+
temp_file = audio_file
|
60 |
+
elif not audio_file:
|
61 |
+
return "Please provide either an audio file or a YouTube URL."
|
62 |
+
|
63 |
+
files = {'file': open(audio_file, 'rb')}
|
64 |
+
data = {'language': 'en', 'model_name': 'whisper-large-v2-imda'}
|
65 |
+
response = requests.post(f"{API_URL}/asr", data=data, files=files)
|
66 |
+
|
67 |
+
if response.status_code == 200:
|
68 |
+
return response.json().get("text", "")
|
69 |
+
else:
|
70 |
+
return f"Error: {response.status_code}"
|
71 |
+
except Exception as e:
|
72 |
+
return f"Error: {str(e)}"
|
73 |
+
finally:
|
74 |
+
# Clean up the temporary file if it was a YouTube download
|
75 |
+
if temp_file and os.path.exists(temp_file):
|
76 |
+
os.remove(temp_file)
|
77 |
+
|
78 |
+
def embed_youtube(youtube_url):
|
79 |
+
if youtube_url:
|
80 |
+
try:
|
81 |
+
# video_id = YoutubeDL().extract_info(youtube_url, download=False)['id']\
|
82 |
+
video_id = youtube_url.split("v=")[1]
|
83 |
+
print(video_id)
|
84 |
+
embed_html = f'<iframe width="560" height="315" src="https://www.youtube.com/embed/{video_id}" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>'
|
85 |
+
return gr.update(value=embed_html, visible=True), "", None
|
86 |
+
except:
|
87 |
+
return gr.update(value="", visible=False), "Invalid YouTube URL", None
|
88 |
+
return gr.update(value="", visible=False), "", None
|
89 |
+
|
90 |
+
def clear_on_audio_input(audio):
|
91 |
+
if audio is not None:
|
92 |
+
return "", gr.update(value="", visible=False), ""
|
93 |
+
return gr.update(), gr.update(), gr.update()
|
94 |
+
|
95 |
+
# Create the Gradio interface with improved aesthetics
|
96 |
+
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
97 |
+
gr.Markdown("# ποΈ Audio Transcription Service")
|
98 |
+
gr.Markdown("Upload an audio file, record your voice, or paste a YouTube URL to get an English transcription.")
|
99 |
+
|
100 |
+
with gr.Row():
|
101 |
+
with gr.Column(scale=2):
|
102 |
+
audio_input = gr.Audio(sources=['microphone', 'upload'], type="filepath", label="Audio Input")
|
103 |
+
youtube_input = gr.Textbox(label="YouTube URL", placeholder="Or paste a YouTube URL here...")
|
104 |
+
video_player = gr.HTML(visible=False)
|
105 |
+
with gr.Column(scale=3):
|
106 |
+
result = gr.Textbox(
|
107 |
+
label="Transcription Result",
|
108 |
+
placeholder="Your transcription will appear here...",
|
109 |
+
lines=10
|
110 |
+
)
|
111 |
+
|
112 |
+
run_button = gr.Button("π Transcribe Audio", variant="primary")
|
113 |
+
run_button.click(run_asr, inputs=[audio_input, youtube_input], outputs=[result])
|
114 |
+
|
115 |
+
# Update video player and clear transcription and audio input when YouTube URL is entered
|
116 |
+
youtube_input.change(
|
117 |
+
fn=embed_youtube,
|
118 |
+
inputs=[youtube_input],
|
119 |
+
outputs=[video_player, result, audio_input]
|
120 |
+
)
|
121 |
+
|
122 |
+
# Clear transcription, YouTube input, and video player when audio is input
|
123 |
+
audio_input.change(
|
124 |
+
fn=clear_on_audio_input,
|
125 |
+
inputs=[audio_input],
|
126 |
+
outputs=[result, video_player, youtube_input]
|
127 |
+
)
|
128 |
+
|
129 |
+
gr.Markdown("### How to use:")
|
130 |
+
gr.Markdown("1. Upload an audio file or record your voice using the microphone, OR paste a YouTube URL.")
|
131 |
+
gr.Markdown("2. If you paste a YouTube URL, the video will be displayed for your reference, and any previous transcription or audio input will be cleared.")
|
132 |
+
gr.Markdown("3. If you upload or record audio, any previous transcription, YouTube URL, and video will be cleared.")
|
133 |
+
gr.Markdown("4. Click the 'Transcribe Audio' button to start the process.")
|
134 |
+
gr.Markdown("5. Wait for a few seconds, and your transcription will appear in the result box.")
|
135 |
+
|
136 |
+
# Launch the Gradio interface
|
137 |
+
demo.launch(
|
138 |
+
server_name='0.0.0.0',
|
139 |
+
server_port=5008,
|
140 |
+
ssl_certfile='/home/ubuntu/astarwiz_com/astarwiz_com.crt',
|
141 |
+
ssl_keyfile='/home/ubuntu/astarwiz_com/astarwiz_com.key',
|
142 |
+
ssl_verify=False
|
143 |
+
)
|