Skip to main content
Voice Changer is speech-to-speech. You give it a recording, name a voice, and get the same performance back in that voice: same words, same pauses, same emphasis, same length. It is for when you already have a take you want to keep. If you only have text, use text-to-speech; if you want your own voice available as a target, see voice cloning. Here is a 7-second clip from /audio/speech and the result of converting it to the George voice. The waveforms sit on one time axis, and the gaps between phrases land in the same places.
Two waveforms stacked on the same time axis: the source recording in blue and the converted recording in orange, with silences aligned
The conversion runs asynchronously through four endpoints under /audio/voice-changer/: quote prices a length, queue submits the recording and charges you, retrieve polls until the MP3 is ready, and complete deletes the stored media once you have it. The shape is the same as the music endpoints, but the path is different and the two do not accept each other’s models. The examples assume VENICE_API_KEY is set:

Choose a model

Voice-changer models live under GET /models?type=music with model_spec.voice_changer set to true; there is no dedicated type filter. Right now there is one, elevenlabs-voice-changer: it takes mp3, wav, ogg, mp4, or aac sources up to 300 seconds, offers 20 named voices with Aria as the default, accepts a raw ElevenLabs Voice ID in place of a name, and supports remove_background_noise and seed. Those details can change, so read them from the API. This query returns everything the rest of the guide depends on:
Sending a field the model does not support returns 400. A recording longer than max_source_audio_duration_seconds returns 422 before any charge, with the limit in the message. One thing the API does not check at queue time is the voice name. Queue a voice the model does not have and you still get 200 and a queue_id; the rejection arrives on the first retrieve, with the charge refunded. You get the money back but lose the round trip, so check voices before you queue.

1. Get a price quote

Billing is by the length of the source recording, rounded up to the next whole minute. For elevenlabs-voice-changer that is $0.35 for anything up to 60 seconds, $0.69 up to 120, $1.04 up to 180, $1.38 up to 240, and $1.73 up to 300. A 7-second clip costs the same as a 60-second one, and 60.5 seconds is billed as two minutes. If you have many short segments, join them into one file that stays under a minute boundary instead of queueing each separately. The tiers come from pricing.durations in /models. Quote takes a whole number of seconds and needs no API key:
This is an estimate. The charge is computed from the length Venice measures when the recording is queued.

2. Queue the conversion

Send the recording either as a multipart file upload or as an audio_url in a JSON body, but not both. A URL has to be publicly reachable without headers or cookies; Venice fetches the bytes itself and never passes the URL to the provider. Venice checks the bytes, not the extension, so a file has to actually be one of the accepted containers, and files with a video track are rejected. With curl -F, leave Content-Type alone so curl can set the multipart boundary, and send remove_background_noise as true/false and seed as digits.
The multipart request above is the one that produced the George clip at the top of the page. Omit voice to get default_voice. When supports_custom_voice_id is true, voice can also be a provider Voice ID; for elevenlabs-voice-changer that means any ElevenLabs voice you have access to, including library voices that are not in Venice’s voices list. remove_background_noise and seed are only accepted when the model reports support for them. The response gives you the handle for everything that follows:
duration_seconds is the length Venice measured, and the tier you were billed on. If you quoted 60 and this says 61.2, you paid for two minutes. Keep model and queue_id; retrieve and complete both need them, and the id is good for 24 hours. You have been charged at this point, not when the audio comes back, so do not retry a queue request. If you have a queue_id, poll with it. If the response never arrived, sending the recording again can charge you twice. Queue is limited to 40 requests per minute and retrieve to 120; both report x-ratelimit-remaining-requests.

3. Poll and download

Call retrieve with the values from the queue response:
The response is one of two things. While the job is running you get JSON:
When it is done you get audio/mpeg and the body is the MP3. Branch on Content-Type. The two numbers are milliseconds: how long jobs on this model usually take, and how long yours has been running. The gap is a reasonable first sleep, but the average is only a hint. A 148-second source took 24 seconds against an average of 7, so on longer inputs execution_duration will overtake average_execution_time. When it does, fall back to a fixed interval of a few seconds and keep going. Short clips go the other way: the 7-second example came back on the very first poll. The finished response carries x-venice-audio-duration (seconds), x-venice-inference-time, x-venice-audio-format, x-venice-model-id, and x-venice-model-name. Output is always 128 kbps mono MP3 at 44.1 kHz, whatever you sent in. The audio duration should match your source to within a few milliseconds; if it is off by more than that, listen before you ship it.

If it fails

A job the provider accepted and then failed comes back as an error status with error and credits_refunded in the body. true means the charge was reversed. false with a message ending in “please contact support” means the refund itself failed and the next poll will try again. The verdict is stored, so polling again replays it. A job that never reached the provider looks different. Retrieve keeps saying PROCESSING for up to 10 minutes, then returns 504 and refunds you, so give a PROCESSING job at least that long before you treat it as stuck. The full set of terminal outcomes is on the retrieve reference.

Clean up

Pass delete_media_on_completion: true on retrieve and the stored media is deleted in the same call that hands you the audio. Any later retrieve for that id returns 404. If you want to download more than once, leave it off and call complete when you are finished. Complete returns {"success": true} and is safe to call repeatedly.

Complete example

Everything above, end to end: check the voice exists, quote, upload, poll until the audio arrives, save it. The deadline is 12 minutes so that a dispatch failure shows up as a refund rather than a timeout.
There is no complete call because retrieve deletes the media on its way out. Drop delete_media_on_completion and call complete yourself if you need the file more than once.

API parameters

Queue

Retrieve and complete

Errors