/** * Inflect-Micro-v2 OpenAI-compatible TTS Server * * Start: tts_server [--port 8000] [--host 0.0.0.0] * * API: * GET /health → {"status":"ok"} * GET /v1/models → model list * POST /v1/audio/speech → {"model":"tts-1","input":"Hello"} → audio/wav * * Dependencies: cpp-httplib (header-only), nlohmann/json (header-only) * git clone https://github.com/yhirose/cpp-httplib.git * git clone https://github.com/nlohmann/json.git * * Build: cmake .. -DCPPHTTPLIB_DIR=... -DJSON_DIR=... && make tts_server */ #include #include #include #include #include // #include // cpp-httplib // #include // nlohmann/json #include "inflect_tts.hpp" // ---- Simple HTTP server without external deps (production: use cpp-httplib) ---- static void handle_request(const std::string& method, const std::string& path, const std::string& body, std::string& response) { // Health check if (path == "/health") { response = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" "{\"status\":\"ok\",\"model\":\"inflect-micro-v2\"}"; return; } // POST /v1/audio/speech if (method == "POST" && path == "/v1/audio/speech") { // Parse JSON body (simplified; production: use nlohmann/json) std::string text; float speed = 1.0f; // Extract "input" field size_t pos = body.find("\"input\":\""); if (pos != std::string::npos) { pos += 9; size_t end = body.find("\"", pos); if (end != std::string::npos) text = body.substr(pos, end - pos); } if (text.empty()) { response = "HTTP/1.1 400 Bad Request\r\n\r\n"; return; } try { static TTSEngine engine("../models/inflect_encoder.axmodel", "../models/inflect_decoder.axmodel"); auto waveform = engine.synthesize(text, speed); std::ostringstream wav_data; // Simplified: write raw float32 PCM; production: add WAV header wav_data.write(reinterpret_cast(waveform.data()), waveform.size() * sizeof(float)); std::ostringstream resp; resp << "HTTP/1.1 200 OK\r\n" << "Content-Type: audio/wav\r\n" << "Content-Length: " << wav_data.str().size() << "\r\n" << "X-Sample-Rate: 24000\r\n" << "\r\n" << wav_data.str(); response = resp.str(); } catch (const std::exception& e) { response = "HTTP/1.1 500 Internal Server Error\r\n\r\n"; } return; } response = "HTTP/1.1 404 Not Found\r\n\r\n"; } int main(int argc, char* argv[]) { int port = 8000; std::string host = "0.0.0.0"; for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "--port") == 0 && i + 1 < argc) port = std::stoi(argv[++i]); else if (strcmp(argv[i], "--host") == 0 && i + 1 < argc) host = argv[++i]; } std::cout << "🎤 Inflect-Micro-v2 TTS Server\n"; std::cout << " Listening on " << host << ":" << port << "\n"; std::cout << " POST /v1/audio/speech (OpenAI-compatible)\n"; std::cout << " GET /health\n"; std::cout << "\n"; std::cout << " Example:\n"; std::cout << " curl -X POST http://localhost:" << port << "/v1/audio/speech \\\n"; std::cout << " -H 'Content-Type: application/json' \\\n"; std::cout << " -d '{\"model\":\"tts-1\",\"input\":\"Hello world\"}' \\\n"; std::cout << " --output speech.wav\n"; std::cout << "\n"; std::cout << " Note: Production build requires cpp-httplib + nlohmann/json.\n"; std::cout << " See CMakeLists.txt for setup instructions.\n"; // TODO: Production HTTP loop using cpp-httplib // httplib::Server svr; // svr.Post("/v1/audio/speech", [&](const httplib::Request& req, httplib::Response& res) { // ... // }); // svr.listen(host.c_str(), port); return 0; }