File size: 2,992 Bytes
9e1e4ee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4d18ab0
a60f44b
 
 
 
ef76c0c
a60f44b
 
 
 
 
 
 
 
 
ef76c0c
4d18ab0
ef76c0c
4d18ab0
 
 
 
 
 
 
 
 
ef76c0c
4d18ab0
 
ef76c0c
 
4d18ab0
 
ef76c0c
4d18ab0
9e1e4ee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# backend/models.py

from dataclasses import dataclass
from typing import Any, Optional

# Model name mapping for anonymization
# Maps internal model names to display labels
MODEL_NAME_MAP = {
    "xtts": "Model A",     # Coqui XTTS -> Model A
    "csm": "Model B",      # Sesame CSM -> Model B
    "orpheus": "Model C",  # Orpheus -> Model C
}


def get_display_model_name(internal_name: str) -> str:
    """Convert internal model name to display label."""
    return MODEL_NAME_MAP.get(internal_name, internal_name.upper())


def audio_to_base64_url(audio_data):
    """Convert audio data to base64 URL for HTML audio elements."""
    if isinstance(audio_data, str):
        if audio_data.startswith("data:audio/"):
            return audio_data
        elif audio_data.endswith(('.wav', '.mp3', '.flac', '.ogg')):
            # Handle file path from LFS - convert to base64
            try:
                import base64
                import os
                if os.path.exists(audio_data):
                    with open(audio_data, "rb") as f:
                        audio_bytes = f.read()
                    b64 = base64.b64encode(audio_bytes).decode("ascii")
                    return f"data:audio/wav;base64,{b64}"
            except Exception as e:
                print(f"[WARN] Failed to convert file to base64 URL: {e}")
    elif isinstance(audio_data, tuple) and len(audio_data) == 2:
        # Convert (array, sample_rate) tuple to base64 URL
        try:
            import numpy as np
            import base64
            import io
            try:
                import soundfile as sf
            except ImportError:
                return None
                
            array, sr = audio_data
            if sf is not None:
                buf = io.BytesIO()
                sf.write(buf, np.array(array), int(sr), format="WAV")
                b64 = base64.b64encode(buf.getvalue()).decode("ascii")
                return f"data:audio/wav;base64,{b64}"
        except Exception as e:
            print(f"[WARN] Failed to convert audio tuple to base64 URL: {e}")
    return None


# Data models
@dataclass
class Clip:
    id: str
    model: str
    speaker: str  # male/female
    exercise: str
    exercise_id: str
    transcript: str
    audio_url: Any  # Can be string URL or tuple (array, sample_rate)
    duration_s: Optional[float] = None


@dataclass
class MOSResponse:
    session_id: str
    clip_id: str
    clarity: int
    pronunciation: int
    prosody: int
    naturalness: int
    overall: int
    comment: str = ""
    gender_mismatch: bool = False  # Flag for wrong gender voice


@dataclass
class ABResponse:
    session_id: str
    clip_a_id: str
    clip_b_id: str
    comparison_type: str  # "model_vs_model" or "gender_vs_gender"
    choice: str  # "A", "B", "tie"
    comment: str = ""
    gender_mismatch_a: bool = False  # Flag for wrong gender voice in clip A
    gender_mismatch_b: bool = False  # Flag for wrong gender voice in clip B