The Projects & Studio API provides comprehensive tools for managing complex audio production workflows, including studio projects, chapter management, and Audio Native embeddable players. These features enable professional audiobook creation, long-form content production, and web-based audio experiences.
import {
ElevenLabsClient,
type BodyCreateStudioProjectV1StudioProjectsPost,
type BodyUpdateStudioProjectV1StudioProjectsPost,
type BodyUpdateStudioProjectContentV1StudioProjectsProjectIdContentPost,
type BodyCreatesAudioNativeEnabledProjectV1AudioNativePost,
type BodyUpdateAudioNativeProjectContentV1AudioNativeProjectIdContentPost,
type ProjectsAddRequestTargetAudience,
type ProjectsAddRequestFiction,
type ProjectsAddRequestSourceType
} from 'elevenlabs';const client = new ElevenLabsClient();
// Create a basic studio project
const project = await client.studio.projects.create({
name: "My Audiobook Project",
default_title_voice_id: "pNInz6obpgDQGcFmaJgB", // Voice for chapter titles
default_paragraph_voice_id: "21m00Tcm4TlvDq8ikWAM", // Voice for content
default_model_id: "eleven_multilingual_v2",
quality_preset: "high", // standard, high, ultra, ultra lossless
// Project metadata
title: "The Great Adventure",
author: "John Author",
description: "An epic adventure story spanning multiple chapters",
language: "en",
content_type: "fiction",
target_audience: "adult",
genres: ["fantasy", "adventure", "fiction"],
// Processing options
auto_convert: true, // Automatically convert to audio
volume_normalization: true, // Apply audiobook normalization
apply_text_normalization: "auto"
});
console.log('Project created:', project.project_id);
console.log('Project status:', project.state);import * as fs from 'fs';
// Create project from existing content
const advancedProject = await client.studio.projects.create({
name: "Professional Audiobook Production",
default_title_voice_id: "narrator_voice_id",
default_paragraph_voice_id: "character_voice_id",
default_model_id: "eleven_multilingual_v2",
// Initialize from document
from_document: fs.createReadStream('manuscript.txt'),
// OR from URL
// from_url: "https://example.com/book-content.html",
// High-quality production settings
quality_preset: "ultra", // 50% credit increase but highest quality
// Complete metadata
title: "The Complete Guide to AI",
author: "Dr. AI Expert",
description: "A comprehensive guide to artificial intelligence",
isbn_number: "978-1234567890",
original_publication_date: "2024-01-01",
language: "en",
content_type: "non-fiction",
target_audience: "adult",
genres: ["technology", "education", "reference"],
mature_content: false,
fiction: "non-fiction",
// Advanced processing
auto_convert: false, // Manual control over conversion
auto_assign_voices: true, // AI voice assignment
volume_normalization: true,
apply_text_normalization: "on",
// Pronunciation customization
pronunciation_dictionary_locators: [
JSON.stringify({
pronunciation_dictionary_id: "dict_id_1",
version_id: "version_1"
})
],
// Webhook notification
callback_url: "https://your-app.com/webhooks/project-complete"
});// Get all projects
const projects = await client.studio.projects.getAll();
console.log(`Found ${projects.projects.length} projects`);
projects.projects.forEach(project => {
console.log(`- ${project.name} (${project.project_id})`);
console.log(` Status: ${project.state}`);
console.log(` Quality: ${project.quality_preset}`);
console.log(` Created: ${new Date(project.create_date_unix * 1000).toLocaleDateString()}`);
});
// Get specific project details
const projectDetails = await client.studio.projects.get(project.project_id);
console.log('Project details:', {
name: projectDetails.name,
state: projectDetails.state,
wordCount: projectDetails.word_count,
chapterCount: projectDetails.chapters?.length,
totalDuration: projectDetails.duration_seconds,
progress: projectDetails.conversion_progress_percentage
});// Update project settings
const updatedProject = await client.studio.projects.update(
project.project_id,
{
name: "Updated Project Name",
title: "Updated Title",
description: "Updated project description",
quality_preset: "ultra", // Upgrade quality
volume_normalization: true,
// Update voice assignments
default_title_voice_id: "new_narrator_voice_id",
default_paragraph_voice_id: "new_character_voice_id"
}
);// Replace project content
await client.studio.projects.updateContent(
project.project_id,
{
content: `# Chapter 1: The Beginning
It was a dark and stormy night when our hero first discovered the mysterious artifact.
The rain pattered against the window as she examined the strange glowing object.
# Chapter 2: The Journey
With determination in her heart, she set off on the journey that would change everything.
The path ahead was uncertain, but her resolve was unwavering.`,
// Processing options
auto_convert: true,
apply_text_normalization: "auto"
}
);
// OR update from file
await client.studio.projects.updateContent(
project.project_id,
{
from_document: fs.createReadStream('updated_manuscript.txt'),
auto_convert: true
}
);
// OR update from URL
await client.studio.projects.updateContent(
project.project_id,
{
from_url: "https://example.com/updated-content.html",
auto_convert: false // Manual conversion control
}
);// Get all chapters for a project
const chapters = await client.studio.chapters.getAll(project.project_id);
console.log(`Project has ${chapters.chapters.length} chapters`);
chapters.chapters.forEach((chapter, index) => {
console.log(`Chapter ${index + 1}: ${chapter.name}`);
console.log(` State: ${chapter.state}`);
console.log(` Duration: ${chapter.audio_duration_seconds}s`);
console.log(` Word count: ${chapter.word_count}`);
});// Add a new chapter to the project
const newChapter = await client.studio.chapters.create(
project.project_id,
{
name: "Chapter 5: The Revelation",
content: `The truth was finally revealed in all its shocking detail.
Everything they thought they knew was about to change forever.
The ancient prophecy spoke of this moment, but none of them
had truly believed it would come to pass in their lifetime.`,
// Chapter-specific voice settings
voice_id: "dramatic_narrator_voice_id",
model_id: "eleven_multilingual_v2",
// Position in project
chapter_index: 4 // Insert at position 5 (0-indexed)
}
);
console.log('Chapter created:', newChapter.chapter_id);// Update chapter content and settings
const updatedChapter = await client.studio.chapters.update(
project.project_id,
newChapter.chapter_id,
{
name: "Chapter 5: The Great Revelation",
content: `The truth was finally revealed in all its shocking, magnificent detail.
Everything they thought they knew was about to change forever and ever.`,
// Update voice for this chapter
voice_id: "epic_narrator_voice_id",
// Force regeneration
regenerate_audio: true
}
);// Get chapter audio
const chapterAudio = await client.studio.chapters.getAudio(
project.project_id,
newChapter.chapter_id
);
// Save chapter audio
import { pipeline } from 'stream';
import { promisify } from 'util';
const pipelineAsync = promisify(pipeline);
await pipelineAsync(
chapterAudio,
fs.createWriteStream(`chapter_${newChapter.chapter_id}.mp3`)
);
// Delete chapter
await client.studio.chapters.delete(project.project_id, newChapter.chapter_id);
console.log('Chapter deleted');// Start audio conversion for entire project
await client.studio.projects.convertToAudio(project.project_id, {
quality_preset: "high",
volume_normalization: true,
apply_text_normalization: "auto"
});
console.log('Audio conversion started');// Monitor project conversion progress
async function monitorProjectConversion(projectId: string) {
let isComplete = false;
while (!isComplete) {
const project = await client.studio.projects.get(projectId);
console.log(`Conversion progress: ${project.conversion_progress_percentage}%`);
console.log(`State: ${project.state}`);
if (project.state === 'converted') {
console.log('✓ Project conversion completed!');
isComplete = true;
} else if (project.state === 'conversion_failed') {
console.log('✗ Project conversion failed');
throw new Error('Conversion failed');
} else {
// Wait 30 seconds before checking again
await new Promise(resolve => setTimeout(resolve, 30000));
}
}
}
// Usage
await monitorProjectConversion(project.project_id);// Download complete project audio
const projectAudio = await client.studio.projects.getAudio(project.project_id);
await pipelineAsync(
projectAudio,
fs.createWriteStream(`${project.name}_complete.mp3`)
);
console.log('Project audio downloaded');
// Download individual chapters
const chapters = await client.studio.chapters.getAll(project.project_id);
for (let i = 0; i < chapters.chapters.length; i++) {
const chapter = chapters.chapters[i];
if (chapter.state === 'converted') {
const chapterAudio = await client.studio.chapters.getAudio(
project.project_id,
chapter.chapter_id
);
const filename = `${chapter.name.replace(/\s+/g, '_')}.mp3`;
await pipelineAsync(chapterAudio, fs.createWriteStream(filename));
console.log(`Downloaded: ${filename}`);
}
}// Create embeddable audio player project
const audioNativeProject = await client.audioNative.create({
name: "Website Audio Content",
// Content source
text_content: `Welcome to our website! This audio content will be embedded
directly into your web pages, providing an interactive listening experience
for your visitors. They can play, pause, and navigate through the content
seamlessly.`,
// Voice and model settings
voice_id: "professional_web_voice_id",
model_id: "eleven_multilingual_v2",
// Auto-start conversion
auto_convert: true,
// Embedding options
auto_play: false, // Don't auto-play on page load
show_controls: true, // Show player controls
background_color: "#ffffff",
text_color: "#000000"
});
console.log('Audio Native project created:', audioNativeProject.project_id);
console.log('Embed code:', audioNativeProject.embed_html);// Create Audio Native project with advanced settings
const advancedAudioNative = await client.audioNative.create({
name: "Interactive Article Reader",
// Rich content
text_content: `# Article Title
This is an interactive article that readers can listen to while following along
with the text. The audio player will highlight sections as they're spoken.
## Section 1: Introduction
Here we introduce the main concepts...
## Section 2: Deep Dive
Now we explore the details...`,
// High-quality voice settings
voice_id: "article_narrator_voice_id",
model_id: "eleven_multilingual_v2",
voice_settings: {
stability: 0.7,
similarity_boost: 0.8,
style: 0.2,
speed: 0.95 // Slightly slower for article reading
},
// Advanced player options
auto_convert: true,
auto_play: false,
show_controls: true,
enable_logging: false, // Privacy mode
// Customization
background_color: "#f8f9fa",
text_color: "#212529",
primary_color: "#007bff",
// Behavior settings
highlight_current_section: true,
show_progress_bar: true,
enable_speed_control: true,
enable_download: false // Disable download option
});// Update Audio Native project content
await client.audioNative.updateContent(
audioNativeProject.project_id,
{
text_content: `# Updated Content
This is the updated version of our audio content with new information
and improved sections for better user engagement.
## New Section: Additional Features
We've added exciting new features based on user feedback...`,
// Update settings
voice_id: "updated_voice_id",
auto_convert: true,
// New customization
background_color: "#f0f0f0",
show_controls: true,
enable_speed_control: true
}
);
console.log('Audio Native content updated');interface BodyCreateStudioProjectV1StudioProjectsPost {
/** Project name for identification */
name: string;
/** Default voice for chapter titles */
default_title_voice_id: string;
/** Default voice for paragraph content */
default_paragraph_voice_id: string;
/** Model ID for audio generation */
default_model_id: string;
/** Content source options */
from_url?: string; // Extract from URL
from_document?: File | fs.ReadStream | Blob; // Upload document
/**
* Output quality preset:
* - "standard": 128kbps, 44.1kHz
* - "high": 192kbps, 44.1kHz (+20% credits)
* - "ultra": 192kbps, 44.1kHz, highest quality (+50% credits)
* - "ultra lossless": 705.6kbps, 44.1kHz, lossless (+100% credits)
*/
quality_preset?: "standard" | "high" | "ultra" | "ultra lossless";
/** Project metadata */
title?: string;
author?: string;
description?: string;
genres?: string[];
target_audience?: "children" | "young_adult" | "adult";
language?: string; // ISO 639-1 code
content_type?: string;
original_publication_date?: string; // YYYY-MM-DD or YYYY
mature_content?: boolean;
isbn_number?: string;
fiction?: "fiction" | "non-fiction";
/** Processing options */
volume_normalization?: boolean;
apply_text_normalization?: "auto" | "on" | "off" | "apply_english";
auto_convert?: boolean;
auto_assign_voices?: boolean;
/** Pronunciation dictionaries */
pronunciation_dictionary_locators?: string[];
/** Webhook callback URL */
callback_url?: string;
/** Project source type */
source_type?: string;
}interface BodyCreatesAudioNativeEnabledProjectV1AudioNativePost {
/** Project name */
name: string;
/** Text content to convert */
text_content?: string;
/** Voice and model settings */
voice_id?: string;
model_id?: string;
voice_settings?: VoiceSettings;
/** Processing options */
auto_convert?: boolean;
enable_logging?: boolean;
/** Player configuration */
auto_play?: boolean;
show_controls?: boolean;
highlight_current_section?: boolean;
show_progress_bar?: boolean;
enable_speed_control?: boolean;
enable_download?: boolean;
/** Visual customization */
background_color?: string;
text_color?: string;
primary_color?: string;
}// Complete audiobook production workflow
async function createAudiobook(manuscriptPath: string) {
console.log('Starting audiobook production...');
// Step 1: Create project
const project = await client.studio.projects.create({
name: "Professional Audiobook",
default_title_voice_id: "narrator_voice_id",
default_paragraph_voice_id: "character_voice_id",
default_model_id: "eleven_multilingual_v2",
from_document: fs.createReadStream(manuscriptPath),
quality_preset: "ultra",
// Audiobook metadata
title: "The Great Novel",
author: "Famous Author",
isbn_number: "978-1234567890",
language: "en",
content_type: "fiction",
fiction: "fiction",
// Production settings
auto_convert: false, // Manual control
volume_normalization: true,
apply_text_normalization: "auto"
});
console.log('✓ Project created:', project.project_id);
// Step 2: Wait for project initialization
let projectReady = false;
while (!projectReady) {
const status = await client.studio.projects.get(project.project_id);
if (status.state === 'ready' || status.state === 'converted') {
projectReady = true;
} else {
await new Promise(resolve => setTimeout(resolve, 10000));
}
}
// Step 3: Customize chapters
const chapters = await client.studio.chapters.getAll(project.project_id);
for (let i = 0; i < chapters.chapters.length; i++) {
const chapter = chapters.chapters[i];
// Assign different voices based on content
let voiceId = "narrator_voice_id";
if (chapter.name.toLowerCase().includes('dialogue')) {
voiceId = "character_voice_id";
} else if (chapter.name.toLowerCase().includes('action')) {
voiceId = "action_narrator_voice_id";
}
await client.studio.chapters.update(
project.project_id,
chapter.chapter_id,
{
voice_id: voiceId,
regenerate_audio: true
}
);
console.log(`✓ Configured chapter: ${chapter.name}`);
}
// Step 4: Start conversion
await client.studio.projects.convertToAudio(project.project_id, {
quality_preset: "ultra",
volume_normalization: true
});
console.log('✓ Audio conversion started');
// Step 5: Monitor progress
await monitorProjectConversion(project.project_id);
// Step 6: Download final audiobook
const projectAudio = await client.studio.projects.getAudio(project.project_id);
const filename = 'complete_audiobook.mp3';
await pipelineAsync(projectAudio, fs.createWriteStream(filename));
console.log(`✓ Audiobook saved: ${filename}`);
return project.project_id;
}// Create audio-enabled web content
async function createWebAudioContent(articles: Array<{title: string, content: string}>) {
const audioProjects = [];
for (const article of articles) {
const audioProject = await client.audioNative.create({
name: `Audio: ${article.title}`,
text_content: `# ${article.title}\n\n${article.content}`,
voice_id: "web_narrator_voice_id",
model_id: "eleven_turbo_v2_5", // Faster for web content
// Web-optimized settings
auto_convert: true,
auto_play: false,
show_controls: true,
enable_speed_control: true,
highlight_current_section: true,
// Brand colors
background_color: "#ffffff",
text_color: "#333333",
primary_color: "#0066cc"
});
audioProjects.push({
title: article.title,
projectId: audioProject.project_id,
embedCode: audioProject.embed_html
});
console.log(`✓ Created audio for: ${article.title}`);
}
// Generate HTML page with all audio content
const htmlContent = `
<!DOCTYPE html>
<html>
<head>
<title>Audio-Enhanced Articles</title>
<style>
.article { margin: 2rem 0; padding: 1rem; border: 1px solid #ddd; }
.audio-player { margin: 1rem 0; }
</style>
</head>
<body>
<h1>Audio-Enhanced Content</h1>
${audioProjects.map(project => `
<div class="article">
<h2>${project.title}</h2>
<div class="audio-player">
${project.embedCode}
</div>
</div>
`).join('')}
</body>
</html>
`;
fs.writeFileSync('audio_articles.html', htmlContent);
console.log('✓ HTML page generated: audio_articles.html');
return audioProjects;
}// Manage multiple projects efficiently
class ProjectManager {
private client: ElevenLabsClient;
private projects: Map<string, any> = new Map();
constructor(client: ElevenLabsClient) {
this.client = client;
}
async createBatch(projectConfigs: any[]) {
const results = [];
for (const config of projectConfigs) {
try {
const project = await this.client.studio.projects.create(config);
this.projects.set(project.project_id, project);
results.push({ success: true, projectId: project.project_id });
} catch (error) {
results.push({ success: false, error: error.message });
}
}
return results;
}
async monitorAllProjects() {
const statuses = [];
for (const [projectId] of this.projects) {
try {
const status = await this.client.studio.projects.get(projectId);
statuses.push({
projectId,
name: status.name,
state: status.state,
progress: status.conversion_progress_percentage
});
} catch (error) {
statuses.push({
projectId,
error: error.message
});
}
}
return statuses;
}
async downloadCompletedProjects() {
const statuses = await this.monitorAllProjects();
for (const status of statuses) {
if (status.state === 'converted') {
try {
const audio = await this.client.studio.projects.getAudio(status.projectId);
const filename = `${status.name.replace(/\s+/g, '_')}.mp3`;
await pipelineAsync(audio, fs.createWriteStream(filename));
console.log(`Downloaded: ${filename}`);
} catch (error) {
console.error(`Failed to download ${status.projectId}:`, error);
}
}
}
}
}import { ElevenLabsError, ElevenLabsTimeoutError } from 'elevenlabs';
try {
const project = await client.studio.projects.create({
name: "Test Project",
default_title_voice_id: "invalid_voice_id",
default_paragraph_voice_id: "invalid_voice_id",
default_model_id: "invalid_model_id"
});
} catch (error) {
if (error instanceof ElevenLabsError) {
console.error('Project creation error:', error.statusCode);
if (error.statusCode === 400) {
console.error('Invalid parameters:', error.body);
} else if (error.statusCode === 402) {
console.error('Insufficient credits for project creation');
} else if (error.statusCode === 422) {
console.error('Validation error:', error.body);
}
}
}
// Robust project monitoring
async function robustProjectMonitoring(projectId: string, maxWaitTime = 3600000) { // 1 hour
const startTime = Date.now();
while (Date.now() - startTime < maxWaitTime) {
try {
const project = await client.studio.projects.get(projectId);
if (project.state === 'converted') {
return project;
} else if (project.state === 'conversion_failed') {
throw new Error(`Project conversion failed: ${project.error_message}`);
}
await new Promise(resolve => setTimeout(resolve, 30000));
} catch (error) {
console.error('Error checking project status:', error);
await new Promise(resolve => setTimeout(resolve, 60000)); // Wait longer on error
}
}
throw new Error('Project conversion timeout');
}