diff --git a/package-lock.json b/package-lock.json index 3a3f093..e43bbed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "dependencies": { "aws-sdk": "^2.1669.0", + "axios": "^1.7.7", "bcryptjs": "^2.4.3", "body-parser": "^1.20.2", "compression": "^1.7.4", @@ -19,6 +20,7 @@ "express": "^4.17.1", "express-mongo-sanitize": "^2.0.0", "express-rate-limit": "^5.0.0", + "form-data": "^4.0.1", "helmet": "^4.1.0", "http-status": "^1.4.0", "joi": "^17.3.0", @@ -2262,7 +2264,6 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true, "license": "MIT" }, "node_modules/atob": { @@ -2347,6 +2348,17 @@ "dev": true, "license": "MIT" }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/babel-jest": { "version": "26.6.3", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz", @@ -3153,7 +3165,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -3695,7 +3706,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -5043,10 +5053,9 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", diff --git a/package.json b/package.json index 550ef98..236b74e 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ ], "dependencies": { "aws-sdk": "^2.1669.0", + "axios": "^1.7.7", "bcryptjs": "^2.4.3", "body-parser": "^1.20.2", "compression": "^1.7.4", @@ -58,6 +59,7 @@ "express": "^4.17.1", "express-mongo-sanitize": "^2.0.0", "express-rate-limit": "^5.0.0", + "form-data": "^4.0.1", "helmet": "^4.1.0", "http-status": "^1.4.0", "joi": "^17.3.0", diff --git a/src/routes/api/aiTextToSpeech.js b/src/routes/api/aiTextToSpeech.js index 1337be1..1315b34 100644 --- a/src/routes/api/aiTextToSpeech.js +++ b/src/routes/api/aiTextToSpeech.js @@ -1,5 +1,7 @@ +const axios = require('axios'); +const AWS = require('aws-sdk'); + const aiTextToSpeech = async (req, res) => { - const AWS = require('aws-sdk'); AWS.config.update({ region: 'ap-south-1', accessKeyId: process.env.AWS_polly2_ACCESS_KEY_ID, @@ -7,8 +9,6 @@ const aiTextToSpeech = async (req, res) => { }); const polly = new AWS.Polly(); - const s3 = new AWS.S3(); - const BUCKET_NAME = 'polly-bs'; const voiceIdMap = { "Ava": "Ivy", "Monstero": "Justin", @@ -19,7 +19,7 @@ const aiTextToSpeech = async (req, res) => { const { text, voiceId: frontendVoiceId } = req.body; - if (!text || !frontendVoiceId) { + if (!text || !frontendVoiceId) { return res.status(400).json({ error: 'Text and voiceId are required' }); } @@ -31,68 +31,59 @@ const aiTextToSpeech = async (req, res) => { const params = { Text: text, OutputFormat: 'mp3', - Engine:'neural', + Engine: 'neural', VoiceId: pollyVoiceId, }; try { + // Generate a folder name based on current timestamp and random digits function generateTimestampWithRandomDigits() { - // Get the current date and time const now = new Date(); - - // Format the current date as YYYY-MM-DD_HH-mm-ss const formattedDate = now.toISOString().replace('T', '_').replace(/\..+/, '').replace(/:/g, '-'); - - // Generate 4 random digits const randomDigits = Math.floor(Math.random() * 10000).toString().padStart(4, '0'); - - // Concatenate the formatted date with the random digits return `${formattedDate}_${randomDigits}`; - } - - // Example usage - const folder = generateTimestampWithRandomDigits(); + } - // Generate timestamp for folder structure - // const timestamp = moment().format('YYYY-MM-DD_HH-mm-ss'); + const folder = generateTimestampWithRandomDigits(); const folderName = `audio_files/${folder}`; // Request Polly to synthesize speech const data = await polly.synthesizeSpeech(params).promise(); const audioBuffer = data.AudioStream; - // Define S3 paths - const audioFilePath = `${folderName}/speech.mp3`; - const textFilePath = `${folderName}/text.txt`; + // Prepare the text file as a buffer + const textBuffer = Buffer.from(text, 'utf-8'); - // Upload audio file to S3 - await s3.upload({ - Bucket: BUCKET_NAME, - Key: audioFilePath, - Body: audioBuffer, - ContentType: 'audio/mpeg' - }).promise(); + // Prepare the form data to send via POST request + const formData = new FormData(); + formData.append('file1', audioBuffer, 'speech.mp3'); + formData.append('file2', textBuffer, 'text.txt'); + formData.append('folder', folderName); // Send folder name as form data + formData.append('bucket', 'beanstalkedu-test'); // Adjust bucket if needed - // Upload text file to S3 - await s3.upload({ - Bucket: BUCKET_NAME, - Key: textFilePath, - Body: text, - ContentType: 'text/plain' - }).promise(); + // Send the POST request to upload the files + const response = await axios.post( + 'https://preschool-curriculum.in/api/one/v1/file/upload', + formData, + { + headers: { + 'Authorization': `Bearer ${process.env.BEARER_TOKEN}`, + ...formData.getHeaders() // Ensure FormData headers are included + } + } + ); - // Return success response with S3 paths + // Return success response with URLs from the response res.json({ - message: 'Speech generated and saved to S3 successfully', - audioFileUrl: `https://${BUCKET_NAME}.s3.amazonaws.com/${audioFilePath}`, - textFileUrl: `https://${BUCKET_NAME}.s3.amazonaws.com/${textFilePath}` + message: 'Speech generated and saved successfully', + fileUrls: response.data.urls, + fileKeys: response.data.data }); + } catch (error) { - console.error('Error generating speech or saving to S3:', error); - res.status(500).json({ error: 'Error generating speech or saving to S3' }); + console.error('Error generating speech or uploading files:', error); + res.status(500).json({ error: 'Error generating speech or uploading files' }); } +}; - -} - -module.exports = aiTextToSpeech; \ No newline at end of file +module.exports = aiTextToSpeech; diff --git a/yarn.lock b/yarn.lock index e474a08..64a04d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1296,6 +1296,15 @@ aws4@^1.8.0: resolved "https://registry.npmjs.org/aws4/-/aws4-1.13.1.tgz" integrity sha512-u5w79Rd7SU4JaIlA/zFqG+gOiuq25q5VLyZ8E+ijJeILuTxVzZgp2CaGw/UTw6pXYN9XMO9yiqj/nEHmhTG5CA== +axios@^1.7.7: + version "1.7.7" + resolved "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz" + integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + babel-jest@^26.6.3: version "26.6.3" resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz" @@ -2974,7 +2983,7 @@ fn.name@1.x.x: resolved "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.14.0: +follow-redirects@^1.14.0, follow-redirects@^1.15.6: version "1.15.6" resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz" integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== @@ -3005,10 +3014,10 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== +form-data@^4.0.0, form-data@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz" + integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw== dependencies: asynckit "^0.4.0" combined-stream "^1.0.8"