|
import "dotenv/config"; |
|
import FormData from "form-data"; |
|
import axios from "axios"; |
|
import fs from "fs"; |
|
|
|
interface ICloneVoiceParams { |
|
description: string; |
|
name: string; |
|
fileUrls: string[]; |
|
labels: Record<string, string>; |
|
} |
|
|
|
const handleStreamEnd = (stream: fs.ReadStream): Promise<void> => { |
|
return new Promise((resolve) => { |
|
if (!stream || stream?.closed) { |
|
resolve(); |
|
return; |
|
} |
|
|
|
stream.once("end", () => { |
|
resolve(); |
|
}); |
|
stream.once("close", () => { |
|
resolve(); |
|
}); |
|
}); |
|
}; |
|
|
|
const cloneVoiceHandler = async ( |
|
params: ICloneVoiceParams |
|
): Promise<string> => { |
|
const { name, description, fileUrls = [], labels = {} } = params; |
|
const formData = new FormData(); |
|
const streams: fs.ReadStream[] = []; |
|
|
|
console.log("Début du clonage de voix..."); |
|
console.log("Fichiers à traiter:", fileUrls); |
|
|
|
for (let i = 0; i < fileUrls.length; i++) { |
|
try { |
|
const filePath = fileUrls[i]; |
|
console.log(`Traitement du fichier ${filePath}...`); |
|
|
|
const fileStream = fs.createReadStream(filePath); |
|
streams.push(fileStream); |
|
|
|
formData.append("files", fileStream, { |
|
filename: "sample1.mp3", |
|
contentType: "audio/mpeg", |
|
}); |
|
} catch (err) { |
|
console.error("Erreur lors du traitement du fichier:", err); |
|
throw err; |
|
} |
|
} |
|
|
|
formData.append("name", name); |
|
formData.append("description", description); |
|
|
|
if (typeof labels === "object" && labels) { |
|
formData.append("labels", JSON.stringify(labels)); |
|
} |
|
|
|
try { |
|
const elevenlabsUrl = "https://api.elevenlabs.io/v1/voices/add"; |
|
const elevenLabsApiKey = process.env.ELEVENLABS_API_KEY || ""; |
|
console.log("Envoi de la requête à ElevenLabs..."); |
|
|
|
const elevenLabsResponse = await axios.post(elevenlabsUrl, formData, { |
|
headers: { |
|
...formData.getHeaders(), |
|
Accept: "application/json", |
|
"xi-api-key": elevenLabsApiKey, |
|
}, |
|
}); |
|
|
|
console.log("Réponse d'ElevenLabs:", elevenLabsResponse.data); |
|
return elevenLabsResponse.data?.voice_id || ""; |
|
} catch (err) { |
|
console.error( |
|
"Erreur lors de l'appel à ElevenLabs:", |
|
err.response?.data || err |
|
); |
|
throw err; |
|
} finally { |
|
|
|
for (const stream of streams) { |
|
stream.destroy(); |
|
} |
|
} |
|
}; |
|
|
|
const params = { |
|
name: "test", |
|
description: "Voix française calme", |
|
fileUrls: [ |
|
"./sample1.mp3", |
|
], |
|
labels: { |
|
accent: "français", |
|
type: "calme", |
|
}, |
|
}; |
|
|
|
try { |
|
const voiceId = await cloneVoiceHandler(params); |
|
console.log("Voice ID obtenu:", voiceId); |
|
} catch (error) { |
|
console.error("Erreur globale:", error); |
|
} |
|
|