summaryrefslogtreecommitdiff
path: root/packages/ai/src/tts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/ai/src/tts')
-rw-r--r--packages/ai/src/tts/eleven.ts20
-rw-r--r--packages/ai/src/tts/minimax.ts107
-rw-r--r--packages/ai/src/tts/output.mp3bin0 -> 1020960 bytes
3 files changed, 127 insertions, 0 deletions
diff --git a/packages/ai/src/tts/eleven.ts b/packages/ai/src/tts/eleven.ts
new file mode 100644
index 0000000..c870b11
--- /dev/null
+++ b/packages/ai/src/tts/eleven.ts
@@ -0,0 +1,20 @@
+import { ElevenLabsClient, play } from "@elevenlabs/elevenlabs-js";
+
+const elevenlabs = new ElevenLabsClient({
+ apiKey: Bun.env.ELEVEN_KEY!, // Defaults to process.env.ELEVENLABS_API_KEY
+});
+
+const models = await elevenlabs.models.list();
+for (const model of models) {
+ const langs = model.languages || [];
+ for (const lang of langs) {
+ if (lang.name === "Thai") console.log(model.modelId);
+ }
+}
+// ONLY eleven_v3 has Thai!
+// const audio = await elevenlabs.textToSpeech.convert("Xb7hH8MSUJpSbSDYk0k2", {
+// text: "Hello! 你好! Hola! नमस्ते! Bonjour! こんにちは! مرحبا! 안녕하세요! Ciao! Cześć! Привіт! வணக்கம்!",
+// modelId: "eleven_multilingual_v2",
+// });
+
+// await play(audio);
diff --git a/packages/ai/src/tts/minimax.ts b/packages/ai/src/tts/minimax.ts
new file mode 100644
index 0000000..4421f94
--- /dev/null
+++ b/packages/ai/src/tts/minimax.ts
@@ -0,0 +1,107 @@
+// https://platform.minimax.io/docs/api-reference/speech-t2a-async-create/
+//
+//
+//
+
+const text = `สำนักข่าวต่างประเทศรายงานเมื่อ 18 พ.ย. 2568 ว่า เจ้าหน้าที่กู้ภัยของประเทศชิลี กำลังดำเนินการค้นหากลุ่มนักท่องเที่ยวที่สูญหายไปในพายุหิมะรุนแรงซึ่งเกิดขึ้นที่ อุทยานแห่งชาติ “ตอร์เรส เดล ไพเน” ในภูมิภาคปาตาโกเนีย ทางตอนใต้ของชิลี หลังพายุทำให้มีผู้เสียชีวิตแล้วอย่างน้อย 5 ศพ`;
+// const text = `So I start using it for my project and after about 20 mins - oh, no. Out of credits.
+// I didn't even get to try a single Gemini 3 prompt. I was out of credits before my first had completed. I guess I've burned through the free tier in some other app but the error message gave me no clues. As far as I can tell there's no link to give Google my money in the app. Maybe they think they have enough.
+
+// After switching to gpt-oss:120b it did some things quite well, and the annotation feature in the plan doc is really nice. It has potential but I suspect it's suffering from Google's typical problem that it's only really been tested on Googlers.`;
+const model = "speech-2.6-hd";
+const voice1 = "Thai_male_1_sample8";
+const voice2 = "Thai_male_2_sample2";
+const voice3 = "Thai_female_1_sample1";
+const voice4 = "Thai_female_2_sample2";
+const params = {
+ model,
+ language_boost: "auto",
+ voice_setting: { voice_id: voice1, speed: 1, vol: 1, pitch: 1 },
+ pronunciation_dct: { tone: ["lol, lmao"] },
+ audio_setting: {
+ audio_sample_rate: 32000,
+ bitrate: 128_000,
+ format: "mp3",
+ channel: 2,
+ },
+ voice_modify: {
+ pitch: 0,
+ intensity: 0,
+ timbre: 0,
+ sound_Effects: "spacious_echo",
+ },
+};
+
+async function getVoices() {
+ const endpoint = "/get_voice";
+ const body = { voice_type: "all" };
+ return await post(endpoint, body);
+}
+async function tts() {
+ const endpoint = "/t2a_v2";
+ const body = { text, stream: false, ...params };
+ return await post(endpoint, body);
+}
+async function ws() {
+ const url = "wss://api.minimax.io/ws/v1/t2a_v2";
+ const event = "task_start";
+
+ const headers = {
+ Authorization: `Bearer ${Bun.env.MINIMAX_API_KEY!}`,
+ };
+ const socket = new WebSocket(url, { headers });
+ const body = { event, ...params };
+ const body2 = { event: "task_continue", text };
+ socket.send(JSON.stringify(body));
+ // const event = "task_continue";
+ // const event = "task_finish";
+}
+async function tts_async() {
+ const body = {
+ text,
+ ...params,
+ };
+ return await post("/t2a_async_v2", body);
+}
+async function post(path: string, body: any) {
+ const url = "https://api.minimax.io/v1" + path;
+ const options = {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${Bun.env.MINIMAX_API_KEY2!}`,
+ },
+ body: JSON.stringify(body),
+ };
+
+ try {
+ const response = await fetch(url, options);
+ const data = await response.json();
+ return data;
+ } catch (error) {
+ console.error(error);
+ }
+}
+async function get(path: string) {
+ const url = "https://api.minimax.io/v1" + path;
+ const options = {
+ headers: {
+ Authorization: `Bearer ${Bun.env.MINIMAX_API_KEY!}`,
+ },
+ };
+
+ try {
+ const response = await fetch(url, options);
+ const data = await response.json();
+ console.log(data);
+ } catch (error) {
+ console.error(error);
+ }
+}
+
+import fs from "node:fs";
+const res = await tts();
+const audio = res.data.audio;
+const audioBuffer = Buffer.from(audio, "hex");
+const filename = "output.mp3";
+fs.writeFileSync(filename, audioBuffer);
diff --git a/packages/ai/src/tts/output.mp3 b/packages/ai/src/tts/output.mp3
new file mode 100644
index 0000000..9f22e3a
--- /dev/null
+++ b/packages/ai/src/tts/output.mp3
Binary files differ