From 012b9dc4a100b5b545c90f59174a1388e3babd46 Mon Sep 17 00:00:00 2001 From: Felix Waweru Date: Thu, 7 Sep 2023 08:47:50 +0000 Subject: [PATCH 01/11] feat: added get models and customizable stream --- index.js | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 5be5c81..1624980 100644 --- a/index.js +++ b/index.js @@ -85,6 +85,8 @@ Function that converts text to speech and returns a readable stream of the audio @param {string} modelId - The model to use for the text-to-speech conversion. If null, it will use elevenlab's default model. +@param {string} responseType - The response type for the text-to-speech function (arrayBuffer, stream, etc). If null, it will use 'stream' by default. + @returns {Object} - A readable stream of the audio data. */ const textToSpeechStream = async ( @@ -93,7 +95,8 @@ const textToSpeechStream = async ( textInput, stability, similarityBoost, - modelId + modelId, + responseType ) => { try { if (!apiKey || !voiceID || !textInput) { @@ -120,7 +123,7 @@ const textToSpeechStream = async ( "xi-api-key": apiKey, "Content-Type": "application/json", }, - responseType: "stream", + responseType: responseType ? responseType : "stream" }); return response.data; @@ -323,6 +326,36 @@ const editVoiceSettings = async ( } }; +/** + +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"); + } + + 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); + } +}; + module.exports = { textToSpeech: textToSpeech, textToSpeechStream: textToSpeechStream, @@ -332,4 +365,5 @@ module.exports = { getVoice: getVoice, deleteVoice: deleteVoice, editVoiceSettings: editVoiceSettings, + getModels: getModels, }; From 0d79b8c6086624e42ab36d82188306b9984db173 Mon Sep 17 00:00:00 2001 From: Felix Waweru Date: Thu, 7 Sep 2023 08:55:11 +0000 Subject: [PATCH 02/11] chore: semver --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b2eca81..613c3fc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "elevenlabs-node", - "version": "1.1.3", + "version": "1.2.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": { From d7b046dcb03702f59f2b0972704f538d9ae831a3 Mon Sep 17 00:00:00 2001 From: Felix Waweru Date: Thu, 7 Sep 2023 08:57:49 +0000 Subject: [PATCH 03/11] feat: added getModels to test --- test/app.test.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/app.test.js b/test/app.test.js index eb741b3..15e3a5b 100644 --- a/test/app.test.js +++ b/test/app.test.js @@ -75,6 +75,15 @@ describe("Eleven Labs Node Unit Test", () => { expect(response.status).toEqual('ok'); }); + // getModels test + test("Test getModels", async () => { + // Execute test + const response = await script.getModels(apiKey); + + // Response check + expect(response).toBeTruthy(); + }); + // deleteVoice test // TODO: Add create voice test first // test("Test deleteVoice", async () => { From 270830c72b2bfb1b13459973854fd5be6403cfec Mon Sep 17 00:00:00 2001 From: Felix Waweru Date: Thu, 7 Sep 2023 09:10:57 +0000 Subject: [PATCH 04/11] fix: fixed textToSpeech file creation wait --- index.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 1624980..cd57cb7 100644 --- a/index.js +++ b/index.js @@ -61,9 +61,15 @@ const textToSpeech = async ( response.data.pipe(fs.createWriteStream(fileName)); - return { - status: "ok", - }; + 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); } From 40484a0399c1eca5634120cdddde87c703439c63 Mon Sep 17 00:00:00 2001 From: Felix Waweru Date: Thu, 7 Sep 2023 09:14:25 +0000 Subject: [PATCH 05/11] feat: added responseType to test --- test/app.test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/app.test.js b/test/app.test.js index 15e3a5b..4cf286c 100644 --- a/test/app.test.js +++ b/test/app.test.js @@ -7,6 +7,7 @@ const textInput = 'mozzy is cool'; const stability = '0.5'; const similarityBoost = '0.5'; const modelId = 'eleven_multilingual_v1'; +const responseType = 'stream'; describe("Eleven Labs Node Unit Test", () => { @@ -22,7 +23,7 @@ describe("Eleven Labs Node Unit Test", () => { // textToSpeechStream test test("Test textToSpeechStream", async () => { // Execute test - const response = await script.textToSpeechStream(apiKey, voiceID, textInput, stability, similarityBoost, modelId); + const response = await script.textToSpeechStream(apiKey, voiceID, textInput, stability, similarityBoost, modelId, responseType); // Response check expect(!response).toBeFalsy(); From 4f68d6153e3abad7a3a6f492323d1594dbd53d92 Mon Sep 17 00:00:00 2001 From: Felix Waweru Date: Thu, 7 Sep 2023 09:24:12 +0000 Subject: [PATCH 06/11] feat: updated test --- test/app.test.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/app.test.js b/test/app.test.js index 4cf286c..3f066ac 100644 --- a/test/app.test.js +++ b/test/app.test.js @@ -14,6 +14,7 @@ describe("Eleven Labs Node Unit Test", () => { // textToSpeech test test("Test textToSpeech", async () => { // Execute test + await process.nextTick(() => {}); const response = await script.textToSpeech(apiKey, voiceID, fileName, textInput, stability, similarityBoost, modelId); // Response check @@ -23,6 +24,7 @@ describe("Eleven Labs Node Unit Test", () => { // textToSpeechStream test test("Test textToSpeechStream", async () => { // Execute test + await process.nextTick(() => {}); const response = await script.textToSpeechStream(apiKey, voiceID, textInput, stability, similarityBoost, modelId, responseType); // Response check @@ -32,6 +34,7 @@ describe("Eleven Labs Node Unit Test", () => { // getVoices test test("Test getVoices", async () => { // Execute test + await process.nextTick(() => {}); const response = await script.getVoices(apiKey); // Response check @@ -41,6 +44,7 @@ describe("Eleven Labs Node Unit Test", () => { // getDefaultVoiceSettings test test("Test getDefaultVoiceSettings", async () => { // Execute test + await process.nextTick(() => {}); const response = await script.getDefaultVoiceSettings(); // Response check @@ -51,6 +55,7 @@ describe("Eleven Labs Node Unit Test", () => { // getVoiceSettings test test("Test getVoiceSettings", async () => { // Execute test + await process.nextTick(() => {}); const response = await script.getVoiceSettings(apiKey, voiceID); // Response check @@ -61,6 +66,7 @@ describe("Eleven Labs Node Unit Test", () => { // getVoice test test("Test getVoice", async () => { // Execute test + await process.nextTick(() => {}); const response = await script.getVoice(apiKey, voiceID); // Response check @@ -70,6 +76,7 @@ describe("Eleven Labs Node Unit Test", () => { // editVoiceSettings test test("Test editVoiceSettings", async () => { // Execute test + await process.nextTick(() => {}); const response = await script.editVoiceSettings(apiKey, voiceID, stability, similarityBoost); // Response check @@ -79,6 +86,7 @@ describe("Eleven Labs Node Unit Test", () => { // getModels test test("Test getModels", async () => { // Execute test + await process.nextTick(() => {}); const response = await script.getModels(apiKey); // Response check From 4e5fd5deed005f6f075a4dc76ac716f74adbde9f Mon Sep 17 00:00:00 2001 From: Felix Waweru Date: Thu, 7 Sep 2023 09:25:27 +0000 Subject: [PATCH 07/11] feat: updated test command --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 613c3fc..a881de4 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "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" + "test": "jest --testPathPattern=test --detectOpenHandles --forceExit" }, "repository": { "type": "git", From 8a8617e64dc3aa9452314664adeb3fffadee72d8 Mon Sep 17 00:00:00 2001 From: Felix Waweru Date: Thu, 7 Sep 2023 09:38:03 +0000 Subject: [PATCH 08/11] feat: added user info functionality --- index.js | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/index.js b/index.js index cd57cb7..c1dace5 100644 --- a/index.js +++ b/index.js @@ -362,6 +362,66 @@ const getModels = async (apiKey) => { } }; +/** + +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"); + } + + 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"); + } + + 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, @@ -372,4 +432,6 @@ module.exports = { deleteVoice: deleteVoice, editVoiceSettings: editVoiceSettings, getModels: getModels, + getUserInfo: getUserInfo, + getUserSubscription: getUserSubscription, }; From fb70fdd094809f164916e65d33886f05bf3787a8 Mon Sep 17 00:00:00 2001 From: Felix Waweru Date: Thu, 7 Sep 2023 09:38:29 +0000 Subject: [PATCH 09/11] feat: added user info function test --- test/app.test.js | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/test/app.test.js b/test/app.test.js index 3f066ac..de2764a 100644 --- a/test/app.test.js +++ b/test/app.test.js @@ -93,8 +93,28 @@ describe("Eleven Labs Node Unit Test", () => { expect(response).toBeTruthy(); }); - // deleteVoice test - // TODO: Add create voice test first + // getUserInfo test + test("Test getUserInfo", async () => { + // Execute test + await process.nextTick(() => {}); + const response = await script.getUserInfo(apiKey); + + // Response check + expect(response.xi_api_key).toEqual(apiKey); + }); + + // getUserSubscription test + test("Test getUserSubscription", async () => { + // Execute test + await process.nextTick(() => {}); + const response = await script.getUserSubscription(apiKey); + + // Response check + expect(response.status).toBeTruthy(); + }); + + // deleteVoice test + // TODO: Add create voice test first // test("Test deleteVoice", async () => { // // Execute test // const response = await script.deleteVoice(apiKey, voiceID); From fff79fad4d6263fde09ec963be58bf0d7836aa35 Mon Sep 17 00:00:00 2001 From: Felix Waweru Date: Thu, 7 Sep 2023 09:41:07 +0000 Subject: [PATCH 10/11] docs: updated readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 39aa015..701375c 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,9 @@ This is an open source Eleven Labs NodeJS package for converting text to speech | `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` | ## Requirements From 1be359aad73c94e3488bf9ba1e11de472752b9ac Mon Sep 17 00:00:00 2001 From: Felix Waweru Date: Thu, 7 Sep 2023 09:49:55 +0000 Subject: [PATCH 11/11] feat: test branch merge workflow --- .github/workflows/pre-test.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/pre-test.yml diff --git a/.github/workflows/pre-test.yml b/.github/workflows/pre-test.yml new file mode 100644 index 0000000..f0891cd --- /dev/null +++ b/.github/workflows/pre-test.yml @@ -0,0 +1,23 @@ +# This workflow will run tests using Jest +# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages + +name: NPM Package Test + +on: + push: + branches: + - test + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 16 + - run: npm install + - run: npm test + env: + ELEVENLABS_API_KEY: ${{ secrets.ELEVENLABS_API_KEY }} + ELEVENLABS_VOICE_ID: ${{ secrets.ELEVENLABS_VOICE_ID }} \ No newline at end of file