package speaker import ( "fmt" "os" "path/filepath" "strings" "gopkg.in/yaml.v3" ) // Map resolves input file basenames to canonical speaker names. type Map struct { inputs map[string]Input } // Input describes one input entry in speakers.yml. type Input struct { Speaker string `yaml:"speaker"` } type fileSchema struct { Inputs map[string]Input `yaml:"inputs"` } // LoadMap parses a speakers.yml file. func LoadMap(path string) (Map, error) { data, err := os.ReadFile(path) if err != nil { return Map{}, err } var parsed fileSchema if err := yaml.Unmarshal(data, &parsed); err != nil { return Map{}, fmt.Errorf("parse speaker map %q: %w", path, err) } if len(parsed.Inputs) == 0 { return Map{}, fmt.Errorf("speaker map %q must contain at least one inputs entry", path) } inputs := make(map[string]Input, len(parsed.Inputs)) for key, input := range parsed.Inputs { basename := filepath.Base(strings.TrimSpace(key)) if basename == "." || basename == "" { return Map{}, fmt.Errorf("speaker map %q contains an empty input key", path) } if _, exists := inputs[basename]; exists { return Map{}, fmt.Errorf("speaker map %q contains duplicate basename mapping for %q", path, basename) } input.Speaker = strings.TrimSpace(input.Speaker) if input.Speaker == "" { return Map{}, fmt.Errorf("speaker map entry %q must include speaker", basename) } inputs[basename] = input } return Map{inputs: inputs}, nil } // SpeakerForSource returns the canonical speaker for a transcript source path. func (m Map) SpeakerForSource(source string) (string, error) { basename := filepath.Base(source) input, ok := m.inputs[basename] if !ok { return "", fmt.Errorf("speaker map has no entry for input basename %q", basename) } return input.Speaker, nil }