| import _ from "lodash";
|
|
|
| import Request from "@/lib/request/Request.ts";
|
| import Response from "@/lib/response/Response.ts";
|
| import audio from "@/api/controllers/audio.ts";
|
| import modelMap from "../consts/model-map.ts";
|
| import environment from "@/lib/environment.ts";
|
| import core from "../controllers/core.ts";
|
| import logger from "@/lib/logger.ts";
|
|
|
| const REPLACE_AUDIO_MODEL_ENV = (
|
| environment.envVars["REPLACE_AUDIO_MODEL"] || ""
|
| )
|
| .split(",")
|
| .map((v) => v.trim());
|
| const VOICE_TO_MODEL_INDEX = Object.keys(modelMap["tts-1"]).reduce(
|
| (obj, key, i) => {
|
| obj[key] = i;
|
| return obj;
|
| },
|
| {}
|
| );
|
| const REPLACE_AUDIO_MODEL = Object.values(modelMap["tts-1"]).map(
|
| (v, i) => REPLACE_AUDIO_MODEL_ENV[i] || v
|
| );
|
|
|
| export default {
|
| prefix: "/deem/v1/audio",
|
|
|
| post: {
|
| "/speech": async (request: Request) => {
|
| request
|
| .validate("body.input", _.isString)
|
| .validate("body.voice", _.isString)
|
| .validate("headers.authorization", _.isString);
|
|
|
| const tokens = core.tokenSplit(request.headers.authorization);
|
|
|
| const token = _.sample(tokens);
|
| let { model, input, voice } = request.body;
|
| if (voice in VOICE_TO_MODEL_INDEX) {
|
| voice =
|
| REPLACE_AUDIO_MODEL[VOICE_TO_MODEL_INDEX[voice]] || "male-botong";
|
| logger.info(`请求voice切换为: ${voice}`);
|
| }
|
| const stream = await audio.createSpeech(model, input, voice, token);
|
| return new Response(stream, {
|
| headers: {
|
| "Content-Type": "audio/mpeg",
|
| },
|
| });
|
| },
|
|
|
| "/transcriptions": async (request: Request) => {
|
| request
|
| .validate("body.model", _.isString)
|
| .validate("body.response_format", v => _.isUndefined(v) || _.isString(v))
|
| .validate("headers.authorization", _.isString);
|
|
|
| const tokens = core.tokenSplit(request.headers.authorization);
|
|
|
| const token = _.sample(tokens);
|
| if(!request.files['file'] && !request.body["file"])
|
| throw new Error('File field is not set');
|
| let tmpFilePath;
|
| if(request.files['file']) {
|
| const file = request.files['file'];
|
| if(!['audio/mp3', 'audio/mpeg', 'audio/x-wav', 'audio/wave', 'audio/mp4a-latm', 'audio/flac', 'audio/ogg', 'audio/webm'].includes(file.mimetype))
|
| throw new Error(`File MIME type ${file.mimetype} is unsupported`);
|
| tmpFilePath = file.filepath;
|
| }
|
| else
|
| throw new Error('File field is not set');
|
| const { model, response_format: responseFormat = 'json' } = request.body;
|
| const text = await audio.createTranscriptions(model, tmpFilePath, token);
|
| return new Response(responseFormat == 'json' ? { text } : text);
|
| },
|
| },
|
| };
|
|
|