diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 6a58767..e200ea2 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -11,6 +11,9 @@ on: jobs: build: runs-on: ubuntu-latest + permissions: + contents: read + id-token: write steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 @@ -32,6 +35,6 @@ jobs: node-version: 16 registry-url: https://registry.npmjs.org/ - run: npm install - - run: npm publish + - run: npm publish --provenance env: NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} diff --git a/.gitignore b/.gitignore index fa035d0..e75bd3f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules package-lock.json .DS_Store .eslintrc.json -audio.mp3 \ No newline at end of file +audio.mp3 +.env \ No newline at end of file diff --git a/README.md b/README.md index 701375c..1c302ae 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,11 @@

+ + NPM Package Build + +
+
@@ -45,17 +50,31 @@ This is an open source Eleven Labs NodeJS package for converting text to speech |
Function
| Parameters | Endpoint | | --------------------------------------- | --------------------------------------------------------------------------- | -------------------------------------- | -| `textToSpeech` | (apiKey, voiceID, fileName, textInput, stability, similarityBoost, modelId) | `/v1/text-to-speech/{voice_id}` | -| `textToSpeechStream` | (apiKey, voiceID, textInput, stability, similarityBoost, modelId) | `/v1/text-to-speech/{voice_id}/stream` | -| `getVoices` | (apiKey) | `/v1/voices` | -| `getDefaultVoiceSettings` | N/A | `/v1/voices/settings/default` | -| `getVoiceSettings` | (apiKey, voiceID) | `/v1/voices/{voice_id}/settings` | -| `getVoice` | (apiKey, voiceID) | `/v1/voices/{voice_id}` | -| `deleteVoice` | (apiKey, voiceID) | `/v1/voices/{voice_id}` | -| `editVoiceSettings` | (apiKey, voiceID, stability, similarityBoost) | `/v1/voices/{voice_id}/settings/edit` | -| `getModels` | (apiKey) | `/v1/models` | -| `getUserInfo` | (apiKey) | `/v1/user` | -| `getUserSubscription` | (apiKey) | `/v1/user/subscription` | +| `textToSpeech` | ({voiceId, fileName, textInput, stability, similarityBoost, modelId, style, speakerBoost}) | `/v1/text-to-speech/{voice_id}` | +| `textToSpeechStream` | ({voiceId, textInput, stability, similarityBoost, modelId, responseType, style, speakerBoost}) | `/v1/text-to-speech/{voice_id}/stream` | +| `editVoiceSettings` | ({voiceId, stability, similarityBoost}) | `/v1/voices/{voice_id}/settings/edit` | +| `getVoiceSettings` | ({voiceId}) | `/v1/voices/{voice_id}/settings` | +| `deleteVoice` | ({voiceId}) | `/v1/voices/{voice_id}` | +| `getVoice` | ({voiceId}) | `/v1/voices/{voice_id}` | +| `getVoices` | N/A | `/v1/voices` | +| `getModels` | N/A | `/v1/models` | +| `getUserInfo` | N/A | `/v1/user` | +| `getUserSubscription` | N/A | `/v1/user/subscription` | +| `getDefaultVoiceSettings` | N/A | `/v1/voices/settings/default` | + +## Parameters +|
Variable
| Description | Type | +| --------------------------------------- | --------------------------------------------------------------------------- | -------------------------------------- | +| `fileName` | Name and file path for your audio file e.g (`./gen/hello`) | `String` | +| `textInput` | Text to be converted into audio e.g (`Hello`) | `String` | +| `stability` | Stability for Text to Speech default (`0`) | `Float` | +| `similarityBoost` | Similarity Boost for Text to Speech default (`0`) | `Float` | +| `voiceId` | ElevenLabs Voice ID e.g (`pNInz6obpgDQGcFmaJgB`) | `String` | +| `modelId` | ElevenLabs Model ID e.g (`elevenlabs_multilingual_v2`) | `String` | +| `responseType` | Streaming response type e.g (`stream`) | `String` | +| `speakerBoost` | Speaker Boost for Text to Speech e.g (`true`) | `Boolean` | +| `style` | Style Exaggeration for Text to Speech (0-100) default (`0`) | `Integer` | + ## Requirements @@ -69,50 +88,264 @@ To install the Elevenlabs package, run the following command: npm install elevenlabs-node ``` +## Setup + +Setup the ElevenLabs configurations for your project. + +|
Variable
| Description | Default | +| --------------------------------------- | --------------------------------------------------------------------------- | -------------------------------------- | +| `apiKey` | (`Required`) Your API key from Elevenlabs | N/A | +| `voiceId` | (`Optional`) A Voice ID from Elevenlabs | Adam (`pNInz6obpgDQGcFmaJgB`) | + +```javascript +const ElevenLabs = require("elevenlabs-node"); + +const voice = new ElevenLabs( + { + apiKey: "0e2c037kl8561005671b1de345s8765c", // Your API key from Elevenlabs + voiceId: "pNInz6obpgDQGcFmaJgB", // A Voice ID from Elevenlabs + } +); +``` + ## Usage +### Text To Speech + +Generating an audio file from text. + +```javascript +const ElevenLabs = require("elevenlabs-node"); + +const voice = new ElevenLabs( + { + apiKey: "0e2c037kl8561005671b1de345s8765c", // Your API key from Elevenlabs + voiceId: "pNInz6obpgDQGcFmaJgB", // A Voice ID from Elevenlabs + } +); + +voice.textToSpeech({ + // Required Parameters + fileName: "audio.mp3", // The name of your audio file + textInput: "mozzy is cool", // The text you wish to convert to speech + + // Optional Parameters + voiceId: "21m00Tcm4TlvDq8ikWAM", // A different Voice ID from the default + stability: 0.5, // The stability for the converted speech + similarityBoost: 0.5, // The similarity boost for the converted speech + modelId: "elevenlabs_multilingual_v2", // The ElevenLabs Model ID + style: 1, // The style exaggeration for the converted speech + speakerBoost: true // The speaker boost for the converted speech + }).then((res) => { + console.log(res); +}); +``` + +### Text To Speech Stream + +Generating an audio stream from text. + +```javascript +const ElevenLabs = require("elevenlabs-node"); +const fs = require("fs-extra"); + +const voice = new ElevenLabs( + { + apiKey: "0e2c037kl8561005671b1de345s8765c", // Your API key from Elevenlabs + voiceId: "pNInz6obpgDQGcFmaJgB", // A Voice ID from Elevenlabs + } +); + +const voiceResponse = voice.textToSpeechStream({ + // Required Parameters + textInput: "mozzy is cool", // The text you wish to convert to speech + + // Optional Parameters + voiceId: "21m00Tcm4TlvDq8ikWAM", // A different Voice ID from the default + stability: 0.5, // The stability for the converted speech + similarityBoost: 0.5, // The similarity boost for the converted speech + modelId: "elevenlabs_multilingual_v2", // The ElevenLabs Model ID + style: 1, // The style exaggeration for the converted speech + responseType: "stream", // The streaming type (arraybuffer, stream, json) + speakerBoost: true // The speaker boost for the converted speech + }).then((res) => { + res.pipe(fs.createWriteStream(fileName)); +}); +``` + +### Edit Voice Settings + +Editing voice settings. + +```javascript +const ElevenLabs = require("elevenlabs-node"); + +const voice = new ElevenLabs( + { + apiKey: "0e2c037kl8561005671b1de345s8765c", // Your API key from Elevenlabs + } +); + +const voiceResponse = voice.editVoiceSettings({ + // Required Parameters + voiceId: "pNInz6obpgDQGcFmaJgB", // The ID of the voice you want to edit + stabilityBoost: 0.5, // The Stability Boost for the voice + similarityBoost: 0.5, // The Similarity Boost for the voice + }).then((res) => { + console.log(res); +}); +``` + +### Get Voice Settings + +Getting voice settings. + +```javascript +const ElevenLabs = require("elevenlabs-node"); + +const voice = new ElevenLabs( + { + apiKey: "0e2c037kl8561005671b1de345s8765c", // Your API key from Elevenlabs + } +); + +const voiceResponse = voice.getVoiceSettings({ + // Required Parameters + voiceId: "pNInz6obpgDQGcFmaJgB" // The ID of the voice you want to get + }).then((res) => { + console.log(res); +}); +``` + +### Delete Voice + +Delete voice. + +```javascript +const ElevenLabs = require("elevenlabs-node"); + +const voice = new ElevenLabs( + { + apiKey: "0e2c037kl8561005671b1de345s8765c", // Your API key from Elevenlabs + } +); + +const voiceResponse = voice.deleteVoice({ + // Required Parameters + voiceId: "pNInz6obpgDQGcFmaJgB" // The ID of the voice you want to delete + }).then((res) => { + console.log(res); +}); +``` + +### Get Voice + Getting voice details. ```javascript -const voice = require("elevenlabs-node"); +const ElevenLabs = require("elevenlabs-node"); + +const voice = new ElevenLabs( + { + apiKey: "0e2c037kl8561005671b1de345s8765c", // Your API key from Elevenlabs + } +); + +const voiceResponse = voice.getVoice({ + // Required Parameters + voiceId: "pNInz6obpgDQGcFmaJgB" // The ID of the voice you want to get + }).then((res) => { + console.log(res); +}); +``` + +### Get Voices + +Getting all voice details. + +```javascript +const ElevenLabs = require("elevenlabs-node"); -const apiKey = "0e2c037kl8561005671b1de345s8765c"; // Your API key from Elevenlabs -const voiceID = "pNInz6obpgDQGcFmaJgB"; // The ID of the voice you want to get +const voice = new ElevenLabs( + { + apiKey: "0e2c037kl8561005671b1de345s8765c", // Your API key from Elevenlabs + } +); -const voiceResponse = voice.getVoice(apiKey, voiceID).then((res) => { +const voiceResponse = voice.getVoices().then((res) => { console.log(res); }); ``` -Generating an audio file from text +### Get Models + +Getting all model details. ```javascript -const voice = require("elevenlabs-node"); -const fs = require("fs-extra"); +const ElevenLabs = require("elevenlabs-node"); -const apiKey = "0e2c037kl8561005671b1de345s8765c"; // Your API key from Elevenlabs -const voiceID = "pNInz6obpgDQGcFmaJgB"; // The ID of the voice you want to get -const fileName = "audio.mp3"; // The name of your audio file -const textInput = "mozzy is cool"; // The text you wish to convert to speech +const voice = new ElevenLabs( + { + apiKey: "0e2c037kl8561005671b1de345s8765c", // Your API key from Elevenlabs + } +); -voice.textToSpeech(apiKey, voiceID, fileName, textInput).then((res) => { +const voiceResponse = voice.getModels().then((res) => { console.log(res); }); ``` -Generating an audio stream from text +### Get User Info + +Getting user info associated with the API Key. ```javascript -const voice = require("elevenlabs-node"); -const fs = require("fs-extra"); +const ElevenLabs = require("elevenlabs-node"); + +const voice = new ElevenLabs( + { + apiKey: "0e2c037kl8561005671b1de345s8765c", // Your API key from Elevenlabs + } +); + +const voiceResponse = voice.getUserInfo().then((res) => { + console.log(res); +}); +``` + +### Get User Subscription + +Getting user subscription info associated with the API Key. + +```javascript +const ElevenLabs = require("elevenlabs-node"); + +const voice = new ElevenLabs( + { + apiKey: "0e2c037kl8561005671b1de345s8765c", // Your API key from Elevenlabs + } +); + +const voiceResponse = voice.getUserSubscription().then((res) => { + console.log(res); +}); +``` + +### Get Default Voice Settings + +Getting default voice settings. + +```javascript +const ElevenLabs = require("elevenlabs-node"); -const apiKey = "0e2c037kl8561005671b1de345s8765c"; // Your API key from Elevenlabs -const voiceID = "pNInz6obpgDQGcFmaJgB"; // The ID of the voice you want to get -const fileName = "audio.mp3"; // The name of your audio file -const textInput = "mozzy is cool"; // The text you wish to convert to speech +const voice = new ElevenLabs( + { + apiKey: "0e2c037kl8561005671b1de345s8765c", // Your API key from Elevenlabs + } +); -voice.textToSpeechStream(apiKey, voiceID, textInput).then((res) => { - res.pipe(fs.createWriteStream(fileName)); +const voiceResponse = voice.getDefaultVoiceSettings().then((res) => { + console.log(res); }); ``` diff --git a/index.js b/index.js index c1dace5..9d2e1b4 100644 --- a/index.js +++ b/index.js @@ -1,14 +1,34 @@ const axios = require("axios"); const fs = require("fs-extra"); -const elevenLabsAPI = "https://api.elevenlabs.io/v1"; +const elevenLabsAPIV1 = "https://api.elevenlabs.io/v1"; + /** -Function that converts text to speech and saves the audio file to the specified file name. +Function initializes ElevenLabs API. + +@param {Object} - An object containing the API Key and API Version [default: ElevenLabs V1]. +*/ +function ElevenLabs(options = { + apiKey: "", + voiceId: "" +}) { + + this.apiKey = options.apiKey ? options.apiKey : ""; + this.voiceId = options.voiceId ? options.voiceId : "pNInz6obpgDQGcFmaJgB"; // Default voice 'Adam' + + if(this.apiKey === ""){ + console.log("ERR: Missing API key"); + return; + } +} + + +/** -@param {string} apiKey - The API key to authenticate the request. +Function that converts text to speech and saves the audio file to the specified file name. -@param {string} voiceID - The ID of the voice to use for the text-to-speech conversion. +@param {string} voiceId - A different ID for the voice to use with the text-to-speech conversion. @param {string} fileName - The name of the file to save the audio data to. @@ -20,68 +40,80 @@ Function that converts text to speech and saves the audio file to the specified @param {string} modelId - The model to use for the text-to-speech conversion. If null, it will use elevenlab's default model. +@param {boolean} speakerBoost - The speaker boost setting for the voice. + @returns {Object} - An object containing the status of the operation. */ -const textToSpeech = async ( - apiKey, - voiceID, - fileName, - textInput, - stability, - similarityBoost, - modelId -) => { - try { - if (!apiKey || !voiceID || !fileName || !textInput) { - console.log("ERR: Missing parameter"); +ElevenLabs.prototype.textToSpeech = async function({ + voiceId, + fileName, + textInput, + stability, + similarityBoost, + modelId, + style, + speakerBoost +}) { + try { + if (!fileName) { + console.log("ERR: Missing parameter {fileName}"); + return; + } else if (!textInput) { + console.log("ERR: Missing parameter {textInput}"); + return; + } + + const voiceIdValue = voiceId ? voiceId : this.voiceId; + const voiceURL = `${elevenLabsAPIV1}/text-to-speech/${voiceIdValue}`; + const stabilityValue = stability ? stability : 0; + const similarityBoostValue = similarityBoost ? similarityBoost : 0; + const styleValue = style ? style : 0; + + const response = await axios({ + method: "POST", + url: voiceURL, + data: { + text: textInput, + voice_settings: { + stability: stabilityValue, + similarity_boost: similarityBoostValue, + style: styleValue, + use_speaker_boost: speakerBoost, + }, + model_id: modelId ? modelId : undefined, + }, + headers: { + Accept: "audio/mpeg", + "xi-api-key": this.apiKey, + "Content-Type": "application/json", + }, + responseType: "stream", + }); + + response.data.pipe(fs.createWriteStream(fileName)); + + const writeStream = fs.createWriteStream(fileName); + response.data.pipe(writeStream); + + return new Promise((resolve, reject) => { + const responseJson = { + status: "ok", + fileName: fileName + }; + writeStream.on('finish', () => resolve(responseJson)); + + writeStream.on('error', reject); + }); + } catch (error) { + console.log(error); } - - const voiceURL = `${elevenLabsAPI}/text-to-speech/${voiceID}`; - const stabilityValue = stability ? stability : 0; - const similarityBoostValue = similarityBoost ? similarityBoost : 0; - - const response = await axios({ - method: "POST", - url: voiceURL, - data: { - text: textInput, - voice_settings: { - stability: stabilityValue, - similarity_boost: similarityBoostValue, - }, - model_id: modelId ? modelId : undefined, - }, - headers: { - Accept: "audio/mpeg", - "xi-api-key": apiKey, - "Content-Type": "application/json", - }, - responseType: "stream", - }); - - response.data.pipe(fs.createWriteStream(fileName)); - - const writeStream = fs.createWriteStream(fileName); - response.data.pipe(writeStream); - - return new Promise((resolve, reject) => { - const responseJson = { status: "ok", fileName: fileName }; - writeStream.on('finish', () => resolve(responseJson)); - - writeStream.on('error', reject); - }); - } catch (error) { - console.log(error); - } }; /** Function that converts text to speech and returns a readable stream of the audio data. -@param {string} apiKey - The API key to authenticate the request. - -@param {string} voiceID - The ID of the voice to use for the text-to-speech conversion. +@param {string} voiceId - A different ID for the voice to use with the text-to-speech conversion. @param {string} textInput - The text to convert to speech. @@ -93,79 +125,81 @@ Function that converts text to speech and returns a readable stream of the audio @param {string} responseType - The response type for the text-to-speech function (arrayBuffer, stream, etc). If null, it will use 'stream' by default. +@param {boolean} speakerBoost - The speaker boost setting for the voice. + @returns {Object} - A readable stream of the audio data. */ -const textToSpeechStream = async ( - apiKey, - voiceID, - textInput, - stability, - similarityBoost, - modelId, - responseType -) => { - try { - if (!apiKey || !voiceID || !textInput) { - console.log("ERR: Missing parameter"); +ElevenLabs.prototype.textToSpeechStream = async function({ + voiceId, + textInput, + stability, + similarityBoost, + modelId, + responseType, + style, + speakerBoost +}) { + try { + if (!textInput) { + console.log("ERR: Missing parameter {textInput}"); + return; + } + + const voiceIdValue = voiceId ? voiceId : this.voiceId; + const voiceURL = `${elevenLabsAPIV1}/text-to-speech/${voiceIdValue}/stream`; + const stabilityValue = stability ? stability : 0; + const similarityBoostValue = similarityBoost ? similarityBoost : 0; + const styleValue = style ? style : 0; + + const response = await axios({ + method: "POST", + url: voiceURL, + data: { + text: textInput, + voice_settings: { + stability: stabilityValue, + similarity_boost: similarityBoostValue, + style: styleValue, + use_speaker_boost: speakerBoost, + }, + model_id: modelId ? modelId : undefined, + }, + headers: { + Accept: "audio/mpeg", + "xi-api-key": this.apiKey, + "Content-Type": "application/json", + }, + responseType: responseType ? responseType : "stream" + }); + + return response.data; + } catch (error) { + console.log(error); } - - const voiceURL = `${elevenLabsAPI}/text-to-speech/${voiceID}/stream`; - const stabilityValue = stability ? stability : 0; - const similarityBoostValue = similarityBoost ? similarityBoost : 0; - - const response = await axios({ - method: "POST", - url: voiceURL, - data: { - text: textInput, - voice_settings: { - stability: stabilityValue, - similarity_boost: similarityBoostValue, - }, - model_id: modelId ? modelId : undefined, - }, - headers: { - Accept: "audio/mpeg", - "xi-api-key": apiKey, - "Content-Type": "application/json", - }, - responseType: responseType ? responseType : "stream" - }); - - return response.data; - } catch (error) { - console.log(error); - } }; /** Function that returns an object containing the details for all the voices. -@param {string} apiKey - The API key to authenticate the request. - @returns {Object} - An object containing the list of voices and their details. */ -const getVoices = async (apiKey) => { - try { - if (!apiKey) { - console.log("ERR: Missing parameter"); +ElevenLabs.prototype.getVoices = async function() { + try { + const voiceURL = `${elevenLabsAPIV1}/voices`; + + const response = await axios({ + method: "GET", + url: voiceURL, + headers: { + "xi-api-key": this.apiKey, + }, + }); + + return response.data; + } catch (error) { + console.log(error); } - - const voiceURL = `${elevenLabsAPI}/voices`; - - const response = await axios({ - method: "GET", - url: voiceURL, - headers: { - "xi-api-key": apiKey, - }, - }); - - return response.data; - } catch (error) { - console.log(error); - } }; /** @@ -174,124 +208,119 @@ Function that returns an object containing the default settings for the voices. @returns {Object} - An object containing the default settings for the voices. */ -const getDefaultVoiceSettings = async () => { - try { - const voiceURL = `${elevenLabsAPI}/voices/settings/default`; - - const response = await axios({ - method: "GET", - url: voiceURL, - }); - - return response.data; - } catch (error) { - console.log(error); - } +ElevenLabs.prototype.getDefaultVoiceSettings = async function() { + try { + const voiceURL = `${elevenLabsAPIV1}/voices/settings/default`; + + const response = await axios({ + method: "GET", + url: voiceURL, + }); + + return response.data; + } catch (error) { + console.log(error); + } }; /** Function that returns an object containing the settings of the specified voice. -@param {string} apiKey - The API key to authenticate the request. - -@param {string} voiceID - The ID of the voice to use for the text-to-speech conversion. +@param {string} voiceId - The ID of the voice to use for the text-to-speech conversion. @returns {Object} - An object containing the settings of the specified voice. */ -const getVoiceSettings = async (apiKey, voiceID) => { - try { - if (!apiKey || !voiceID) { - console.log("ERR: Missing parameter"); +ElevenLabs.prototype.getVoiceSettings = async function({voiceId}) { + try { + if (!voiceId) { + console.log("ERR: Missing parameter {voiceId}"); + return; + } + + const voiceURL = `${elevenLabsAPIV1}/voices/${voiceId}/settings`; + + const response = await axios({ + method: "GET", + url: voiceURL, + headers: { + "xi-api-key": this.apiKey, + }, + }); + + return response.data; + } catch (error) { + console.log(error); } - - const voiceURL = `${elevenLabsAPI}/voices/${voiceID}/settings`; - - const response = await axios({ - method: "GET", - url: voiceURL, - headers: { - "xi-api-key": apiKey, - }, - }); - - return response.data; - } catch (error) { - console.log(error); - } }; /** Function that returns an object containing the details of the specified voice. -@param {string} apiKey - The API key to authenticate the request. - -@param {string} voiceID - The ID of the voice to use for the text-to-speech conversion. +@param {string} voiceId - The ID of the voice to use for the text-to-speech conversion. @returns {Object} - An object containing the details of the specified voice. */ -const getVoice = async (apiKey, voiceID) => { - try { - if (!apiKey || !voiceID) { - console.log("ERR: Missing parameter"); +ElevenLabs.prototype.getVoice = async function({voiceId}) { + try { + if (!voiceId) { + console.log("ERR: Missing parameter {voiceId}"); + return; + } + + const voiceURL = `${elevenLabsAPIV1}/voices/${voiceId}`; + + const response = await axios({ + method: "GET", + url: voiceURL, + headers: { + "xi-api-key": this.apiKey, + }, + }); + + return response.data; + } catch (error) { + console.log(error); } - - const voiceURL = `${elevenLabsAPI}/voices/${voiceID}`; - - const response = await axios({ - method: "GET", - url: voiceURL, - headers: { - "xi-api-key": apiKey, - }, - }); - - return response.data; - } catch (error) { - console.log(error); - } }; /** Function that returns an object containing the status of the delete operation. -@param {string} apiKey - The API key to authenticate the request. - -@param {string} voiceID - The ID of the voice to use for the text-to-speech conversion. +@param {string} voiceId - The ID of the voice to use for the text-to-speech conversion. @returns {Object} - An object containing the status of the delete operation. */ -const deleteVoice = async (apiKey, voiceID) => { - try { - if (!apiKey || !voiceID) { - console.log("ERR: Missing parameter"); +ElevenLabs.prototype.deleteVoice = async function({voiceId}) { + try { + if (!voiceId) { + console.log("ERR: Missing parameter {voiceId}"); + return; + } + + const voiceURL = `${elevenLabsAPIV1}/voices/${voiceId}`; + + const response = await axios({ + method: "DELETE", + url: voiceURL, + headers: { + "xi-api-key": this.apiKey, + }, + }); + + return response.data; + } catch (error) { + console.log(error); } - - const voiceURL = `${elevenLabsAPI}/voices/${voiceID}`; - - const response = await axios({ - method: "DELETE", - url: voiceURL, - headers: { - "xi-api-key": apiKey, - }, - }); - - return response.data; - } catch (error) { - console.log(error); - } }; /** Function that returns an object containing the status of the edit operation. -@param {string} apiKey - The API key to authenticate the request. - -@param {string} voiceID - The ID of the voice to use for the text-to-speech conversion. +@param {string} voiceId - The ID of the voice to use for the text-to-speech conversion. @param {number} stability - The stability setting for the voice. @@ -299,139 +328,109 @@ Function that returns an object containing the status of the edit operation. @returns {Object} - An object containing the status of the edit operation. */ -const editVoiceSettings = async ( - apiKey, - voiceID, - stability, - similarityBoost -) => { - try { - if (!apiKey || !voiceID) { - console.log("ERR: Missing parameter"); +ElevenLabs.prototype.editVoiceSettings = async function({ + voiceId, + stability, + similarityBoost +}) { + try { + if (!voiceId) { + console.log("ERR: Missing parameter {voiceId}"); + return; + } + + const voiceURL = `${elevenLabsAPIV1}/voices/${voiceId}/settings/edit`; + const stabilityValue = stability ? stability : 0; + const similarityBoostValue = similarityBoost ? similarityBoost : 0; + + const response = await axios({ + method: "POST", + url: voiceURL, + data: { + stability: stabilityValue, + similarity_boost: similarityBoostValue, + }, + headers: { + "xi-api-key": this.apiKey, + }, + }); + + return response.data; + } catch (error) { + console.log(error); } - - const voiceURL = `${elevenLabsAPI}/voices/${voiceID}/settings/edit`; - const stabilityValue = stability ? stability : 0; - const similarityBoostValue = similarityBoost ? similarityBoost : 0; - - const response = await axios({ - method: "POST", - url: voiceURL, - data: { - stability: stabilityValue, - similarity_boost: similarityBoostValue, - }, - headers: { - "xi-api-key": apiKey, - }, - }); - - return response.data; - } catch (error) { - console.log(error); - } }; /** Function that returns an object containing the list of voice models. -@param {string} apiKey - The API key to authenticate the request. - @returns {Object} - An object containing the list of voice models and their details. */ -const getModels = async (apiKey) => { - try { - if (!apiKey) { - console.log("ERR: Missing parameter"); +ElevenLabs.prototype.getModels = async function() { + try { + const voiceURL = `${elevenLabsAPIV1}/models`; + + const response = await axios({ + method: "GET", + url: voiceURL, + headers: { + "xi-api-key": this.apiKey, + }, + }); + + return response.data; + } catch (error) { + console.log(error); } - - const voiceURL = `${elevenLabsAPI}/models`; - - const response = await axios({ - method: "GET", - url: voiceURL, - headers: { - "xi-api-key": apiKey, - }, - }); - - return response.data; - } catch (error) { - console.log(error); - } }; /** Function that returns the user details. -@param {string} apiKey - The API key to authenticate the request. - @returns {Object} - An object containing the user details. */ -const getUserInfo = async (apiKey) => { - try { - if (!apiKey) { - console.log("ERR: Missing parameter"); +ElevenLabs.prototype.getUserInfo = async function() { + try { + const voiceURL = `${elevenLabsAPIV1}/user`; + + const response = await axios({ + method: "GET", + url: voiceURL, + headers: { + "xi-api-key": this.apiKey, + }, + }); + + return response.data; + } catch (error) { + console.log(error); } - - const voiceURL = `${elevenLabsAPI}/user`; - - const response = await axios({ - method: "GET", - url: voiceURL, - headers: { - "xi-api-key": apiKey, - }, - }); - - return response.data; - } catch (error) { - console.log(error); - } }; /** Function that returns the user subscription details. -@param {string} apiKey - The API key to authenticate the request. - @returns {Object} - An object containing the user subscription details. */ -const getUserSubscription = async (apiKey) => { - try { - if (!apiKey) { - console.log("ERR: Missing parameter"); +ElevenLabs.prototype.getUserSubscription = async function() { + try { + const voiceURL = `${elevenLabsAPIV1}/user/subscription`; + + const response = await axios({ + method: "GET", + url: voiceURL, + headers: { + "xi-api-key": this.apiKey, + }, + }); + + return response.data; + } catch (error) { + console.log(error); } - - const voiceURL = `${elevenLabsAPI}/user/subscription`; - - const response = await axios({ - method: "GET", - url: voiceURL, - headers: { - "xi-api-key": apiKey, - }, - }); - - return response.data; - } catch (error) { - console.log(error); - } }; -module.exports = { - textToSpeech: textToSpeech, - textToSpeechStream: textToSpeechStream, - getVoices: getVoices, - getDefaultVoiceSettings: getDefaultVoiceSettings, - getVoiceSettings: getVoiceSettings, - getVoice: getVoice, - deleteVoice: deleteVoice, - editVoiceSettings: editVoiceSettings, - getModels: getModels, - getUserInfo: getUserInfo, - getUserSubscription: getUserSubscription, -}; +module.exports = ElevenLabs; \ No newline at end of file diff --git a/package.json b/package.json index a881de4..27e4929 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "elevenlabs-node", - "version": "1.2.0", + "version": "2.0.0", "description": "This is an open source Eleven Labs NodeJS package for converting text to speech using the Eleven Labs API", "main": "index.js", "scripts": { - "test": "jest --testPathPattern=test --detectOpenHandles --forceExit" + "test": "jest --testPathPattern=test --forceExit" }, "repository": { "type": "git", @@ -30,6 +30,7 @@ "fs-extra": "^11.1.1" }, "devDependencies": { + "dotenv": "^16.3.1", "eslint": "^8.45.0", "jest": "^29.6.1" } diff --git a/test/app.test.js b/test/app.test.js index de2764a..24ca6cb 100644 --- a/test/app.test.js +++ b/test/app.test.js @@ -1,13 +1,23 @@ -const script = require('../index.js'); +const ElevenLabs = require('../index.js'); +require('dotenv').config() const apiKey = process.env.ELEVENLABS_API_KEY; -const voiceID = process.env.ELEVENLABS_VOICE_ID; +const voiceId = process.env.ELEVENLABS_VOICE_ID; const fileName = 'audio.mp3'; const textInput = 'mozzy is cool'; const stability = '0.5'; const similarityBoost = '0.5'; const modelId = 'eleven_multilingual_v1'; const responseType = 'stream'; +const style = 0; +const speakerBoost = true; + +const script = new ElevenLabs( + { + apiKey: apiKey, + voiceId: voiceId + } +); describe("Eleven Labs Node Unit Test", () => { @@ -15,7 +25,7 @@ describe("Eleven Labs Node Unit Test", () => { test("Test textToSpeech", async () => { // Execute test await process.nextTick(() => {}); - const response = await script.textToSpeech(apiKey, voiceID, fileName, textInput, stability, similarityBoost, modelId); + const response = await script.textToSpeech({voiceId, fileName, textInput, stability, similarityBoost, modelId, style, speakerBoost}); // Response check expect(response.status).toEqual('ok'); @@ -25,7 +35,7 @@ describe("Eleven Labs Node Unit Test", () => { test("Test textToSpeechStream", async () => { // Execute test await process.nextTick(() => {}); - const response = await script.textToSpeechStream(apiKey, voiceID, textInput, stability, similarityBoost, modelId, responseType); + const response = await script.textToSpeechStream({voiceId, textInput, stability, similarityBoost, modelId, responseType, style, speakerBoost}); // Response check expect(!response).toBeFalsy(); @@ -35,7 +45,7 @@ describe("Eleven Labs Node Unit Test", () => { test("Test getVoices", async () => { // Execute test await process.nextTick(() => {}); - const response = await script.getVoices(apiKey); + const response = await script.getVoices(); // Response check expect(response.voices).toBeTruthy(); @@ -56,7 +66,7 @@ describe("Eleven Labs Node Unit Test", () => { test("Test getVoiceSettings", async () => { // Execute test await process.nextTick(() => {}); - const response = await script.getVoiceSettings(apiKey, voiceID); + const response = await script.getVoiceSettings({voiceId}); // Response check expect(response.stability).toBeTruthy(); @@ -67,7 +77,7 @@ describe("Eleven Labs Node Unit Test", () => { test("Test getVoice", async () => { // Execute test await process.nextTick(() => {}); - const response = await script.getVoice(apiKey, voiceID); + const response = await script.getVoice({voiceId}); // Response check expect(response.voice_id).toBeTruthy(); @@ -77,7 +87,7 @@ describe("Eleven Labs Node Unit Test", () => { test("Test editVoiceSettings", async () => { // Execute test await process.nextTick(() => {}); - const response = await script.editVoiceSettings(apiKey, voiceID, stability, similarityBoost); + const response = await script.editVoiceSettings({voiceId, stability, similarityBoost}); // Response check expect(response.status).toEqual('ok'); @@ -87,7 +97,7 @@ describe("Eleven Labs Node Unit Test", () => { test("Test getModels", async () => { // Execute test await process.nextTick(() => {}); - const response = await script.getModels(apiKey); + const response = await script.getModels(); // Response check expect(response).toBeTruthy(); @@ -97,7 +107,7 @@ describe("Eleven Labs Node Unit Test", () => { test("Test getUserInfo", async () => { // Execute test await process.nextTick(() => {}); - const response = await script.getUserInfo(apiKey); + const response = await script.getUserInfo(); // Response check expect(response.xi_api_key).toEqual(apiKey); @@ -107,19 +117,32 @@ describe("Eleven Labs Node Unit Test", () => { test("Test getUserSubscription", async () => { // Execute test await process.nextTick(() => {}); - const response = await script.getUserSubscription(apiKey); + const response = await script.getUserSubscription(); // Response check expect(response.status).toBeTruthy(); }); +}); + +describe("Required Variables Test", () => { + + // textToSpeech test + test("Test textToSpeech", async () => { + // Execute test + await process.nextTick(() => {}); + const response = await script.textToSpeech({fileName, textInput}); + + // Response check + expect(response.status).toEqual('ok'); + }); - // deleteVoice test - // TODO: Add create voice test first - // test("Test deleteVoice", async () => { - // // Execute test - // const response = await script.deleteVoice(apiKey, voiceID); + // textToSpeechStream test + test("Test textToSpeechStream", async () => { + // Execute test + await process.nextTick(() => {}); + const response = await script.textToSpeechStream({textInput}); - // // Response check - // expect(response.status).toEqual('ok'); - // }); + // Response check + expect(!response).toBeFalsy(); + }); }); \ No newline at end of file