MeysamSh's picture
First working version
64862fd
import gradio as gr
import pandas as pd
import os
import hashlib
from datasets import Dataset, concatenate_datasets, load_dataset
from huggingface_hub import login
# ============================
# CONFIGURATION
# ============================
AUDIO_FOLDER = "audio_files"
audio_files = sorted(os.listdir(AUDIO_FOLDER))
ADMIN_PASSWORD_HASH = "eb32da077dfaf326cd6f73e0716b628da6427aa318a2d0b9fafa9ef315b5e885"
# ============================
# HF DATASET CONFIGURATION
# ============================
HF_DATASET_NAME = "MeysamSh/Annotate_Samples" # replace with your HF dataset
HF_TOKEN = os.environ.get("HF_TOKEN") # store your token as a secret in Spaces
login(HF_TOKEN)
# ============================
# USER FUNCTIONS
# ============================
def load_hf_dataset():
"""Load existing HF Dataset or create empty one if not exists."""
try:
ds = load_dataset(HF_DATASET_NAME, split="train")
except:
# Dataset does not exist yet
df = pd.DataFrame(columns=["user_id", "gender", "audio_file", "score"])
ds = Dataset.from_pandas(df)
ds.push_to_hub(HF_DATASET_NAME, private=True)
return ds
def submit_annotation_hf(user_id, gender, score, audio_file):
"""Append annotation to HF Dataset."""
ds = load_hf_dataset()
new_row = pd.DataFrame([{
"user_id": user_id,
"gender": gender,
"audio_file": audio_file,
"score": score
}])
ds_new = Dataset.from_pandas(new_row)
ds_combined = concatenate_datasets([ds, ds_new])
ds_combined.push_to_hub(HF_DATASET_NAME)
def load_next_audio(state):
if state is None:
state = {"index": 0}
idx = state["index"]
if idx >= len(audio_files):
return None, state, {"played": 0}, "All audio files annotated."
filepath = os.path.join(AUDIO_FOLDER, audio_files[idx])
return filepath, state, {"played": 0}, f"Loaded {audio_files[idx]}"
def submit_annotation(user_id, gender, score, state):
if state is None:
state = {"index": 0}
idx = state["index"]
if idx >= len(audio_files):
return state, "No more audio files."
audio_file = audio_files[idx]
submit_annotation_hf(user_id, gender, score, audio_file)
state["index"] += 1
return state, f"Saved rating for {audio_file}."
# ============================
# SUBMIT BUTTON CONTROL
# ============================
def check_submit_ready(user_id, audio_played, score):
ready = len(user_id.strip()) > 1 and audio_played['played'] == 1 and score != "None"
return gr.update(interactive=ready)
def mark_audio_played():
return {"played": 1}
# ============================
# ADMIN FUNCTIONS
# ============================
def hash_password(password: str) -> str:
return hashlib.sha256(password.encode()).hexdigest()
def admin_login(input_password):
if hash_password(input_password) == ADMIN_PASSWORD_HASH:
ds = load_hf_dataset()
df = ds.to_pandas()
# For download: write temp CSV
temp_csv = "annotations_export.csv"
df.to_csv(temp_csv, index=False)
return (
gr.update(visible=True),
df,
temp_csv,
gr.update(value="Admin authentication successful.")
)
else:
return (
gr.update(visible=False),
None,
None,
gr.update(value="Admin authentication failed.")
)
# ============================
# GRADIO UI
# ============================
with gr.Blocks() as demo:
gr.Markdown("# Audio MOS Annotation Tool")
# --------------------------
# USER SECTION
# --------------------------
state = gr.State({"index": 0})
audio_played = gr.State({"played": 0})
with gr.Row():
user_id = gr.Textbox(label="User ID")
gender = gr.Dropdown(["Male", "Female", "Other"], label="Gender", value="Other")
audio_player = gr.Audio(label="Audio File")
with gr.Row():
score = gr.Dropdown(choices=["None","1", "2", "3", "4", "5"], value="None", label="MOS Score (1–5)")
submit_btn = gr.Button("Submit Score", interactive=False)
status = gr.Textbox(label="Status", interactive=False)
# Load first audio
demo.load(
load_next_audio,
inputs=state,
outputs=[audio_player, state, audio_played, status]
)
# Mark audio as played
audio_player.play(
mark_audio_played,
None,
audio_played
)
# Enable submit button only when conditions are met
user_id.change(
check_submit_ready,
inputs=[user_id, audio_played, score],
outputs=submit_btn
)
audio_played.change(
check_submit_ready,
inputs=[user_id, audio_played, score],
outputs=submit_btn
)
score.change(
check_submit_ready,
inputs=[user_id, audio_played, score],
outputs=submit_btn
)
# Save annotation
submit_btn.click(
submit_annotation,
inputs=[user_id, gender, score, state],
outputs=[state, status]
)
# Load next audio
submit_btn.click(
load_next_audio,
inputs=state,
outputs=[audio_player, state, audio_played, status]
)
# ============================
# ADMIN DASHBOARD
# ============================
gr.Markdown("## Admin Dashboard (Restricted Access)")
with gr.Row():
admin_password = gr.Textbox(label="Admin Password", type="password")
admin_login_btn = gr.Button("Login")
login_status = gr.Textbox(label="Login Status:", interactive=False)
with gr.Column(visible=False) as admin_panel:
gr.Markdown("### Annotation Results")
pd_loaded=load_hf_dataset().to_pandas()
results_table = gr.DataFrame(interactive=False, value=pd_loaded)
pd_loaded.to_csv("annotations_export.csv", index=False)
download_admin = gr.File(label="Download annotations.csv", value="annotations_export.csv")
admin_login_btn.click(
admin_login,
inputs=admin_password,
outputs=[admin_panel, results_table, download_admin, login_status]
)
# ============================
# APP LAUNCH
# ============================
if __name__ == "__main__":
demo.launch()