| 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); |
| } |
|
|