UNPKG

gpt-sovits-sdk

Version:

Node.js SDK for GPT-SoVITS API

502 lines (501 loc) 22.4 kB
"use strict"; /** * GPT-SoVITS SDK 直接返回文件的接口测试脚本 * * 这个脚本专注于测试直接返回二进制数据的API端点,如获取音频文件和直接TTS */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); const index_1 = require("./index"); const path = __importStar(require("path")); const fs = __importStar(require("fs")); // 创建输出目录 const outputDir = path.join(__dirname, '../test-output/direct'); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } // 创建客户端实例 const client = (0, index_1.createClient)({ baseUrl: 'http://127.0.0.1:9880', // 默认API地址 timeout: 60000, // 设置超时时间为60秒 debug: true, // 启用调试输出 retries: 2 // 设置重试次数 }); /** * 测试获取音频文件 */ async function testGetAudio() { console.log('=== 测试获取音频文件 ==='); try { // 首先,我们需要获取一个可用的音频文件路径 // 可以通过先执行TTS来获取一个音频文件 console.log('执行TTS以获取音频文件...'); // 获取情感参考音频列表 const emotionResponse = await client.getEmotionReferenceAudios(); if (!emotionResponse || !emotionResponse.data || !emotionResponse.data.referenceAudios || emotionResponse.data.referenceAudios.length === 0) { console.log('没有找到可用的情感参考音频,跳过测试'); return false; } // 选择第一个音频 const refAudio = emotionResponse.data.referenceAudios[0]; console.log(`选择参考音频: ${refAudio.name}`); // 获取可用模型 const modelsResponse = await client.getModels(); if (!modelsResponse || !modelsResponse.data || !modelsResponse.data.gpt_models || !modelsResponse.data.sovits_models || modelsResponse.data.gpt_models.length === 0 || modelsResponse.data.sovits_models.length === 0) { console.log('没有找到可用的模型,跳过测试'); return false; } // 选择模型 const gptModel = modelsResponse.data.gpt_models[0].path; const sovitsModel = modelsResponse.data.sovits_models[0].path; console.log(`选择GPT模型: ${gptModel}`); console.log(`选择SoVITS模型: ${sovitsModel}`); // 设置模型 await client.setGptModel(gptModel); await client.setSovitsModel(sovitsModel); // 执行TTS const ttsResponse = await client.textToSpeech({ text: '这是一个测试获取音频文件的示例。', textLang: index_1.TextLanguage.CHINESE, refAudioPath: refAudio.id, promptLang: index_1.TextLanguage.CHINESE, mediaType: index_1.MediaType.WAV, gptModel: gptModel, sovitsModel: sovitsModel }); if (!ttsResponse || !ttsResponse.audio_path) { console.log('TTS未返回有效的音频路径,跳过测试'); return false; } const audioPath = ttsResponse.audio_path; console.log(`生成的音频文件路径: ${audioPath}`); // 测试获取音频文件(返回ArrayBuffer) console.log('\n测试获取音频文件(返回ArrayBuffer)...'); const audioData = await client.getAudio(audioPath); if (!audioData) { console.log('❌ 获取音频文件失败'); return false; } if (audioData instanceof ArrayBuffer) { console.log(`✅ 成功获取音频文件,大小: ${audioData.byteLength} 字节`); } else { console.log(`✅ 成功获取音频文件,路径: ${audioData}`); if (fs.existsSync(audioData)) { const fileStats = fs.statSync(audioData); console.log(`文件大小: ${fileStats.size} 字节`); } } // 测试获取音频文件并保存到本地 console.log('\n测试获取音频文件并保存到本地...'); const outputPath = path.join(outputDir, `get_audio_${Date.now()}.wav`); const savedPath = await client.getAudio(audioPath, outputPath); if (!savedPath) { console.log('❌ 保存音频文件失败'); return false; } if (typeof savedPath === 'string' && fs.existsSync(savedPath)) { console.log(`✅ 成功保存音频文件到: ${savedPath}`); const fileStats = fs.statSync(savedPath); console.log(`文件大小: ${fileStats.size} 字节`); } else { console.log('❌ 保存音频文件失败或返回的不是有效路径'); return false; } return true; } catch (error) { console.error('❌ 获取音频文件测试失败:', error); if (error instanceof Error) { console.error('错误信息:', error.message); console.error('错误堆栈:', error.stack); } return false; } } /** * 测试直接TTS */ async function testDirectTTS() { console.log('\n=== 测试直接TTS ==='); try { // 获取情感参考音频列表 const emotionResponse = await client.getEmotionReferenceAudios(); if (!emotionResponse || !emotionResponse.data || !emotionResponse.data.referenceAudios || emotionResponse.data.referenceAudios.length === 0) { console.log('没有找到可用的情感参考音频,跳过测试'); return false; } // 选择第一个音频 const refAudio = emotionResponse.data.referenceAudios[0]; console.log(`选择参考音频: ${refAudio.name}`); // 获取可用模型 const modelsResponse = await client.getModels(); if (!modelsResponse || !modelsResponse.data || !modelsResponse.data.gpt_models || !modelsResponse.data.sovits_models || modelsResponse.data.gpt_models.length === 0 || modelsResponse.data.sovits_models.length === 0) { console.log('没有找到可用的模型,跳过测试'); return false; } // 选择模型 const gptModel = modelsResponse.data.gpt_models[0].path; const sovitsModel = modelsResponse.data.sovits_models[0].path; console.log(`选择GPT模型: ${gptModel}`); console.log(`选择SoVITS模型: ${sovitsModel}`); // 设置模型 await client.setGptModel(gptModel); await client.setSovitsModel(sovitsModel); // 测试直接TTS(返回ArrayBuffer) console.log('\n测试直接TTS(返回ArrayBuffer)...'); const audioData = await client.textToSpeechDirect({ text: '这是一个测试直接TTS的示例,返回ArrayBuffer。', textLang: index_1.TextLanguage.CHINESE, refAudioPath: refAudio.id, promptLang: index_1.TextLanguage.CHINESE, mediaType: index_1.MediaType.WAV, gptModel: gptModel, sovitsModel: sovitsModel }); if (!audioData) { console.log('❌ 直接TTS失败'); return false; } if (audioData instanceof ArrayBuffer) { console.log(`✅ 成功执行直接TTS,返回数据大小: ${audioData.byteLength} 字节`); } else { console.log(`✅ 成功执行直接TTS,返回路径: ${audioData}`); if (fs.existsSync(audioData)) { const fileStats = fs.statSync(audioData); console.log(`文件大小: ${fileStats.size} 字节`); } } // 测试直接TTS并保存到本地 console.log('\n测试直接TTS并保存到本地...'); const outputPath = path.join(outputDir, `direct_tts_${Date.now()}.wav`); const savedPath = await client.textToSpeechDirect({ text: '这是一个测试直接TTS的示例,保存到本地文件。', textLang: index_1.TextLanguage.CHINESE, refAudioPath: refAudio.id, promptLang: index_1.TextLanguage.CHINESE, mediaType: index_1.MediaType.WAV, gptModel: gptModel, sovitsModel: sovitsModel }, outputPath); if (!savedPath) { console.log('❌ 保存直接TTS音频文件失败'); return false; } if (typeof savedPath === 'string' && fs.existsSync(savedPath)) { console.log(`✅ 成功保存直接TTS音频文件到: ${savedPath}`); const fileStats = fs.statSync(savedPath); console.log(`文件大小: ${fileStats.size} 字节`); } else { console.log('❌ 保存直接TTS音频文件失败或返回的不是有效路径'); return false; } return true; } catch (error) { console.error('❌ 直接TTS测试失败:', error); if (error instanceof Error) { console.error('错误信息:', error.message); console.error('错误堆栈:', error.stack); } return false; } } /** * 测试不同媒体类型 */ async function testDifferentMediaTypes() { console.log('\n=== 测试不同媒体类型 ==='); try { // 获取情感参考音频列表 const emotionResponse = await client.getEmotionReferenceAudios(); if (!emotionResponse || !emotionResponse.data || !emotionResponse.data.referenceAudios || emotionResponse.data.referenceAudios.length === 0) { console.log('没有找到可用的情感参考音频,跳过测试'); return false; } // 选择第一个音频 const refAudio = emotionResponse.data.referenceAudios[0]; console.log(`选择参考音频: ${refAudio.name}`); // 获取可用模型 const modelsResponse = await client.getModels(); if (!modelsResponse || !modelsResponse.data || !modelsResponse.data.gpt_models || !modelsResponse.data.sovits_models || modelsResponse.data.gpt_models.length === 0 || modelsResponse.data.sovits_models.length === 0) { console.log('没有找到可用的模型,跳过测试'); return false; } // 选择模型 const gptModel = modelsResponse.data.gpt_models[0].path; const sovitsModel = modelsResponse.data.sovits_models[0].path; // 设置模型 await client.setGptModel(gptModel); await client.setSovitsModel(sovitsModel); // 测试不同的媒体类型 const mediaTypes = [index_1.MediaType.WAV, index_1.MediaType.MP3, index_1.MediaType.OGG]; for (const mediaType of mediaTypes) { console.log(`\n测试媒体类型: ${mediaType}...`); try { // 注意:OGG格式在非流式模式下不支持,预期会失败 if (mediaType === index_1.MediaType.OGG) { console.log('⚠️ 注意: OGG格式在非流式模式下不支持,预期会失败'); } const outputPath = path.join(outputDir, `media_type_${mediaType}_${Date.now()}.${mediaType}`); const savedPath = await client.textToSpeechDirect({ text: `这是一个测试${mediaType}格式的示例。`, textLang: index_1.TextLanguage.CHINESE, refAudioPath: refAudio.id, promptLang: index_1.TextLanguage.CHINESE, mediaType: mediaType, gptModel: gptModel, sovitsModel: sovitsModel }, outputPath); if (!savedPath) { console.log(`❌ ${mediaType}格式测试失败`); continue; } if (typeof savedPath === 'string' && fs.existsSync(savedPath)) { console.log(`✅ 成功生成${mediaType}格式音频: ${savedPath}`); const fileStats = fs.statSync(savedPath); console.log(`文件大小: ${fileStats.size} 字节`); } else { console.log(`❌ ${mediaType}格式测试失败或返回的不是有效路径`); } } catch (mediaError) { if (mediaType === index_1.MediaType.OGG && mediaError instanceof Error && (mediaError.message.includes('OGG格式不支持非流式模式') || mediaError.message.includes('400'))) { console.log(`ℹ️ OGG格式测试预期失败: OGG格式不支持非流式模式,这是预期的行为`); } else { console.error(`❌ ${mediaType}格式测试失败:`, mediaError); } } } return true; } catch (error) { console.error('❌ 媒体类型测试失败:', error); if (error instanceof Error) { console.error('错误信息:', error.message); console.error('错误堆栈:', error.stack); } return false; } } /** * 测试日文语音生成 */ async function testJapaneseVoice() { console.log('\n=== 测试日文语音生成 ==='); try { // 获取情感参考音频列表 const emotionResponse = await client.getEmotionReferenceAudios(); if (!emotionResponse || !emotionResponse.data || !emotionResponse.data.referenceAudios || emotionResponse.data.referenceAudios.length === 0) { console.log('没有找到可用的情感参考音频,跳过测试'); return false; } // 选择一个合适的音频(优先选择日语音频,如果没有则使用第一个) let refAudio = emotionResponse.data.referenceAudios[0]; // 尝试查找日语音频 const japaneseAudio = emotionResponse.data.referenceAudios.find(audio => audio.language === '日文' || audio.language === 'ja' || audio.language === 'japanese'); if (japaneseAudio) { refAudio = japaneseAudio; console.log('找到日语参考音频:', refAudio.name); } else { console.log('未找到日语参考音频,使用默认音频:', refAudio.name); } // 获取可用模型 const modelsResponse = await client.getModels(); if (!modelsResponse || !modelsResponse.data || !modelsResponse.data.gpt_models || !modelsResponse.data.sovits_models || modelsResponse.data.gpt_models.length === 0 || modelsResponse.data.sovits_models.length === 0) { console.log('没有找到可用的模型,跳过测试'); return false; } // 选择模型 const gptModel = modelsResponse.data.gpt_models[0].path; const sovitsModel = modelsResponse.data.sovits_models[0].path; console.log(`选择GPT模型: ${gptModel}`); console.log(`选择SoVITS模型: ${sovitsModel}`); // 设置模型 await client.setGptModel(gptModel); await client.setSovitsModel(sovitsModel); // 日文测试文本 const japaneseText = 'こんにちは、これは日本語の音声合成テストです。'; console.log(`日文测试文本: ${japaneseText}`); // 测试日文TTS并保存到本地 console.log('\n测试日文TTS并保存到本地...'); const outputPath = path.join(outputDir, `japanese_tts_${Date.now()}.wav`); const savedPath = await client.textToSpeechDirect({ text: japaneseText, textLang: 'ja', refAudioPath: refAudio.id, promptLang: refAudio.language === '日文' ? 'ja' : (refAudio.language === '英文' ? 'en' : 'zh'), mediaType: index_1.MediaType.WAV, gptModel: gptModel, sovitsModel: sovitsModel }, outputPath); if (!savedPath) { console.log('❌ 保存日文TTS音频文件失败'); return false; } if (typeof savedPath === 'string' && fs.existsSync(savedPath)) { console.log(`✅ 成功保存日文TTS音频文件到: ${savedPath}`); const fileStats = fs.statSync(savedPath); console.log(`文件大小: ${fileStats.size} 字节`); } else { console.log('❌ 保存日文TTS音频文件失败或返回的不是有效路径'); return false; } return true; } catch (error) { console.error('❌ 日文TTS测试失败:', error); if (error instanceof Error) { console.error('错误信息:', error.message); console.error('错误堆栈:', error.stack); } return false; } } /** * 测试英文语音生成 */ async function testEnglishVoice() { console.log('\n=== 测试英文语音生成 ==='); try { // 获取情感参考音频列表 const emotionResponse = await client.getEmotionReferenceAudios(); if (!emotionResponse || !emotionResponse.data || !emotionResponse.data.referenceAudios || emotionResponse.data.referenceAudios.length === 0) { console.log('没有找到可用的情感参考音频,跳过测试'); return false; } // 选择一个合适的音频(优先选择英语音频,如果没有则使用第一个) let refAudio = emotionResponse.data.referenceAudios[0]; // 尝试查找英语音频 const englishAudio = emotionResponse.data.referenceAudios.find(audio => audio.language === '英文' || audio.language === 'en' || audio.language === 'english'); if (englishAudio) { refAudio = englishAudio; console.log('找到英语参考音频:', refAudio.name); } else { console.log('未找到英语参考音频,使用默认音频:', refAudio.name); } // 获取可用模型 const modelsResponse = await client.getModels(); if (!modelsResponse || !modelsResponse.data || !modelsResponse.data.gpt_models || !modelsResponse.data.sovits_models || modelsResponse.data.gpt_models.length === 0 || modelsResponse.data.sovits_models.length === 0) { console.log('没有找到可用的模型,跳过测试'); return false; } // 选择模型 const gptModel = modelsResponse.data.gpt_models[0].path; const sovitsModel = modelsResponse.data.sovits_models[0].path; console.log(`选择GPT模型: ${gptModel}`); console.log(`选择SoVITS模型: ${sovitsModel}`); // 设置模型 await client.setGptModel(gptModel); await client.setSovitsModel(sovitsModel); // 英文测试文本 const englishText = 'Hello, this is a test for English voice synthesis. The quick brown fox jumps over the lazy dog.'; console.log(`英文测试文本: ${englishText}`); // 测试英文TTS并保存到本地 console.log('\n测试英文TTS并保存到本地...'); const outputPath = path.join(outputDir, `english_tts_${Date.now()}.wav`); const savedPath = await client.textToSpeechDirect({ text: englishText, textLang: 'en', refAudioPath: refAudio.id, promptLang: refAudio.language === '英文' ? 'en' : (refAudio.language === '日文' ? 'ja' : 'zh'), mediaType: index_1.MediaType.WAV, gptModel: gptModel, sovitsModel: sovitsModel }, outputPath); if (!savedPath) { console.log('❌ 保存英文TTS音频文件失败'); return false; } if (typeof savedPath === 'string' && fs.existsSync(savedPath)) { console.log(`✅ 成功保存英文TTS音频文件到: ${savedPath}`); const fileStats = fs.statSync(savedPath); console.log(`文件大小: ${fileStats.size} 字节`); } else { console.log('❌ 保存英文TTS音频文件失败或返回的不是有效路径'); return false; } return true; } catch (error) { console.error('❌ 英文TTS测试失败:', error); if (error instanceof Error) { console.error('错误信息:', error.message); console.error('错误堆栈:', error.stack); } return false; } } /** * 运行测试 */ async function runTests() { console.log('开始测试 GPT-SoVITS SDK 直接返回文件的接口...\n'); // 测试获取音频文件 await testGetAudio(); // 测试直接TTS await testDirectTTS(); // 测试不同媒体类型 await testDifferentMediaTypes(); // 测试日文语音生成 await testJapaneseVoice(); // 测试英文语音生成 await testEnglishVoice(); console.log('\n测试完成!'); } // 执行测试 runTests().catch(error => { console.error('测试过程中发生错误:', error); });