aiTextToSpeech file upload
parent
51c520108b
commit
411766987c
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
module.exports = aiTextToSpeech;
|
||||
|
|
19
yarn.lock
19
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"
|
||||
|
|
Loading…
Reference in New Issue