List Custom Voices
Browse user-created custom voices using .ListCustomVoices().
Basic Usage
var response = await Api.ElevenLabs
.ListCustomVoices()
.ExecuteAsync();
foreach (var voice in response.Voices)
{
Debug.Log($"Custom Voice: {voice.Name}");
}What are Custom Voices?
Custom voices are voices that you or your organization have created:
Voice cloning - Clone a real person's voice
Professional voice lab - Professional voice creation service
Instant voice cloning - Quick voice cloning from samples
Unity Integration Examples
Example 1: Custom Voice Manager
public class CustomVoiceManager : MonoBehaviour
{
[SerializeField] private TMPro.TMP_Dropdown dropdown;
private List<VoiceData> customVoices = new();
async void Start()
{
await LoadCustomVoices();
}
async UniTask LoadCustomVoices()
{
var response = await Api.ElevenLabs.ListCustomVoices().ExecuteAsync();
customVoices = response.Voices;
dropdown.ClearOptions();
var options = customVoices
.Select(v => new TMPro.TMP_Dropdown.OptionData(v.Name))
.ToList();
dropdown.AddOptions(options);
}
public VoiceData GetSelectedVoice()
{
int index = dropdown.value;
return customVoices[index];
}
}Example 2: Voice Library UI
public class VoiceLibrary : MonoBehaviour
{
[SerializeField] private Transform builtInParent;
[SerializeField] private Transform customParent;
[SerializeField] private GameObject voiceItemPrefab;
async void Start()
{
await LoadAllVoices();
}
async UniTask LoadAllVoices()
{
// Load built-in voices
var builtIn = await Api.ElevenLabs.ListVoices().ExecuteAsync();
CreateVoiceItems(builtIn.Voices, builtInParent, isCustom: false);
// Load custom voices
var custom = await Api.ElevenLabs.ListCustomVoices().ExecuteAsync();
CreateVoiceItems(custom.Voices, customParent, isCustom: true);
}
void CreateVoiceItems(List<VoiceData> voices, Transform parent, bool isCustom)
{
foreach (var voice in voices)
{
var item = Instantiate(voiceItemPrefab, parent);
var text = item.GetComponentInChildren<TMPro.TextMeshProUGUI>();
string prefix = isCustom ? "★ " : "";
text.text = $"{prefix}{voice.Name}\n<size=80%>{voice.Description}</size>";
}
}
}Example 3: Voice Type Selector
public class VoiceTypeSelector : MonoBehaviour
{
public enum VoiceType { BuiltIn, Custom, All }
[SerializeField] private VoiceType voiceType = VoiceType.All;
public async UniTask<List<VoiceData>> GetVoices()
{
var allVoices = new List<VoiceData>();
if (voiceType == VoiceType.BuiltIn || voiceType == VoiceType.All)
{
var builtIn = await Api.ElevenLabs.ListVoices().ExecuteAsync();
allVoices.AddRange(builtIn.Voices);
}
if (voiceType == VoiceType.Custom || voiceType == VoiceType.All)
{
var custom = await Api.ElevenLabs.ListCustomVoices().ExecuteAsync();
allVoices.AddRange(custom.Voices);
}
return allVoices;
}
}Provider Support
ElevenLabs
var customVoices = await Api.ElevenLabs.ListCustomVoices().ExecuteAsync();Features:
✅ Voice cloning
✅ Professional voice lab
✅ Instant voice cloning
✅ Voice editing
OpenAI
❌ OpenAI does not support custom voices. Only built-in voices available.
Google
// Limited custom voice support
var voices = await Api.Google.ListCustomVoices().ExecuteAsync();Combining Built-in and Custom Voices
public class AllVoicesManager : MonoBehaviour
{
public async UniTask<List<VoiceData>> GetAllVoices()
{
var allVoices = new List<VoiceData>();
// Get built-in voices
var builtInResponse = await Api.ElevenLabs.ListVoices().ExecuteAsync();
allVoices.AddRange(builtInResponse.Voices);
// Get custom voices
var customResponse = await Api.ElevenLabs.ListCustomVoices().ExecuteAsync();
allVoices.AddRange(customResponse.Voices);
return allVoices.OrderBy(v => v.Name).ToList();
}
public async UniTask<Dictionary<string, List<VoiceData>>> GetVoicesByCategory()
{
return new Dictionary<string, List<VoiceData>>
{
["Built-in"] = (await Api.ElevenLabs.ListVoices().ExecuteAsync()).Voices,
["Custom"] = (await Api.ElevenLabs.ListCustomVoices().ExecuteAsync()).Voices
};
}
}Best Practices
✅ Good Practices
// ✅ Cache custom voices
private List<VoiceData> cachedCustomVoices;
private float lastFetchTime;
async UniTask<List<VoiceData>> GetCustomVoicesCache()
{
if (cachedCustomVoices == null || Time.time - lastFetchTime > 3600f)
{
var response = await Api.ElevenLabs.ListCustomVoices().ExecuteAsync();
cachedCustomVoices = response.Voices;
lastFetchTime = Time.time;
}
return cachedCustomVoices;
}
// ✅ Handle empty results
var custom = await Api.ElevenLabs.ListCustomVoices().ExecuteAsync();
if (custom.Voices.Count == 0)
{
Debug.Log("No custom voices found");
}
// ✅ Separate UI for custom voices
CreateVoiceList(builtInVoices, "Built-in Voices");
CreateVoiceList(customVoices, "My Custom Voices");❌ Bad Practices
// ❌ Don't list in Update()
void Update()
{
await Api.ElevenLabs.ListCustomVoices().ExecuteAsync(); // NO!
}
// ❌ Don't assume custom voices exist
var voices = await Api.ElevenLabs.ListCustomVoices().ExecuteAsync();
var first = voices.Voices[0]; // May fail!
// ❌ Don't fetch repeatedly
// Cache the resultsError Handling
public async UniTask<List<VoiceData>> GetCustomVoicesSafe()
{
try
{
var response = await Api.ElevenLabs.ListCustomVoices().ExecuteAsync();
return response.Voices;
}
catch (AIApiException ex)
{
Debug.LogError($"API Error: {ex.Message}");
return new List<VoiceData>();
}
catch (Exception ex)
{
Debug.LogError($"Unexpected error: {ex.Message}");
return new List<VoiceData>();
}
}Next Steps
Get Voice - Get specific voice info
List Voices - Browse built-in voices
Text to Speech - Use custom voices for TTS
Last updated