Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Implement ElevenLabs speech-to-speech, sound effects, audio isolation, and speech-to-text. Use when converting one voice to another, generating sound effects from a text description, removing background noise from a recording, or transcribing audio. Trigger with "elevenlabs speech to speech", "voice changer", "sound effects", "audio isolation", "remove background noise", "elevenlabs transcribe".
.claude/skills/jeremylongshore-elevenlabs-core-workflow-b/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 28% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 93% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 38% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 92% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 65% | 0% |
Secondary ElevenLabs workflows beyond TTS: (1) Speech-to-Speech voice conversion, (2) Sound Effects generation from text descriptions, (3) Audio Isolation for noise removal, and (4) Speech-to-Text transcription. Each maps to one API endpoint and has both a TypeScript SDK and a cURL path.
Full code for every step lives in references/implementation.md; copy-ready invocations are in references/examples.md.
elevenlabs-install-auth setup.The SDK client (new ElevenLabsClient()) reads the API key from the ELEVENLABS_API_KEY environment variable automatically — never hardcode it. cURL requests send it as the xi-api-key: ${ELEVENLABS_API_KEY} header. Full auth setup is covered by the elevenlabs-install-auth skill.
Import the SDK once, then call the relevant module. The client authenticates from the environment:
typescriptimport { ElevenLabsClient } from "@elevenlabs/elevenlabs-js"; import { createReadStream, createWriteStream } from "fs"; import { Readable } from "stream"; import { pipeline } from "stream/promises"; const client = new ElevenLabsClient();
client.speechToSpeech.convert(voiceId, …)against POST /v1/speech-to-speech/{voice_id}. Use model_id: "eleven_english_sts_v2" and set remove_background_noise: true for built-in cleanup.
client.textToSoundEffects.convert({ text, … }) againstPOST /v1/sound-generation. Tune duration_seconds (0.5–30) and prompt_influence (0–1; higher follows the prompt more closely).
client.audioIsolation.audioIsolation({ audio }) againstPOST /v1/audio-isolation, or the streaming variant for large files.
client.speechToText.convert({ audio, model_id: "scribe_v1" })against POST /v1/speech-to-text; optionally enable diarize and word timestamps.
Each returns an audio stream (steps 1–3) piped to disk, or a transcript object (step 4). See references/implementation.md for the complete helper functions and cURL equivalents.
typescriptasync function speechToSpeech(sourceAudioPath, targetVoiceId, outputPath) { const audio = await client.speechToSpeech.convert(targetVoiceId, { audio: createReadStream(sourceAudioPath), model_id: "eleven_english_sts_v2", voice_settings: JSON.stringify({ stability: 0.5, similarity_boost: 0.8 }), remove_background_noise: true, }); await pipeline(Readable.fromWeb(audio as any), createWriteStream(outputPath)); }
| Feature | Method | Endpoint | Billing | |---------|--------|----------|---------| | Speech-to-Speech | POST | /v1/speech-to-speech/{voice_id} | Per character | | Sound Effects | POST | /v1/sound-generation | Per generation | | Audio Isolation | POST | /v1/audio-isolation | 1,000 chars/min of audio | | Audio Isolation Stream | POST | /v1/audio-isolation/stream | 1,000 chars/min of audio | | Speech-to-Text | POST | /v1/speech-to-text | Per audio minute |
outputPath you pass and log aconfirmation, e.g. Voice-converted audio saved to converted.mp3 or Clean audio saved to clean_interview.mp3.
result.text holds the fulltranscription, and result.words (when present) carries word-level { start, end, text } timestamps.
--output file.| Error | HTTP | Cause | Solution | |-------|------|-------|----------| | model_can_not_do_voice_conversion | 400 | Wrong model for STS | Use eleven_english_sts_v2 | | audio_too_short | 400 | STS input under 1 second | Use longer audio clip | | audio_too_long | 400 | STS input over limit | Trim to under 5 minutes | | invalid_sound_prompt | 400 | Nonsensical SFX description | Write descriptive, specific prompts | | file_too_large | 413 | Audio isolation over 500MB | Compress or split the file | | quota_exceeded | 401 | Character/generation limit hit | Check usage dashboard |
Worked, copy-ready invocations for all four workflows — including the three sound-effect variants (rain, laser, seamless forest loop), the "Rachel" voice conversion, an audio-isolation clean-up, and a transcription with word timestamps — are in references/examples.md. A one-liner:
typescript// Generate a 10-second rain sound effect, faithful to the prompt await generateSoundEffect( "Heavy rain on a tin roof with distant thunder", "rain.mp3", { duration: 10, promptInfluence: 0.6 } );
SDK + cURL code, sound-effect tips, and audio-isolation limits.
For common errors, see elevenlabs-common-errors. For SDK patterns, see elevenlabs-sdk-patterns.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 13,801 | 43,931 | +218% | 1 | 1 | 0% | 2,655 | 3,388 | +28% | 0 | 0 | — |
case-02 | fail→pass | 69,508 | 6,698 | -90% | 1 | 1 | 0% | 1,579 | 3,043 | +93% | 0 | 0 | — |
case-03 | fail→pass | 10,277 | 5,956 | -42% | 1 | 1 | 0% | 1,864 | 2,580 | +38% | 0 | 0 | — |
case-04 | fail→pass | 9,006 | 6,324 | -30% | 1 | 1 | 0% | 1,502 | 2,887 | +92% | 0 | 0 | — |
case-05 | fail→pass | 11,677 | 8,140 | -30% | 1 | 1 | 0% | 1,913 | 3,156 | +65% | 0 | 0 | — |
case-06 | pass→pass | 16,723 | 7,511 | -55% | 1 | 1 | 0% | 3,348 | 3,049 | -9% | 0 | 0 | — |
case-07 | pass→pass | 7,348 | 3,223 | -56% | 1 | 1 | 0% | 993 | 2,066 | +108% | 0 | 0 | — |
case-08 | pass→pass | 12,065 | 5,978 | -50% | 1 | 1 | 0% | 2,069 | 2,597 | +26% | 0 | 0 | — |
case-09 | pass→pass | 8,432 | 6,910 | -18% | 1 | 1 | 0% | 1,533 | 2,988 | +95% | 0 | 0 | — |
case-10 | pass→pass | 8,640 | 35,383 | +310% | 1 | 1 | 0% | 1,735 | 3,355 | +93% | 0 | 0 | — |
case-11 | pass→pass | 7,215 | 3,268 | -55% | 1 | 1 | 0% | 1,109 | 2,128 | +92% | 0 | 0 | — |
case-12 | fail→pass | 10,602 | 5,478 | -48% | 1 | 1 | 0% | 1,570 | 2,360 | +50% | 0 | 0 | — |
case-13 | pass→pass | 2,408 | 7,619 | +216% | 1 | 1 | 0% | 350 | 2,051 | +486% | 0 | 0 | — |
case-14 | pass→pass | 4,428 | 3,267 | -26% | 1 | 1 | 0% | 795 | 2,054 | +158% | 0 | 0 | — |
case-15 | pass→pass | 5,949 | 3,304 | -44% | 1 | 1 | 0% | 1,063 | 2,144 | +102% | 0 | 0 | — |
case-16 | fail→pass | 9,013 | 3,057 | -66% | 1 | 1 | 0% | 1,668 | 2,221 | +33% | 0 | 0 | — |
case-17 | pass→pass | 9,332 | 6,146 | -34% | 1 | 1 | 0% | 1,608 | 2,605 | +62% | 0 | 0 | — |
case-18 | pass→pass | 8,590 | 4,817 | -44% | 1 | 1 | 0% | 1,602 | 2,453 | +53% | 0 | 0 | — |
case-19 | fail→pass | 11,249 | 6,934 | -38% | 1 | 1 | 0% | 2,208 | 3,080 | +39% | 0 | 0 | — |
case-20 | pass→pass | 73,109 | 9,207 | -87% | 1 | 1 | 0% | 2,573 | 3,401 | +32% | 0 | 0 | — |
case-21 | pass→pass | 17,925 | 11,077 | -38% | 1 | 1 | 0% | 3,086 | 3,933 | +27% | 0 | 0 | — |
case-22 | fail→pass | 12,096 | 5,488 | -55% | 1 | 1 | 0% | 2,219 | 2,601 | +17% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +41 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.