XUUUUSID commited on
Commit
f1178ae
Β·
verified Β·
1 Parent(s): 2bbabf0

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +166 -0
app.py ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Audio Recording Spreadsheet β€” Hugging Face Spaces (Gradio)
3
+
4
+ Record audio from your browser, give it a name, and it gets logged
5
+ in an interactive table. Download all recordings or the full Excel log.
6
+ """
7
+
8
+ import gradio as gr
9
+ import pandas as pd
10
+ import shutil
11
+ import json
12
+ import os
13
+ from datetime import datetime
14
+
15
+ DATA_DIR = "recordings"
16
+ META_FILE = os.path.join(DATA_DIR, "metadata.json")
17
+ os.makedirs(DATA_DIR, exist_ok=True)
18
+
19
+
20
+ # ── Metadata persistence ────────────────────────────────────────
21
+
22
+ def load_meta():
23
+ if os.path.exists(META_FILE):
24
+ with open(META_FILE, "r") as f:
25
+ return json.load(f)
26
+ return []
27
+
28
+
29
+ def save_meta(entries):
30
+ with open(META_FILE, "w") as f:
31
+ json.dump(entries, f, indent=2, ensure_ascii=False)
32
+
33
+
34
+ # ── Core actions ────────────────────────────────────────────────
35
+
36
+ def save_recording(audio_path, name):
37
+ if audio_path is None:
38
+ gr.Warning("Please record audio first.")
39
+ return None, refresh_table(), gr.update()
40
+
41
+ name = name.strip() or f"Recording_{datetime.now():%Y%m%d_%H%M%S}"
42
+ ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
43
+ filename = f"{name.replace(' ', '_')}_{datetime.now():%Y%m%d_%H%M%S}.wav"
44
+ dest = os.path.join(DATA_DIR, filename)
45
+ shutil.copy2(audio_path, dest)
46
+
47
+ entries = load_meta()
48
+ entries.append({"name": name, "timestamp": ts, "file": filename})
49
+ save_meta(entries)
50
+
51
+ gr.Info(f"Saved: {name}")
52
+ return None, refresh_table(), gr.update(value=None)
53
+
54
+
55
+ def refresh_table():
56
+ entries = load_meta()
57
+ if not entries:
58
+ return pd.DataFrame(columns=["#", "Name", "Timestamp", "File"])
59
+ rows = [
60
+ {"#": i, "Name": e["name"], "Timestamp": e["timestamp"], "File": e["file"]}
61
+ for i, e in enumerate(entries, 1)
62
+ ]
63
+ return pd.DataFrame(rows)
64
+
65
+
66
+ def play_selected(evt: gr.SelectData):
67
+ """When a row is clicked, return its audio for playback."""
68
+ entries = load_meta()
69
+ row = evt.index[0]
70
+ if row < len(entries):
71
+ path = os.path.join(DATA_DIR, entries[row]["file"])
72
+ if os.path.exists(path):
73
+ return path
74
+ return None
75
+
76
+
77
+ def export_excel():
78
+ entries = load_meta()
79
+ if not entries:
80
+ gr.Warning("No recordings to export.")
81
+ return None
82
+ df = pd.DataFrame(entries)
83
+ path = os.path.join(DATA_DIR, "recordings_export.xlsx")
84
+ df.to_excel(path, index=False)
85
+ return path
86
+
87
+
88
+ def delete_selected(evt: gr.SelectData):
89
+ """Delete recording by clicking the table then pressing Delete."""
90
+ entries = load_meta()
91
+ row = evt.index[0]
92
+ if row < len(entries):
93
+ entry = entries.pop(row)
94
+ path = os.path.join(DATA_DIR, entry["file"])
95
+ if os.path.exists(path):
96
+ os.remove(path)
97
+ save_meta(entries)
98
+ gr.Info(f"Deleted: {entry['name']}")
99
+ return refresh_table(), None
100
+
101
+
102
+ # ── UI ──────────────────────────────────────────────────────────
103
+
104
+ with gr.Blocks(title="Audio Recording Sheet", theme=gr.themes.Soft()) as demo:
105
+ gr.Markdown("## Audio Recording Sheet\nRecord, name, and organise your audio notes.")
106
+
107
+ with gr.Row():
108
+ with gr.Column(scale=1):
109
+ name_input = gr.Textbox(label="Recording Name", placeholder="e.g. Interview – Session 3")
110
+ audio_input = gr.Audio(sources=["microphone"], type="filepath", label="Record Audio")
111
+ save_btn = gr.Button("Save Recording", variant="primary")
112
+
113
+ with gr.Column(scale=2):
114
+ table = gr.Dataframe(
115
+ value=refresh_table(),
116
+ label="Recordings",
117
+ interactive=False,
118
+ height=400,
119
+ )
120
+ playback = gr.Audio(label="Playback", interactive=False)
121
+
122
+ with gr.Row():
123
+ refresh_btn = gr.Button("Refresh Table")
124
+ export_btn = gr.Button("Export to Excel")
125
+ delete_btn = gr.Button("Delete Selected", variant="stop")
126
+ excel_file = gr.File(label="Download Excel", visible=True)
127
+
128
+ # ── Wiring ──────────────────────────────────────────────
129
+ selected_row = gr.State(None)
130
+
131
+ save_btn.click(
132
+ fn=save_recording,
133
+ inputs=[audio_input, name_input],
134
+ outputs=[name_input, table, audio_input],
135
+ )
136
+
137
+ refresh_btn.click(fn=refresh_table, outputs=[table])
138
+
139
+ table.select(fn=play_selected, outputs=[playback])
140
+
141
+ export_btn.click(fn=export_excel, outputs=[excel_file])
142
+
143
+ # For delete we need the last selected row β€” store it via select event
144
+ def store_and_play(evt: gr.SelectData):
145
+ audio = play_selected(evt)
146
+ return evt.index[0], audio
147
+
148
+ table.select(fn=store_and_play, outputs=[selected_row, playback])
149
+
150
+ def do_delete(row_idx):
151
+ if row_idx is None:
152
+ gr.Warning("Click a row first.")
153
+ return refresh_table(), None
154
+ entries = load_meta()
155
+ if row_idx < len(entries):
156
+ entry = entries.pop(row_idx)
157
+ path = os.path.join(DATA_DIR, entry["file"])
158
+ if os.path.exists(path):
159
+ os.remove(path)
160
+ save_meta(entries)
161
+ gr.Info(f"Deleted: {entry['name']}")
162
+ return refresh_table(), None
163
+
164
+ delete_btn.click(fn=do_delete, inputs=[selected_row], outputs=[table, playback])
165
+
166
+ demo.launch()