Skip to main content
Glama

MiniMax MCP JS

Official
by MiniMax-AI
voice-clone.ts4.56 kB
import { MiniMaxAPI } from '../utils/api.js'; import { VoiceCloneRequest } from '../types/index.js'; import { MinimaxRequestError } from '../exceptions/index.js'; import { DEFAULT_SPEECH_MODEL, ERROR_AUDIO_FILE_REQUIRED, RESOURCE_MODE_URL } from '../const/index.js'; import { buildOutputFile, processInputFile } from '../utils/file.js'; import * as fs from 'fs'; import * as path from 'path'; import * as requests from 'axios'; export class VoiceCloneAPI { private api: MiniMaxAPI; constructor(api: MiniMaxAPI) { this.api = api; } async cloneVoice(request: VoiceCloneRequest): Promise<string> { // Validate required parameters if (!request.audioFile) { throw new MinimaxRequestError(ERROR_AUDIO_FILE_REQUIRED); } if (!request.voiceId) { throw new MinimaxRequestError('Voice ID is required'); } try { // Step 1: Upload file let files: any; if (request.isUrl) { // Handle URL file try { const response = await requests.default.get(request.audioFile, { responseType: 'stream' }); const tempFilePath = path.join(process.cwd(), 'temp', path.basename(request.audioFile)); // Ensure temp directory exists const tempDir = path.dirname(tempFilePath); if (!fs.existsSync(tempDir)) { fs.mkdirSync(tempDir, { recursive: true }); } // Save stream to temp file const writer = fs.createWriteStream(tempFilePath); response.data.pipe(writer); await new Promise<void>((resolve, reject) => { writer.on('finish', () => resolve()); writer.on('error', reject); }); // Prepare upload parameters with temp file files = { file: { path: tempFilePath, }, }; } catch (error) { throw new MinimaxRequestError(`Failed to download audio from URL: ${String(error)}`); } } else { // Handle local file try { const filePath = processInputFile(request.audioFile); // Prepare upload parameters files = { file: { path: filePath, }, }; } catch (error) { throw new MinimaxRequestError(`Failed to read local file: ${String(error)}`); } } const data = { files, purpose: 'voice_clone', }; // Upload file const uploadResponse = await this.api.post<any>('/v1/files/upload', data); // Get file ID const fileId = uploadResponse?.file?.file_id; if (!fileId) { throw new MinimaxRequestError('Failed to get file ID from upload response'); } // Step 2: Clone voice const payload: Record<string, any> = { file_id: fileId, voice_id: request.voiceId, }; // If demo text is provided, add it to the request if (request.text) { payload.text = request.text; payload.model = DEFAULT_SPEECH_MODEL; } // Send clone request const cloneResponse = await this.api.post<any>('/v1/voice_clone', payload); // Check if there's a demo audio const demoAudio = cloneResponse?.demo_audio; if (!demoAudio) { // If no demo audio, return voice ID directly return request.voiceId; } // If URL mode, return URL directly const resourceMode = this.api.getResourceMode(); if (resourceMode === RESOURCE_MODE_URL) { return demoAudio; } // Step 3: Download demo audio const outputPath = buildOutputFile('voice_clone', request.outputDirectory, 'wav', true); try { // Download audio const audioResponse = await requests.default.get(demoAudio, { responseType: 'arraybuffer' }); // Ensure directory exists const dirPath = path.dirname(outputPath); if (!fs.existsSync(dirPath)) { fs.mkdirSync(dirPath, { recursive: true }); } // Save file fs.writeFileSync(outputPath, Buffer.from(audioResponse.data)); // Return voice ID with path information return `${request.voiceId} (Demo audio: ${outputPath})`; } catch (error) { // If download fails, still return voice ID return request.voiceId; } } catch (error) { if (error instanceof MinimaxRequestError) { throw error; } throw new MinimaxRequestError(`Error occurred while cloning voice: ${String(error)}`); } } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/MiniMax-AI/MiniMax-MCP-JS'

If you have feedback or need assistance with the MCP directory API, please join our Discord server