Spaces:
Runtime error
Runtime error
add error checking
Browse files- app.py +78 -42
- helpers.py +10 -15
app.py
CHANGED
@@ -1,85 +1,121 @@
|
|
1 |
import gradio as gr
|
2 |
-
import os
|
|
|
3 |
|
4 |
-
from helpers import
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
|
6 |
|
7 |
title = """<h1 align="center">🔥AssemblyAI: Conformer-1 Demo🔥</h1>"""
|
8 |
|
9 |
-
subtitle =
|
|
|
|
|
10 |
link = """<p align="center"><a href="https://www.assemblyai.com/blog/conformer-1/">Click here to learn more about the Conformer-1 model</a></p>"""
|
11 |
|
12 |
|
13 |
-
def submit_to_AAI(api_key,
|
14 |
-
radio,
|
15 |
-
audio_file,
|
16 |
-
mic_recording):
|
17 |
|
18 |
if radio == "Audio File":
|
19 |
audio_data = audio_file
|
20 |
elif radio == "Record Audio":
|
21 |
audio_data = mic_recording
|
22 |
-
|
|
|
|
|
|
|
23 |
header = make_header(api_key)
|
24 |
-
|
25 |
# 1. Upload the audio
|
26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
|
28 |
# 2. Request transcript
|
29 |
transcript_response = request_transcript(upload_url, header)
|
30 |
-
|
31 |
-
transcript_id = transcript_response[
|
32 |
-
|
33 |
# 3. Wait for the transcription to complete
|
34 |
_, error = wait_for_completion(transcript_id, header)
|
35 |
-
|
36 |
if error is not None:
|
37 |
return error
|
38 |
|
39 |
-
# 4. Fetch paragraphs of transcript
|
40 |
return make_paragraphs_string(transcript_id, header)
|
41 |
|
42 |
|
43 |
def change_audio_source(radio):
|
44 |
if radio == "Audio File":
|
45 |
-
return [gr.Audio.update(visible=True),
|
46 |
-
gr.Audio.update(visible=False)]
|
47 |
elif radio == "Record Audio":
|
48 |
-
return [gr.Audio.update(visible=False),
|
49 |
-
|
50 |
-
|
51 |
-
with gr.Blocks(
|
52 |
-
|
53 |
-
|
|
|
|
|
|
|
|
|
54 |
gr.HTML(title)
|
55 |
gr.HTML(subtitle)
|
56 |
gr.HTML(link)
|
57 |
-
gr.HTML(
|
58 |
-
|
|
|
|
|
59 |
with gr.Column(elem_id="col_container"):
|
60 |
-
api_key = gr.Textbox(
|
61 |
-
|
|
|
|
|
62 |
with gr.Box():
|
63 |
# Selector for audio source
|
64 |
-
radio = gr.Radio(
|
|
|
|
|
65 |
# Audio object for both file and microphone data
|
66 |
audio_file = gr.Audio()
|
67 |
mic_recording = gr.Audio(source="microphone", visible=False)
|
68 |
-
|
69 |
-
gr.Examples(
|
70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
btn = gr.Button("Run")
|
72 |
-
|
73 |
-
out = gr.Textbox(
|
74 |
-
|
|
|
|
|
75 |
# Changing audio source changes Audio input component
|
76 |
-
radio.change(
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
# Clicking "submit" uploads selected audio to AssemblyAI, performs requested analyses, and displays results
|
81 |
-
btn.click(
|
82 |
-
|
83 |
-
|
|
|
|
|
84 |
|
85 |
-
demo.launch(debug=True)
|
1 |
import gradio as gr
|
2 |
+
import os
|
3 |
+
import requests
|
4 |
|
5 |
+
from helpers import (
|
6 |
+
make_header,
|
7 |
+
upload_file,
|
8 |
+
request_transcript,
|
9 |
+
wait_for_completion,
|
10 |
+
make_paragraphs_string,
|
11 |
+
)
|
12 |
|
13 |
|
14 |
title = """<h1 align="center">🔥AssemblyAI: Conformer-1 Demo🔥</h1>"""
|
15 |
|
16 |
+
subtitle = (
|
17 |
+
"""<p align="center">Automatic Speech Recognition using the AssemblyAI API</p>"""
|
18 |
+
)
|
19 |
link = """<p align="center"><a href="https://www.assemblyai.com/blog/conformer-1/">Click here to learn more about the Conformer-1 model</a></p>"""
|
20 |
|
21 |
|
22 |
+
def submit_to_AAI(api_key, radio, audio_file, mic_recording):
|
|
|
|
|
|
|
23 |
|
24 |
if radio == "Audio File":
|
25 |
audio_data = audio_file
|
26 |
elif radio == "Record Audio":
|
27 |
audio_data = mic_recording
|
28 |
+
|
29 |
+
if not api_key:
|
30 |
+
return "Error! Did you use a valid API key?"
|
31 |
+
|
32 |
header = make_header(api_key)
|
33 |
+
|
34 |
# 1. Upload the audio
|
35 |
+
try:
|
36 |
+
upload_url = upload_file(audio_data, header, is_file=False)
|
37 |
+
except requests.exceptions.HTTPError:
|
38 |
+
return "Error! Did you use a valid API key?"
|
39 |
+
except requests.exceptions.ConnectionError:
|
40 |
+
return "Error! Did you use a valid API key?"
|
41 |
+
|
42 |
+
# if upload_url is None:
|
43 |
+
# return "Error: Did you set a valid API key?"
|
44 |
|
45 |
# 2. Request transcript
|
46 |
transcript_response = request_transcript(upload_url, header)
|
47 |
+
|
48 |
+
transcript_id = transcript_response["id"]
|
49 |
+
|
50 |
# 3. Wait for the transcription to complete
|
51 |
_, error = wait_for_completion(transcript_id, header)
|
52 |
+
|
53 |
if error is not None:
|
54 |
return error
|
55 |
|
56 |
+
# 4. Fetch paragraphs of transcript
|
57 |
return make_paragraphs_string(transcript_id, header)
|
58 |
|
59 |
|
60 |
def change_audio_source(radio):
|
61 |
if radio == "Audio File":
|
62 |
+
return [gr.Audio.update(visible=True), gr.Audio.update(visible=False)]
|
|
|
63 |
elif radio == "Record Audio":
|
64 |
+
return [gr.Audio.update(visible=False), gr.Audio.update(visible=True)]
|
65 |
+
|
66 |
+
|
67 |
+
with gr.Blocks(
|
68 |
+
css="""#col_container {width: 1000px; margin-left: auto; margin-right: auto;}
|
69 |
+
#chatbot {height: 520px; overflow: auto;}"""
|
70 |
+
) as demo:
|
71 |
+
gr.HTML(
|
72 |
+
'<center><a href="https://www.assemblyai.com/"><img src="file/images/logo.png" width="180px"></a></center>'
|
73 |
+
)
|
74 |
gr.HTML(title)
|
75 |
gr.HTML(subtitle)
|
76 |
gr.HTML(link)
|
77 |
+
gr.HTML(
|
78 |
+
"""<center><a href="https://huggingface.co/spaces/assemblyai/Conformer1-Demo?duplicate=true"><img src="https://bit.ly/3gLdBN6" alt="Duplicate Space"></a>Duplicate the Space and run securely with your AssemblyAI API Key</center>"""
|
79 |
+
)
|
80 |
+
|
81 |
with gr.Column(elem_id="col_container"):
|
82 |
+
api_key = gr.Textbox(
|
83 |
+
type="password", label="Enter your AssemblyAI API key here"
|
84 |
+
)
|
85 |
+
|
86 |
with gr.Box():
|
87 |
# Selector for audio source
|
88 |
+
radio = gr.Radio(
|
89 |
+
["Audio File", "Record Audio"], label="Audio Source", value="Audio File"
|
90 |
+
)
|
91 |
# Audio object for both file and microphone data
|
92 |
audio_file = gr.Audio()
|
93 |
mic_recording = gr.Audio(source="microphone", visible=False)
|
94 |
+
|
95 |
+
gr.Examples(
|
96 |
+
[
|
97 |
+
os.path.join(os.path.dirname(__file__), "audio/audio.mp3"),
|
98 |
+
os.path.join(os.path.dirname(__file__), "audio/gettysburg10.wav"),
|
99 |
+
],
|
100 |
+
audio_file,
|
101 |
+
)
|
102 |
+
|
103 |
btn = gr.Button("Run")
|
104 |
+
|
105 |
+
out = gr.Textbox(
|
106 |
+
placeholder="Your formatted transcript will appear here ...", lines=10
|
107 |
+
)
|
108 |
+
|
109 |
# Changing audio source changes Audio input component
|
110 |
+
radio.change(
|
111 |
+
fn=change_audio_source, inputs=[radio], outputs=[audio_file, mic_recording]
|
112 |
+
)
|
113 |
+
|
114 |
# Clicking "submit" uploads selected audio to AssemblyAI, performs requested analyses, and displays results
|
115 |
+
btn.click(
|
116 |
+
fn=submit_to_AAI,
|
117 |
+
inputs=[api_key, radio, audio_file, mic_recording],
|
118 |
+
outputs=out,
|
119 |
+
)
|
120 |
|
121 |
+
demo.launch(debug=True)
|
helpers.py
CHANGED
@@ -9,10 +9,7 @@ transcript_endpoint = "https://api.assemblyai.com/v2/transcript"
|
|
9 |
|
10 |
|
11 |
def make_header(api_key):
|
12 |
-
return {
|
13 |
-
'authorization': api_key,
|
14 |
-
'content-type': 'application/json'
|
15 |
-
}
|
16 |
|
17 |
|
18 |
def _read_file(filename, chunk_size=5242880):
|
@@ -46,7 +43,7 @@ def upload_file(audio_file, header, is_file=True):
|
|
46 |
upload_response = requests.post(
|
47 |
upload_endpoint,
|
48 |
headers=header,
|
49 |
-
data=_read_file(audio_file) if is_file else _read_array(audio_file)
|
50 |
)
|
51 |
if upload_response.status_code != 200:
|
52 |
upload_response.raise_for_status()
|
@@ -59,18 +56,16 @@ def request_transcript(upload_url, header):
|
|
59 |
|
60 |
# If input is a dict returned from `upload_file` rather than a raw upload_url string
|
61 |
if type(upload_url) is dict:
|
62 |
-
upload_url = upload_url[
|
63 |
|
64 |
# Create request
|
65 |
transcript_request = {
|
66 |
-
|
67 |
}
|
68 |
|
69 |
# POST request
|
70 |
transcript_response = requests.post(
|
71 |
-
transcript_endpoint,
|
72 |
-
json=transcript_request,
|
73 |
-
headers=header
|
74 |
)
|
75 |
|
76 |
return transcript_response.json()
|
@@ -79,14 +74,14 @@ def request_transcript(upload_url, header):
|
|
79 |
def wait_for_completion(transcript_id, header):
|
80 |
"""Given a polling endpoint, waits for the transcription/audio analysis to complete"""
|
81 |
polling_endpoint = "https://api.assemblyai.com/v2/transcript/" + transcript_id
|
82 |
-
|
83 |
while True:
|
84 |
polling_response = requests.get(polling_endpoint, headers=header)
|
85 |
polling_response = polling_response.json()
|
86 |
|
87 |
-
if polling_response[
|
88 |
return polling_response, None
|
89 |
-
elif polling_response[
|
90 |
return None, f"Error: {polling_response['error']}"
|
91 |
|
92 |
time.sleep(5)
|
@@ -94,5 +89,5 @@ def wait_for_completion(transcript_id, header):
|
|
94 |
|
95 |
def make_paragraphs_string(transc_id, header):
|
96 |
endpoint = transcript_endpoint + "/" + transc_id + "/paragraphs"
|
97 |
-
paras = requests.get(endpoint, headers=header).json()[
|
98 |
-
return
|
9 |
|
10 |
|
11 |
def make_header(api_key):
|
12 |
+
return {"authorization": api_key, "content-type": "application/json"}
|
|
|
|
|
|
|
13 |
|
14 |
|
15 |
def _read_file(filename, chunk_size=5242880):
|
43 |
upload_response = requests.post(
|
44 |
upload_endpoint,
|
45 |
headers=header,
|
46 |
+
data=_read_file(audio_file) if is_file else _read_array(audio_file),
|
47 |
)
|
48 |
if upload_response.status_code != 200:
|
49 |
upload_response.raise_for_status()
|
56 |
|
57 |
# If input is a dict returned from `upload_file` rather than a raw upload_url string
|
58 |
if type(upload_url) is dict:
|
59 |
+
upload_url = upload_url["upload_url"]
|
60 |
|
61 |
# Create request
|
62 |
transcript_request = {
|
63 |
+
"audio_url": upload_url,
|
64 |
}
|
65 |
|
66 |
# POST request
|
67 |
transcript_response = requests.post(
|
68 |
+
transcript_endpoint, json=transcript_request, headers=header
|
|
|
|
|
69 |
)
|
70 |
|
71 |
return transcript_response.json()
|
74 |
def wait_for_completion(transcript_id, header):
|
75 |
"""Given a polling endpoint, waits for the transcription/audio analysis to complete"""
|
76 |
polling_endpoint = "https://api.assemblyai.com/v2/transcript/" + transcript_id
|
77 |
+
|
78 |
while True:
|
79 |
polling_response = requests.get(polling_endpoint, headers=header)
|
80 |
polling_response = polling_response.json()
|
81 |
|
82 |
+
if polling_response["status"] == "completed":
|
83 |
return polling_response, None
|
84 |
+
elif polling_response["status"] == "error":
|
85 |
return None, f"Error: {polling_response['error']}"
|
86 |
|
87 |
time.sleep(5)
|
89 |
|
90 |
def make_paragraphs_string(transc_id, header):
|
91 |
endpoint = transcript_endpoint + "/" + transc_id + "/paragraphs"
|
92 |
+
paras = requests.get(endpoint, headers=header).json()["paragraphs"]
|
93 |
+
return "\n\n".join(i["text"] for i in paras)
|