Spaces:
Sleeping
Sleeping
last commit
Browse files
app.py
CHANGED
@@ -65,16 +65,25 @@ def validate_audio_duration(audio_file):
|
|
65 |
def start_recording():
|
66 |
"""Function yang dipanggil ketika tombol record ditekan"""
|
67 |
print("ποΈ Recording started...")
|
68 |
-
return
|
|
|
|
|
|
|
69 |
|
70 |
def stop_recording(audio):
|
71 |
"""Function yang dipanggil ketika recording selesai"""
|
72 |
if audio is not None:
|
73 |
print("β
Recording completed!")
|
74 |
-
return
|
|
|
|
|
|
|
75 |
else:
|
76 |
print("β No audio recorded")
|
77 |
-
return
|
|
|
|
|
|
|
78 |
|
79 |
def test_microphone():
|
80 |
"""Function untuk test microphone"""
|
@@ -83,7 +92,10 @@ def test_microphone():
|
|
83 |
|
84 |
def reset_recording_status():
|
85 |
"""Function untuk reset status recording"""
|
86 |
-
return
|
|
|
|
|
|
|
87 |
|
88 |
def handle_audio(audio_file):
|
89 |
"""Handle audio processing - returns (validation_message, transcript, soap, tags)"""
|
@@ -149,7 +161,7 @@ def toggle_inputs_with_refresh(choice):
|
|
149 |
gr.update(visible=(choice == "Realtime Recording")), # validasi realtime
|
150 |
gr.update(visible=(choice == "Input Teks")), # validasi teks
|
151 |
gr.update(visible=(choice == "Realtime Recording")), # recording status group
|
152 |
-
gr.update(visible=(choice == "Realtime Recording")), # record audio group
|
153 |
gr.update(value=""), # transcript
|
154 |
gr.update(value=""), # soap
|
155 |
gr.update(value=""), # tags
|
@@ -167,6 +179,7 @@ def clear_all_data():
|
|
167 |
gr.update(value=""), # transcript_output
|
168 |
gr.update(value=""), # soap_output
|
169 |
gr.update(value=""), # tags_output
|
|
|
170 |
)
|
171 |
|
172 |
def process_data(choice, audio_upload, audio_record, text_input):
|
@@ -215,7 +228,7 @@ def process_data(choice, audio_upload, audio_record, text_input):
|
|
215 |
# Default case - clear all
|
216 |
return ("", "", "", "", "", "")
|
217 |
|
218 |
-
# Custom CSS untuk tampilan modern dengan alignment yang diperbaiki
|
219 |
modern_css = """
|
220 |
<style>
|
221 |
/* Background gradient yang modern */
|
@@ -266,7 +279,7 @@ modern_css = """
|
|
266 |
border: 1px solid rgba(255,255,255,0.2);
|
267 |
}
|
268 |
|
269 |
-
/* Record audio section with padding */
|
270 |
.record-audio-section {
|
271 |
background: rgba(255, 255, 255, 0.95);
|
272 |
border-radius: 20px;
|
@@ -275,6 +288,21 @@ modern_css = """
|
|
275 |
box-shadow: 0 8px 32px rgba(0,0,0,0.1);
|
276 |
backdrop-filter: blur(10px);
|
277 |
border: 1px solid rgba(255,255,255,0.2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
}
|
279 |
|
280 |
/* Output header styling - aligned properly */
|
@@ -479,6 +507,39 @@ modern_css = """
|
|
479 |
.recording-active {
|
480 |
animation: pulse 1s infinite;
|
481 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
482 |
</style>
|
483 |
"""
|
484 |
|
@@ -498,7 +559,7 @@ with gr.Blocks(
|
|
498 |
gr.HTML("""
|
499 |
<div class="main-header">
|
500 |
<h1>ποΈ Realtime Recording</h1>
|
501 |
-
<p>High Quality Audio Recording</p>
|
502 |
</div>
|
503 |
""")
|
504 |
|
@@ -533,8 +594,9 @@ with gr.Blocks(
|
|
533 |
elem_classes=["audio-input"]
|
534 |
)
|
535 |
|
536 |
-
# Input Section - Record Audio with proper padding
|
537 |
-
|
|
|
538 |
gr.HTML("<h3>π΅ Record Your Audio</h3>")
|
539 |
|
540 |
audio_record = gr.Audio(
|
@@ -640,7 +702,7 @@ with gr.Blocks(
|
|
640 |
input_choice.change(
|
641 |
fn=lambda choice: (
|
642 |
gr.update(visible=(choice == "Upload Audio")), # upload_audio_group
|
643 |
-
gr.update(visible=(choice == "Realtime Recording")), # record_audio_group
|
644 |
gr.update(visible=(choice == "Input Teks")), # text_input_group
|
645 |
gr.update(visible=(choice == "Upload Audio")), # validation_upload
|
646 |
gr.update(visible=(choice == "Realtime Recording")), # validation_realtime
|
@@ -665,16 +727,16 @@ with gr.Blocks(
|
|
665 |
],
|
666 |
)
|
667 |
|
668 |
-
# Event handlers untuk recording
|
669 |
audio_record.start_recording(
|
670 |
fn=start_recording,
|
671 |
-
outputs=recording_status
|
672 |
)
|
673 |
|
674 |
audio_record.stop_recording(
|
675 |
fn=stop_recording,
|
676 |
inputs=audio_record,
|
677 |
-
outputs=recording_status
|
678 |
)
|
679 |
|
680 |
clear_button.click(
|
@@ -690,6 +752,7 @@ with gr.Blocks(
|
|
690 |
transcript_output,
|
691 |
soap_output,
|
692 |
tags_output,
|
|
|
693 |
],
|
694 |
)
|
695 |
|
@@ -709,7 +772,7 @@ with gr.Blocks(
|
|
709 |
|
710 |
# Startup information
|
711 |
if __name__ == "__main__":
|
712 |
-
print("π Starting Enhanced SOAP AI Application
|
713 |
print("π Setup Instructions:")
|
714 |
print("1. Install dependencies: pip install gradio pydub nltk requests python-dotenv")
|
715 |
print("2. Make sure wordlist.lst file is available")
|
@@ -718,7 +781,7 @@ if __name__ == "__main__":
|
|
718 |
|
719 |
print("\nπ Application will start at: http://localhost:7860")
|
720 |
print("ποΈ Make sure to allow microphone access when using Realtime Recording!")
|
721 |
-
print("
|
722 |
print()
|
723 |
|
724 |
app.launch()
|
|
|
65 |
def start_recording():
|
66 |
"""Function yang dipanggil ketika tombol record ditekan"""
|
67 |
print("ποΈ Recording started...")
|
68 |
+
return (
|
69 |
+
"ποΈ Sedang merekam... Klik stop untuk menyelesaikan",
|
70 |
+
gr.update(elem_classes=["record-audio-section", "recording-active"]) # Add red border
|
71 |
+
)
|
72 |
|
73 |
def stop_recording(audio):
|
74 |
"""Function yang dipanggil ketika recording selesai"""
|
75 |
if audio is not None:
|
76 |
print("β
Recording completed!")
|
77 |
+
return (
|
78 |
+
"β
Recording selesai! Audio siap diproses",
|
79 |
+
gr.update(elem_classes=["record-audio-section", "recording-completed"]) # Add blue border
|
80 |
+
)
|
81 |
else:
|
82 |
print("β No audio recorded")
|
83 |
+
return (
|
84 |
+
"β Tidak ada audio yang direkam",
|
85 |
+
gr.update(elem_classes=["record-audio-section"]) # Reset to default
|
86 |
+
)
|
87 |
|
88 |
def test_microphone():
|
89 |
"""Function untuk test microphone"""
|
|
|
92 |
|
93 |
def reset_recording_status():
|
94 |
"""Function untuk reset status recording"""
|
95 |
+
return (
|
96 |
+
"π± Siap untuk merekam - Klik tombol record",
|
97 |
+
gr.update(elem_classes=["record-audio-section"]) # Reset to default
|
98 |
+
)
|
99 |
|
100 |
def handle_audio(audio_file):
|
101 |
"""Handle audio processing - returns (validation_message, transcript, soap, tags)"""
|
|
|
161 |
gr.update(visible=(choice == "Realtime Recording")), # validasi realtime
|
162 |
gr.update(visible=(choice == "Input Teks")), # validasi teks
|
163 |
gr.update(visible=(choice == "Realtime Recording")), # recording status group
|
164 |
+
gr.update(visible=(choice == "Realtime Recording"), elem_classes=["record-audio-section"]), # record audio group with reset border
|
165 |
gr.update(value=""), # transcript
|
166 |
gr.update(value=""), # soap
|
167 |
gr.update(value=""), # tags
|
|
|
179 |
gr.update(value=""), # transcript_output
|
180 |
gr.update(value=""), # soap_output
|
181 |
gr.update(value=""), # tags_output
|
182 |
+
gr.update(elem_classes=["record-audio-section"]), # reset record audio group border
|
183 |
)
|
184 |
|
185 |
def process_data(choice, audio_upload, audio_record, text_input):
|
|
|
228 |
# Default case - clear all
|
229 |
return ("", "", "", "", "", "")
|
230 |
|
231 |
+
# Custom CSS untuk tampilan modern dengan alignment yang diperbaiki dan border dinamis
|
232 |
modern_css = """
|
233 |
<style>
|
234 |
/* Background gradient yang modern */
|
|
|
279 |
border: 1px solid rgba(255,255,255,0.2);
|
280 |
}
|
281 |
|
282 |
+
/* Record audio section with padding - default state */
|
283 |
.record-audio-section {
|
284 |
background: rgba(255, 255, 255, 0.95);
|
285 |
border-radius: 20px;
|
|
|
288 |
box-shadow: 0 8px 32px rgba(0,0,0,0.1);
|
289 |
backdrop-filter: blur(10px);
|
290 |
border: 1px solid rgba(255,255,255,0.2);
|
291 |
+
transition: all 0.3s ease;
|
292 |
+
}
|
293 |
+
|
294 |
+
/* Recording active state - RED border */
|
295 |
+
.record-audio-section.recording-active {
|
296 |
+
border: 3px solid #ff4757 !important;
|
297 |
+
box-shadow: 0 8px 32px rgba(255, 71, 87, 0.3), 0 0 20px rgba(255, 71, 87, 0.2) !important;
|
298 |
+
background: rgba(255, 245, 245, 0.98) !important;
|
299 |
+
}
|
300 |
+
|
301 |
+
/* Recording completed state - BLUE border */
|
302 |
+
.record-audio-section.recording-completed {
|
303 |
+
border: 3px solid #3742fa !important;
|
304 |
+
box-shadow: 0 8px 32px rgba(55, 66, 250, 0.3), 0 0 20px rgba(55, 66, 250, 0.2) !important;
|
305 |
+
background: rgba(245, 245, 255, 0.98) !important;
|
306 |
}
|
307 |
|
308 |
/* Output header styling - aligned properly */
|
|
|
507 |
.recording-active {
|
508 |
animation: pulse 1s infinite;
|
509 |
}
|
510 |
+
|
511 |
+
/* Border glow animation for recording states */
|
512 |
+
@keyframes redGlow {
|
513 |
+
0% {
|
514 |
+
box-shadow: 0 8px 32px rgba(255, 71, 87, 0.3), 0 0 20px rgba(255, 71, 87, 0.2);
|
515 |
+
}
|
516 |
+
50% {
|
517 |
+
box-shadow: 0 8px 32px rgba(255, 71, 87, 0.5), 0 0 30px rgba(255, 71, 87, 0.4);
|
518 |
+
}
|
519 |
+
100% {
|
520 |
+
box-shadow: 0 8px 32px rgba(255, 71, 87, 0.3), 0 0 20px rgba(255, 71, 87, 0.2);
|
521 |
+
}
|
522 |
+
}
|
523 |
+
|
524 |
+
@keyframes blueGlow {
|
525 |
+
0% {
|
526 |
+
box-shadow: 0 8px 32px rgba(55, 66, 250, 0.3), 0 0 20px rgba(55, 66, 250, 0.2);
|
527 |
+
}
|
528 |
+
50% {
|
529 |
+
box-shadow: 0 8px 32px rgba(55, 66, 250, 0.5), 0 0 30px rgba(55, 66, 250, 0.4);
|
530 |
+
}
|
531 |
+
100% {
|
532 |
+
box-shadow: 0 8px 32px rgba(55, 66, 250, 0.3), 0 0 20px rgba(55, 66, 250, 0.2);
|
533 |
+
}
|
534 |
+
}
|
535 |
+
|
536 |
+
.record-audio-section.recording-active {
|
537 |
+
animation: redGlow 2s infinite ease-in-out;
|
538 |
+
}
|
539 |
+
|
540 |
+
.record-audio-section.recording-completed {
|
541 |
+
animation: blueGlow 2s infinite ease-in-out;
|
542 |
+
}
|
543 |
</style>
|
544 |
"""
|
545 |
|
|
|
559 |
gr.HTML("""
|
560 |
<div class="main-header">
|
561 |
<h1>ποΈ Realtime Recording</h1>
|
562 |
+
<p>High Quality Audio Recording with Smart Visual Feedback</p>
|
563 |
</div>
|
564 |
""")
|
565 |
|
|
|
594 |
elem_classes=["audio-input"]
|
595 |
)
|
596 |
|
597 |
+
# Input Section - Record Audio with proper padding and dynamic border
|
598 |
+
record_audio_group = gr.Group(elem_classes=["record-audio-section"], visible=True)
|
599 |
+
with record_audio_group:
|
600 |
gr.HTML("<h3>π΅ Record Your Audio</h3>")
|
601 |
|
602 |
audio_record = gr.Audio(
|
|
|
702 |
input_choice.change(
|
703 |
fn=lambda choice: (
|
704 |
gr.update(visible=(choice == "Upload Audio")), # upload_audio_group
|
705 |
+
gr.update(visible=(choice == "Realtime Recording"), elem_classes=["record-audio-section"]), # record_audio_group with reset border
|
706 |
gr.update(visible=(choice == "Input Teks")), # text_input_group
|
707 |
gr.update(visible=(choice == "Upload Audio")), # validation_upload
|
708 |
gr.update(visible=(choice == "Realtime Recording")), # validation_realtime
|
|
|
727 |
],
|
728 |
)
|
729 |
|
730 |
+
# Event handlers untuk recording dengan border dynamics
|
731 |
audio_record.start_recording(
|
732 |
fn=start_recording,
|
733 |
+
outputs=[recording_status, record_audio_group]
|
734 |
)
|
735 |
|
736 |
audio_record.stop_recording(
|
737 |
fn=stop_recording,
|
738 |
inputs=audio_record,
|
739 |
+
outputs=[recording_status, record_audio_group]
|
740 |
)
|
741 |
|
742 |
clear_button.click(
|
|
|
752 |
transcript_output,
|
753 |
soap_output,
|
754 |
tags_output,
|
755 |
+
record_audio_group, # Reset border when clearing
|
756 |
],
|
757 |
)
|
758 |
|
|
|
772 |
|
773 |
# Startup information
|
774 |
if __name__ == "__main__":
|
775 |
+
print("π Starting Enhanced SOAP AI Application...")
|
776 |
print("π Setup Instructions:")
|
777 |
print("1. Install dependencies: pip install gradio pydub nltk requests python-dotenv")
|
778 |
print("2. Make sure wordlist.lst file is available")
|
|
|
781 |
|
782 |
print("\nπ Application will start at: http://localhost:7860")
|
783 |
print("ποΈ Make sure to allow microphone access when using Realtime Recording!")
|
784 |
+
print("π Visual feedback provided through dynamic border colors during recording")
|
785 |
print()
|
786 |
|
787 |
app.launch()
|