/************************************************************************************************** * * Copyright (c) 2019-2026 Axera Semiconductor (Ningbo) Co., Ltd. All Rights Reserved. * * This source file is the property of Axera Semiconductor (Ningbo) Co., Ltd. and * may not be copied or distributed in any isomorphic form without the prior * written consent of Axera Semiconductor (Ningbo) Co., Ltd. * **************************************************************************************************/ #pragma once #include #include #include "httplib.h" #include "api/ax_tts_api.h" #include "openai_err.hpp" #define DEFAULT_PORT 8080 #define TTS_ENDPOINT "/v1/audio/speech" /* OpenAI-Compatible server Following API docs from: https://platform.openai.com/docs/api-reference/audio/createSpeech post http://IP:PORT/v1/audio/speech * Client usage: * - cURL: * curl https://api.openai.com/v1/audio/speech \ -H "Authorization: Bearer $OPENAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini-tts", "input": "The quick brown fox jumped over the lazy dog.", "voice": "alloy" }' \ --output speech.mp3 * * - Python: * from pathlib import Path import openai speech_file_path = Path(__file__).parent / "speech.mp3" with openai.audio.speech.with_streaming_response.create( model="gpt-4o-mini-tts", voice="alloy", input="The quick brown fox jumped over the lazy dog." ) as response: response.stream_to_file(speech_file_path) * - JavaScript: import fs from "fs"; import path from "path"; import OpenAI from "openai"; const openai = new OpenAI(); const speechFile = path.resolve("./speech.mp3"); async function main() { const mp3 = await openai.audio.speech.create({ model: "gpt-4o-mini-tts", voice: "alloy", input: "Today is a wonderful day to build something people love!", }); console.log(speechFile); const buffer = Buffer.from(await mp3.arrayBuffer()); await fs.promises.writeFile(speechFile, buffer); } main(); * Response: * Error: check https://platform.openai.com/docs/guides/error-codes * { "error": { "message": "You exceeded your current quota, please check your plan and billing details.", "type": "insufficient_quota", "param": null, "code": 402 } } * Success: { "file": stream of pcm } */ class TTSServer { public: TTSServer() = default; ~TTSServer() = default; bool init(const std::string& model_path, const std::string& espeak_data_path = "", const std::string& jieba_dict_path = ""); void start(int port = DEFAULT_PORT); void stop(); private: void setup_routes_(); AX_TTS_HANDLE load_tts_(const std::string& model_name); // 设置CORS头 void set_CORS_headers_(httplib::Response& res); /* * request: Content-Type: multipart/form-data * { * "input": "The text to generate audio for." * "instructions": We use instructions for language choice for compatibilty. Supports zh, en, ja, etc. * "model": Supports kokoro and melotts * "speed": The speed of the generated audio. Select a value from 0.25 to 4.0. 1.0 is the default. * "response_format": The format to audio in. Supported formats are mp3, wav. Default to mp3. * } */ bool check_request_(const httplib::Request& req, httplib::Response& res, nlohmann::json& json_data); private: std::map handles_; httplib::Server srv_; std::string model_path_; std::string espeak_data_path_; std::string jieba_dict_path_; };