Kalp97 commited on
Commit
4f790c1
·
verified ·
1 Parent(s): 638594e

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +26 -141
app.py CHANGED
@@ -1,56 +1,39 @@
1
  import gradio as gr
2
  import whisper
3
- import os
4
 
5
  models = {}
6
 
7
  def load_model(model_name):
8
- global models
9
  if model_name not in models:
10
  models[model_name] = whisper.load_model(model_name)
11
  return models[model_name]
12
 
 
 
 
 
 
 
13
  def transcribe(file, model_name, language, show_timestamps, task):
14
  if file is None:
15
  return "Please upload a video or audio file.", ""
16
-
17
  try:
18
  m = load_model(model_name)
19
-
20
  lang = None if language == "Auto Detect" else language.lower()
21
-
22
- result = m.transcribe(
23
- file.name,
24
- language=lang,
25
- verbose=False,
26
- task="translate" if task == "Translate to English" else "transcribe"
27
- )
28
-
29
- # Full plain transcript
30
  plain = result["text"].strip()
31
-
32
- # Timestamped transcript
33
  if show_timestamps:
34
  lines = []
35
  for seg in result["segments"]:
36
  start = format_time(seg["start"])
37
  end = format_time(seg["end"])
38
  lines.append(f"[{start} → {end}] {seg['text'].strip()}")
39
- timestamped = "\n".join(lines)
40
- else:
41
- timestamped = plain
42
-
43
- return timestamped, plain
44
-
45
  except Exception as e:
46
  return f"Error: {str(e)}", ""
47
 
48
- def format_time(seconds):
49
- m = int(seconds // 60)
50
- s = int(seconds % 60)
51
- ms = int((seconds % 1) * 10)
52
- return f"{m:02d}:{s:02d}.{ms}"
53
-
54
  def save_transcript(text):
55
  if not text:
56
  return None
@@ -60,22 +43,17 @@ def save_transcript(text):
60
  return path
61
 
62
  custom_css = """
63
- @import url('https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=DM+Sans:opsz,wght@9..40,300;9..40,400;9..40,500&display=swap');
64
-
65
- * { box-sizing: border-box; }
66
 
67
  body, .gradio-container {
68
  background: #080808 !important;
69
  font-family: 'DM Sans', sans-serif !important;
70
  }
71
-
72
  .gradio-container {
73
  max-width: 1000px !important;
74
  margin: 0 auto !important;
75
  padding: 48px 28px 80px !important;
76
  }
77
-
78
- /* Gold bar */
79
  .gradio-container::before {
80
  content: '';
81
  display: block;
@@ -84,8 +62,6 @@ body, .gradio-container {
84
  background: #c9a96e;
85
  margin-bottom: 32px;
86
  }
87
-
88
- /* Title */
89
  .prose h1 {
90
  font-family: 'DM Serif Display', serif !important;
91
  font-size: 3rem !important;
@@ -93,30 +69,19 @@ body, .gradio-container {
93
  color: #f0ece2 !important;
94
  letter-spacing: -0.02em !important;
95
  line-height: 1.05 !important;
96
- margin-bottom: 0 !important;
97
  }
98
-
99
  .prose p {
100
  color: #555 !important;
101
  font-size: 0.9rem !important;
102
  font-weight: 300 !important;
103
  margin-top: 8px !important;
104
- letter-spacing: 0.01em !important;
105
  }
106
-
107
- /* Panels */
108
  .contain, .gap { background: transparent !important; border: none !important; }
109
-
110
  .block {
111
  background: #0f0f0f !important;
112
  border: 1px solid #1c1c1c !important;
113
  border-radius: 14px !important;
114
- transition: border-color 0.2s !important;
115
  }
116
-
117
- .block:hover { border-color: #2a2a2a !important; }
118
-
119
- /* Labels */
120
  .block label > span, label > span {
121
  font-family: 'DM Sans', sans-serif !important;
122
  font-size: 0.72rem !important;
@@ -125,18 +90,6 @@ body, .gradio-container {
125
  text-transform: uppercase !important;
126
  letter-spacing: 0.12em !important;
127
  }
128
-
129
- /* Dropdowns & selects */
130
- select, .wrap-inner, input[type="text"] {
131
- background: #0f0f0f !important;
132
- color: #c8c4bc !important;
133
- border: 1px solid #1c1c1c !important;
134
- border-radius: 10px !important;
135
- font-family: 'DM Sans', sans-serif !important;
136
- font-size: 0.88rem !important;
137
- }
138
-
139
- /* Textarea */
140
  textarea {
141
  background: transparent !important;
142
  color: #d4d0c8 !important;
@@ -145,15 +98,9 @@ textarea {
145
  line-height: 1.85 !important;
146
  font-weight: 300 !important;
147
  border: none !important;
148
- letter-spacing: 0.01em !important;
149
  }
150
-
151
  textarea::placeholder { color: #2e2e2e !important; }
152
-
153
- /* Checkbox */
154
  input[type="checkbox"] { accent-color: #c9a96e !important; }
155
-
156
- /* Primary button */
157
  button.primary {
158
  background: #c9a96e !important;
159
  border: none !important;
@@ -166,18 +113,12 @@ button.primary {
166
  text-transform: uppercase !important;
167
  padding: 14px 28px !important;
168
  transition: all 0.2s ease !important;
169
- box-shadow: 0 2px 12px rgba(201,169,110,0.15) !important;
170
  }
171
-
172
  button.primary:hover {
173
  background: #d4b87e !important;
174
  transform: translateY(-1px) !important;
175
  box-shadow: 0 6px 24px rgba(201,169,110,0.3) !important;
176
  }
177
-
178
- button.primary:active { transform: translateY(0) !important; }
179
-
180
- /* Secondary button */
181
  button.secondary {
182
  background: transparent !important;
183
  border: 1px solid #1e1e1e !important;
@@ -190,19 +131,7 @@ button.secondary {
190
  text-transform: uppercase !important;
191
  transition: all 0.2s ease !important;
192
  }
193
-
194
- button.secondary:hover {
195
- border-color: #3a3a3a !important;
196
- color: #c8c4bc !important;
197
- }
198
-
199
- /* Download button area */
200
- .file-preview {
201
- background: transparent !important;
202
- border: none !important;
203
- }
204
-
205
- /* Tabs */
206
  .tab-nav button {
207
  font-family: 'DM Sans', sans-serif !important;
208
  font-size: 0.78rem !important;
@@ -213,31 +142,13 @@ button.secondary:hover {
213
  background: transparent !important;
214
  border: none !important;
215
  border-bottom: 2px solid transparent !important;
216
- padding: 10px 16px !important;
217
  transition: all 0.2s !important;
218
  }
219
-
220
- .tab-nav button.selected {
221
- color: #c9a96e !important;
222
- border-bottom-color: #c9a96e !important;
223
- }
224
-
225
- /* Divider */
226
- .divider { border-color: #1c1c1c !important; }
227
-
228
- /* Progress */
229
- .progress-bar { background: #c9a96e !important; }
230
- .progress-bar-wrap { background: #1c1c1c !important; }
231
-
232
- /* Scrollbar */
233
  ::-webkit-scrollbar { width: 3px; }
234
  ::-webkit-scrollbar-track { background: transparent; }
235
  ::-webkit-scrollbar-thumb { background: #2a2a2a; border-radius: 4px; }
236
-
237
  footer { display: none !important; }
238
-
239
- /* Settings row */
240
- .settings-row { gap: 12px !important; }
241
  """
242
 
243
  LANGUAGES = [
@@ -246,80 +157,54 @@ LANGUAGES = [
246
  "Korean", "Arabic", "Russian", "Dutch", "Turkish"
247
  ]
248
 
249
- with gr.Blocks(css=custom_css, title="KalpTranscript") as demo:
250
-
251
  gr.Markdown("""
252
  # KalpTranscript
253
  Turn any video or audio into clean, readable text — powered by OpenAI Whisper.
254
  """)
255
 
256
  with gr.Row():
257
- # Left column - controls
258
  with gr.Column(scale=1):
259
  file_input = gr.File(
260
  label="Drop your file here",
261
  file_types=["video", "audio"]
262
  )
263
-
264
- with gr.Row(elem_classes=["settings-row"]):
265
  model_choice = gr.Dropdown(
266
  choices=["tiny", "base", "small", "medium"],
267
  value="small",
268
- label="Model",
269
- info="small = fast & accurate, medium = best quality"
270
  )
271
  language = gr.Dropdown(
272
  choices=LANGUAGES,
273
  value="Auto Detect",
274
  label="Language"
275
  )
276
-
277
- with gr.Row():
278
- task = gr.Radio(
279
- choices=["Transcribe", "Translate to English"],
280
- value="Transcribe",
281
- label="Task"
282
- )
283
-
284
- timestamps = gr.Checkbox(
285
- label="Show timestamps",
286
- value=False
287
  )
288
-
289
  with gr.Row():
290
  clear_btn = gr.ClearButton(value="Clear")
291
  submit_btn = gr.Button("Transcribe →", variant="primary")
292
 
293
- # Right column - output
294
  with gr.Column(scale=1):
295
  with gr.Tabs():
296
  with gr.Tab("Transcript"):
297
- output = gr.Textbox(
298
- label="",
299
- lines=16,
300
- placeholder="Your transcript will appear here...",
301
- show_copy_button=False
302
- )
303
  with gr.Tab("Download"):
304
- plain_output = gr.Textbox(
305
- label="Plain text (for download)",
306
- lines=10,
307
- visible=False
308
- )
309
  download_btn = gr.Button("Save as .txt", variant="secondary")
310
- download_file = gr.File(label="Download", visible=True)
311
 
312
  submit_btn.click(
313
  fn=transcribe,
314
  inputs=[file_input, model_choice, language, timestamps, task],
315
  outputs=[output, plain_output]
316
  )
317
-
318
- download_btn.click(
319
- fn=save_transcript,
320
- inputs=plain_output,
321
- outputs=download_file
322
- )
323
 
324
  if __name__ == "__main__":
325
- demo.launch()
 
1
  import gradio as gr
2
  import whisper
 
3
 
4
  models = {}
5
 
6
  def load_model(model_name):
 
7
  if model_name not in models:
8
  models[model_name] = whisper.load_model(model_name)
9
  return models[model_name]
10
 
11
+ def format_time(seconds):
12
+ m = int(seconds // 60)
13
+ s = int(seconds % 60)
14
+ ms = int((seconds % 1) * 10)
15
+ return f"{m:02d}:{s:02d}.{ms}"
16
+
17
  def transcribe(file, model_name, language, show_timestamps, task):
18
  if file is None:
19
  return "Please upload a video or audio file.", ""
 
20
  try:
21
  m = load_model(model_name)
 
22
  lang = None if language == "Auto Detect" else language.lower()
23
+ whisper_task = "translate" if task == "Translate to English" else "transcribe"
24
+ result = m.transcribe(file.name, language=lang, verbose=False, task=whisper_task)
 
 
 
 
 
 
 
25
  plain = result["text"].strip()
 
 
26
  if show_timestamps:
27
  lines = []
28
  for seg in result["segments"]:
29
  start = format_time(seg["start"])
30
  end = format_time(seg["end"])
31
  lines.append(f"[{start} → {end}] {seg['text'].strip()}")
32
+ return "\n".join(lines), plain
33
+ return plain, plain
 
 
 
 
34
  except Exception as e:
35
  return f"Error: {str(e)}", ""
36
 
 
 
 
 
 
 
37
  def save_transcript(text):
38
  if not text:
39
  return None
 
43
  return path
44
 
45
  custom_css = """
46
+ @import url('https://fonts.googleapis.com/css2?family=DM+Serif+Display&family=DM+Sans:wght@300;400;500&display=swap');
 
 
47
 
48
  body, .gradio-container {
49
  background: #080808 !important;
50
  font-family: 'DM Sans', sans-serif !important;
51
  }
 
52
  .gradio-container {
53
  max-width: 1000px !important;
54
  margin: 0 auto !important;
55
  padding: 48px 28px 80px !important;
56
  }
 
 
57
  .gradio-container::before {
58
  content: '';
59
  display: block;
 
62
  background: #c9a96e;
63
  margin-bottom: 32px;
64
  }
 
 
65
  .prose h1 {
66
  font-family: 'DM Serif Display', serif !important;
67
  font-size: 3rem !important;
 
69
  color: #f0ece2 !important;
70
  letter-spacing: -0.02em !important;
71
  line-height: 1.05 !important;
 
72
  }
 
73
  .prose p {
74
  color: #555 !important;
75
  font-size: 0.9rem !important;
76
  font-weight: 300 !important;
77
  margin-top: 8px !important;
 
78
  }
 
 
79
  .contain, .gap { background: transparent !important; border: none !important; }
 
80
  .block {
81
  background: #0f0f0f !important;
82
  border: 1px solid #1c1c1c !important;
83
  border-radius: 14px !important;
 
84
  }
 
 
 
 
85
  .block label > span, label > span {
86
  font-family: 'DM Sans', sans-serif !important;
87
  font-size: 0.72rem !important;
 
90
  text-transform: uppercase !important;
91
  letter-spacing: 0.12em !important;
92
  }
 
 
 
 
 
 
 
 
 
 
 
 
93
  textarea {
94
  background: transparent !important;
95
  color: #d4d0c8 !important;
 
98
  line-height: 1.85 !important;
99
  font-weight: 300 !important;
100
  border: none !important;
 
101
  }
 
102
  textarea::placeholder { color: #2e2e2e !important; }
 
 
103
  input[type="checkbox"] { accent-color: #c9a96e !important; }
 
 
104
  button.primary {
105
  background: #c9a96e !important;
106
  border: none !important;
 
113
  text-transform: uppercase !important;
114
  padding: 14px 28px !important;
115
  transition: all 0.2s ease !important;
 
116
  }
 
117
  button.primary:hover {
118
  background: #d4b87e !important;
119
  transform: translateY(-1px) !important;
120
  box-shadow: 0 6px 24px rgba(201,169,110,0.3) !important;
121
  }
 
 
 
 
122
  button.secondary {
123
  background: transparent !important;
124
  border: 1px solid #1e1e1e !important;
 
131
  text-transform: uppercase !important;
132
  transition: all 0.2s ease !important;
133
  }
134
+ button.secondary:hover { border-color: #3a3a3a !important; color: #c8c4bc !important; }
 
 
 
 
 
 
 
 
 
 
 
 
135
  .tab-nav button {
136
  font-family: 'DM Sans', sans-serif !important;
137
  font-size: 0.78rem !important;
 
142
  background: transparent !important;
143
  border: none !important;
144
  border-bottom: 2px solid transparent !important;
 
145
  transition: all 0.2s !important;
146
  }
147
+ .tab-nav button.selected { color: #c9a96e !important; border-bottom-color: #c9a96e !important; }
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  ::-webkit-scrollbar { width: 3px; }
149
  ::-webkit-scrollbar-track { background: transparent; }
150
  ::-webkit-scrollbar-thumb { background: #2a2a2a; border-radius: 4px; }
 
151
  footer { display: none !important; }
 
 
 
152
  """
153
 
154
  LANGUAGES = [
 
157
  "Korean", "Arabic", "Russian", "Dutch", "Turkish"
158
  ]
159
 
160
+ with gr.Blocks(title="KalpTranscript") as demo:
 
161
  gr.Markdown("""
162
  # KalpTranscript
163
  Turn any video or audio into clean, readable text — powered by OpenAI Whisper.
164
  """)
165
 
166
  with gr.Row():
 
167
  with gr.Column(scale=1):
168
  file_input = gr.File(
169
  label="Drop your file here",
170
  file_types=["video", "audio"]
171
  )
172
+ with gr.Row():
 
173
  model_choice = gr.Dropdown(
174
  choices=["tiny", "base", "small", "medium"],
175
  value="small",
176
+ label="Model"
 
177
  )
178
  language = gr.Dropdown(
179
  choices=LANGUAGES,
180
  value="Auto Detect",
181
  label="Language"
182
  )
183
+ task = gr.Radio(
184
+ choices=["Transcribe", "Translate to English"],
185
+ value="Transcribe",
186
+ label="Task"
 
 
 
 
 
 
 
187
  )
188
+ timestamps = gr.Checkbox(label="Show timestamps", value=False)
189
  with gr.Row():
190
  clear_btn = gr.ClearButton(value="Clear")
191
  submit_btn = gr.Button("Transcribe →", variant="primary")
192
 
 
193
  with gr.Column(scale=1):
194
  with gr.Tabs():
195
  with gr.Tab("Transcript"):
196
+ output = gr.Textbox(label="", lines=16, placeholder="Your transcript will appear here...")
 
 
 
 
 
197
  with gr.Tab("Download"):
198
+ plain_output = gr.Textbox(label="Plain text", lines=10, visible=False)
 
 
 
 
199
  download_btn = gr.Button("Save as .txt", variant="secondary")
200
+ download_file = gr.File(label="Download")
201
 
202
  submit_btn.click(
203
  fn=transcribe,
204
  inputs=[file_input, model_choice, language, timestamps, task],
205
  outputs=[output, plain_output]
206
  )
207
+ download_btn.click(fn=save_transcript, inputs=plain_output, outputs=download_file)
 
 
 
 
 
208
 
209
  if __name__ == "__main__":
210
+ demo.launch(css=custom_css)