armyan tts add
This commit is contained in:
57
bot.js
57
bot.js
@@ -4,6 +4,18 @@ import axios from "axios";
|
||||
import FormData from 'form-data';
|
||||
import fs from 'fs';
|
||||
|
||||
import ffmpeg from 'fluent-ffmpeg';
|
||||
|
||||
function convertToOgg(inputPath, outputPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
ffmpeg(inputPath)
|
||||
.audioCodec('libopus')
|
||||
.format('ogg')
|
||||
.on('end', () => resolve())
|
||||
.on('error', (err) => reject(err))
|
||||
.save(outputPath);
|
||||
});
|
||||
}
|
||||
|
||||
import { UserRepository } from "./user.repository.js";
|
||||
|
||||
@@ -30,6 +42,9 @@ bot.onText(/\/info/, (msg)=>{
|
||||
bot.onText(/\/armyan (.+)/, async (msg, match) => {
|
||||
const chatId = msg.chat.id;
|
||||
const textAfterCommand = match[1];
|
||||
const response = await textToArmyan(textAfterCommand);
|
||||
await convertToOgg(`voices/${response.file}.wav`, `voices/${response.file}.ogg`);
|
||||
bot.sendVoice(chatId, `voices/${response.file}.ogg`);
|
||||
})
|
||||
|
||||
|
||||
@@ -85,7 +100,7 @@ bot.on('message', async(msg) => {
|
||||
form.append('file', fs.createReadStream(filePath));
|
||||
|
||||
const response = await axios.post(
|
||||
'http://10.8.1.2:3000/upload',
|
||||
`http://${process.env.API_URL}:${process.env.API_PORT}/upload`,
|
||||
form,
|
||||
{
|
||||
headers: form.getHeaders()
|
||||
@@ -174,3 +189,43 @@ async function getAIResponse(message, context) {
|
||||
console.error('Ошибка при получении ответа от AI:', err);
|
||||
}
|
||||
}
|
||||
|
||||
async function textToArmyan(message) {
|
||||
try {
|
||||
const optionsArmyan = {
|
||||
method: 'POST',
|
||||
url: `https://agent.timeweb.cloud/api/v1/cloud-ai/agents/${accessId}/call`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${tokenAi}`,
|
||||
'x-proxy-source': '',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: {
|
||||
message: `Переведи текст на армянский, ничего не добаляй от себя, просто переведи: '${message}'`,
|
||||
parent_message_id: ''
|
||||
}
|
||||
}
|
||||
|
||||
const responseArmyan = await axios.request(optionsArmyan);
|
||||
|
||||
const options = {
|
||||
method: 'POST',
|
||||
url: `http://${process.env.API_URL}:${process.env.API_PORT}/voice/start`,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: {
|
||||
text: responseArmyan.data.message
|
||||
}
|
||||
}
|
||||
const response = await axios.request(options);
|
||||
if (response.status === 200) {
|
||||
return response.data;
|
||||
} else {
|
||||
console.error('Ошибка при получении ответа от AI:', response.data);
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.error('Ошибка при получении ответа от AI:', err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,3 +7,7 @@ DATABASE_URL =
|
||||
DATABASE_USER =
|
||||
DATABASE_PASSWORD =
|
||||
GEMINI_KEY =
|
||||
PORT = 3000
|
||||
JWT_SECRET = super_secret_key_123
|
||||
API_URL = 10.8.1.3
|
||||
API_PORT = 3000
|
||||
@@ -17,6 +17,7 @@
|
||||
"cors": "^2.8.6",
|
||||
"dotenv": "^17.2.3",
|
||||
"express": "^5.2.1",
|
||||
"fluent-ffmpeg": "^2.1.3",
|
||||
"form-data": "^4.0.5",
|
||||
"jsonwebtoken": "^9.0.3",
|
||||
"multer": "^2.0.2",
|
||||
|
||||
@@ -8,7 +8,6 @@ import { GoogleGenAI, createUserContent, createPartFromUri } from "@google/genai
|
||||
import dotenv from "dotenv";
|
||||
dotenv.config();
|
||||
|
||||
import wav from 'wav';
|
||||
import { text } from "stream/consumers";
|
||||
|
||||
async function shneine(fileName, mimeType) {
|
||||
@@ -58,7 +57,7 @@ const storage = multer.diskStorage({
|
||||
const upload = multer({
|
||||
storage,
|
||||
limits: {
|
||||
fileSize: 50 * 1024 * 1024, // 5 MB
|
||||
fileSize: 500 * 1024 * 1024, // 5 MB
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -2,12 +2,15 @@ import { Router } from "express";
|
||||
import multer from "multer";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import wav from "wav";
|
||||
const router = Router();
|
||||
|
||||
import { GoogleGenAI, createUserContent, createPartFromUri } from "@google/genai";
|
||||
import dotenv from "dotenv";
|
||||
dotenv.config();
|
||||
|
||||
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_KEY });
|
||||
|
||||
async function saveWaveFile(
|
||||
filename,
|
||||
pcmData,
|
||||
@@ -30,15 +33,40 @@ async function saveWaveFile(
|
||||
});
|
||||
}
|
||||
|
||||
async function fawatafa() {
|
||||
const voicesDir = "voices";
|
||||
if (!fs.existsSync(voicesDir)) {
|
||||
fs.mkdirSync(voicesDir);
|
||||
}
|
||||
|
||||
const storage = multer.diskStorage({
|
||||
destination: (req, file, cb) => {
|
||||
cb(null, voicesDir);
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
const uniqueName =
|
||||
Date.now() + "-" + Math.round(Math.random() * 1e9);
|
||||
|
||||
const ext = path.extname(file.originalname);
|
||||
cb(null, uniqueName + ext);
|
||||
},
|
||||
});
|
||||
|
||||
const upload = multer({
|
||||
storage,
|
||||
limits: {
|
||||
fileSize: 500 * 1024 * 1024, // 50 MB
|
||||
},
|
||||
});
|
||||
|
||||
async function fawatafa(text) {
|
||||
const response = await ai.models.generateContent({
|
||||
model: "gemini-2.5-flash-preview-tts",
|
||||
contents: [{ parts: [{ text: `Say aggresive: А перекинул я этот пост, потому что его Саша переслал. И вот вдумайся: Саше 30 лет, и вот на него это полностью работает. То есть он верит, что можно заставить Дурова открыть представительство в России, и это снимет к нему все вопросы, и Телеграм оставят незаблокированным` }] }],
|
||||
contents: [{ parts: [{ text: `Say aggresive: ${text}` }] }],
|
||||
config: {
|
||||
responseModalities: ['AUDIO'],
|
||||
speechConfig: {
|
||||
voiceConfig: {
|
||||
prebuiltVoiceConfig: { voiceName: 'Leda' },
|
||||
prebuiltVoiceConfig: { voiceName: 'Sadaltager' },
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -46,14 +74,18 @@ async function fawatafa() {
|
||||
|
||||
const data = response.candidates?.[0]?.content?.parts?.[0]?.inlineData?.data;
|
||||
const audioBuffer = Buffer.from(data, 'base64');
|
||||
|
||||
const fileName = 'outMarat5.wav';
|
||||
await saveWaveFile(fileName, audioBuffer);
|
||||
const file = Date.now() + "-" + Math.round(Math.random() * 1e9);
|
||||
const fileName = `${file}.wav`;
|
||||
const filePath = path.join(voicesDir, fileName);
|
||||
await saveWaveFile(filePath, audioBuffer);
|
||||
return file;
|
||||
}
|
||||
|
||||
router.post('/voice', async(req, res) => {
|
||||
router.post('/start', async (req, res) => {
|
||||
try {
|
||||
|
||||
const text = req.body.text;
|
||||
const fileName = await fawatafa(text);
|
||||
res.status(200).json({ message: 'Голосовое сообщение успешно обработано', file: fileName });
|
||||
} catch (err) {
|
||||
console.error('Ошибка при обработке голосового сообщения:', err);
|
||||
res.status(500).json({ message: 'Ошибка при обработке голосового сообщения' });
|
||||
|
||||
@@ -6,7 +6,7 @@ import cors from 'cors'
|
||||
import authRoutes from "./routes/auth.js";
|
||||
import userRoutes from "./routes/user.js";
|
||||
import uploadRoutes from "./routes/upload.js";
|
||||
|
||||
import voiceRoutes from "./routes/voice.js";
|
||||
dotenv.config();
|
||||
|
||||
const app = express();
|
||||
@@ -17,6 +17,7 @@ app.use(cors());
|
||||
app.use("/auth", authRoutes);
|
||||
app.use("/user", userRoutes);
|
||||
app.use("/upload", uploadRoutes);
|
||||
app.use("/voice", voiceRoutes);
|
||||
|
||||
|
||||
app.get("/health", (req, res) => {
|
||||
|
||||
Reference in New Issue
Block a user