inoryQwQ
fix: remove duplicate axmodels, fix model paths, add config.json for download tracking
afdce78
Raw
History Blame Contribute Delete
4.17 kB
/**
* 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 <iostream>
#include <sstream>
#include <string>
#include <thread>
#include <chrono>
// #include <httplib.h> // cpp-httplib
// #include <nlohmann/json.hpp> // 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<const char*>(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;
}