tts.controller.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. "use strict";
  2. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
  3. if (k2 === undefined) k2 = k;
  4. var desc = Object.getOwnPropertyDescriptor(m, k);
  5. if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
  6. desc = { enumerable: true, get: function() { return m[k]; } };
  7. }
  8. Object.defineProperty(o, k2, desc);
  9. }) : (function(o, m, k, k2) {
  10. if (k2 === undefined) k2 = k;
  11. o[k2] = m[k];
  12. }));
  13. var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
  14. Object.defineProperty(o, "default", { enumerable: true, value: v });
  15. }) : function(o, v) {
  16. o["default"] = v;
  17. });
  18. var __importStar = (this && this.__importStar) || (function () {
  19. var ownKeys = function(o) {
  20. ownKeys = Object.getOwnPropertyNames || function (o) {
  21. var ar = [];
  22. for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
  23. return ar;
  24. };
  25. return ownKeys(o);
  26. };
  27. return function (mod) {
  28. if (mod && mod.__esModule) return mod;
  29. var result = {};
  30. if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
  31. __setModuleDefault(result, mod);
  32. return result;
  33. };
  34. })();
  35. var __importDefault = (this && this.__importDefault) || function (mod) {
  36. return (mod && mod.__esModule) ? mod : { "default": mod };
  37. };
  38. Object.defineProperty(exports, "__esModule", { value: true });
  39. const router_1 = __importDefault(require("@koa/router"));
  40. const TtsService = __importStar(require("./tts.service"));
  41. const errorHandler_1 = require("../../middleware/errorHandler");
  42. const auth_1 = require("../../middleware/auth");
  43. const models_1 = require("../../models");
  44. const router = new router_1.default();
  45. // 获取可用音色列表
  46. router.get('/voices', async (ctx) => {
  47. const voices = TtsService.getVoices();
  48. ctx.body = {
  49. code: 0,
  50. message: 'success',
  51. data: { voices },
  52. };
  53. });
  54. // 测试 MySQL 连接
  55. router.get('/test-db', async (ctx) => {
  56. try {
  57. const count = await models_1.prisma.book.count();
  58. ctx.body = {
  59. code: 0,
  60. message: 'success',
  61. data: { count, connectionState: 'connected' },
  62. };
  63. }
  64. catch (error) {
  65. ctx.body = {
  66. code: 500,
  67. message: 'error',
  68. data: { error: error.message },
  69. };
  70. }
  71. });
  72. // 生成音频(异步模式)
  73. router.post('/generate', auth_1.optionalAuth, async (ctx) => {
  74. const userId = ctx.state.user?.userId;
  75. const { text, voiceId, voiceParams } = ctx.request.body;
  76. // 调试日志
  77. console.log('📥 收到 TTS 请求:', { textLength: text?.length, voiceId, voiceParams });
  78. // 参数验证
  79. if (!text || text.trim().length === 0) {
  80. throw new errorHandler_1.BadRequestError('请输入要转换的文本');
  81. }
  82. if (!voiceId) {
  83. throw new errorHandler_1.BadRequestError('请选择音色');
  84. }
  85. // 检查字数限制(测试模式:无限制)
  86. const wordCount = text.length;
  87. const quota = ctx.state.userQuota || { dailyLimit: -1, wordLimit: -1 };
  88. if (quota.wordLimit !== -1 && wordCount > quota.wordLimit) {
  89. throw new errorHandler_1.BadRequestError(`文本字数超出限制(${quota.wordLimit}字)`);
  90. }
  91. // 默认参数
  92. const params = {
  93. speed: voiceParams?.speed || 1.0,
  94. pitch: voiceParams?.pitch || 0,
  95. volume: voiceParams?.volume || 50,
  96. };
  97. // 异步生成音频(立即返回)
  98. const result = await TtsService.generateAudio(userId, text, voiceId, params);
  99. // 如果用户已登录,更新使用次数
  100. if (userId) {
  101. const user = await models_1.prisma.user.findUnique({ where: { id: parseInt(userId) } });
  102. if (user) {
  103. await models_1.prisma.user.update({
  104. where: { id: parseInt(userId) },
  105. data: { dailyUsage: user.dailyUsage + 1 },
  106. });
  107. }
  108. }
  109. ctx.body = {
  110. code: 0,
  111. message: '音频生成任务已创建',
  112. data: result, // { audioId, audioUrl: '' }
  113. };
  114. });
  115. // 获取音频生成状态
  116. router.get('/status/:audioId', async (ctx) => {
  117. const { audioId } = ctx.params;
  118. const result = await TtsService.getAudioStatus(audioId);
  119. if (result.status === 'not_found') {
  120. throw new errorHandler_1.NotFoundError('音频不存在');
  121. }
  122. ctx.body = {
  123. code: 0,
  124. message: 'success',
  125. data: result,
  126. };
  127. });
  128. // 预览音色
  129. router.post('/preview', async (ctx) => {
  130. const { voiceId, voiceParams } = ctx.request.body;
  131. if (!voiceId) {
  132. throw new errorHandler_1.BadRequestError('请选择音色');
  133. }
  134. // 返回预览文本
  135. ctx.body = {
  136. code: 0,
  137. message: 'success',
  138. data: {
  139. previewText: '这是一段预览文本,用于试听音色效果。',
  140. voiceId,
  141. },
  142. };
  143. });
  144. exports.default = router;