Skip to content

Commit

Permalink
chore: gut out the tiktok-tts page (it's broken)
Browse files Browse the repository at this point in the history
  • Loading branch information
gitlimes committed Jan 2, 2024
1 parent 66c6f03 commit 180a205
Showing 1 changed file with 4 additions and 185 deletions.
189 changes: 4 additions & 185 deletions pages/tiktok-tts.js
Original file line number Diff line number Diff line change
@@ -1,123 +1,15 @@
import Head from "next/head";
import { useState } from "react";

import CreatableSelect from "react-select/creatable";

const fallbackVoices = require("../public/assets/json/tiktokVoices.json");

import GoHome from "../components/GoHome";
import Guide from "../components/Guide";
import OpenGraph from "../components/openGraph";
import Footer from "../components/Footer";

import styles from "../styles/stuffitempage.module.css";

import { saveAs } from "file-saver";
import absoluteUrl from "next-absolute-url";

export async function getServerSideProps() {
async function getVoices() {
// we fetch the voice options from oscie's repo (thanks oscie), and we parse them to json
const rawVoicesFetch = await fetch(
"https://raw.githubusercontent.com/oscie57/tiktok-voice/main/codes.md"
);
// if fetch fails, use fallback
if (!rawVoicesFetch.ok) {
console.log(
"[warn](tiktok-tts) voice fetch failed, using fallbackVoices"
);
return fallbackVoices;
}

let rawVoices = await rawVoicesFetch.text();

// make each line its own string
rawVoices = rawVoices.split("\n");

// find the table header
const headerRegex = /\| *Language *\| *Voice Code *\|/;
const headerIndex =
rawVoices.findIndex((line) => line.match(headerRegex)) + 2;

// get everything from the header down
rawVoices = rawVoices.splice(headerIndex);

// remove empty lines
const emptyLineRegex = /\| *\| *\|/;
rawVoices = rawVoices.filter(
(line) => !line.match(emptyLineRegex) && line !== ""
);

/* split each line into the columns, and clean it up.
then, assign it to a { label, value } object in the voicelist array
*/
let voiceList = rawVoices.map((line) => {
const columns = line.split("|");
const value = columns[2]?.trim().replace(/`/g, "");
const label = `${columns[1]?.trim()} [${value}]`;

return {
label,
value,
};
});

// create the different voice categories
const englishVoices = voiceList.filter(
(voice) =>
voice.label?.includes("English") || voice.label?.includes("Narrator")
);
const disneyVoices = voiceList.filter((voice) =>
voice.label?.includes("Disney")
);
const singingVoices = voiceList.filter((voice) =>
voice.label?.includes("singing")
);
const otherVoices = voiceList.filter(
(voice) =>
!voice.label?.includes("English") &&
!voice.label?.includes("Disney") &&
!voice.label?.includes("Narrator") &&
!voice.label?.includes("singing")
);

// create the final voiceList object
voiceList = [
{ label: "English", options: englishVoices },
{ label: "Singing", options: singingVoices },
{
label: "Disney",
options: disneyVoices,
},
{ label: "Other", options: otherVoices },
];

// check the validity of the voiceList. if invalid, use fallback
if (voiceList[0].options) {
return voiceList;
} else {
console.log(
"[warn](tiktok-tts) using fallback voices",
"voicelist",
voiceList
);
return fallbackVoices;
}
}

const voices = await getVoices();

return {
props: {
voices,
},
};
}

export default function TikTokTTS({ voices, darkMode }) {
const [notice, setNotice] = useState("");
const [selectedVoice, setSelectedVoice] = useState(null);
const [text, setText] = useState();
export default function TikTokTTS({ darkMode }) {

const customDropdownStyles = {
light: {
Expand Down Expand Up @@ -204,48 +96,6 @@ export default function TikTokTTS({ voices, darkMode }) {
},
};

async function getAudio() {
const ttsurl = `https://api16-normal-useast5.us.tiktokv.com/media/api/text/speech/invoke/?text_speaker=${selectedVoice.value}&req_text=${text}&speaker_map_type=0`;
const fetched = await fetch(
`https://api.allorigins.win/get?url=${encodeURIComponent(ttsurl)}`,
{
method: "POST",
}
);
if (!fetched.ok) {
console.log(fetched);
}

const jsondata = await fetched.json();
const usableData = JSON.parse(jsondata.contents);

// adapted from https://stackoverflow.com/a/27980815
function b64toBlob(dataURI) {
const byteString = atob(dataURI);
const ab = new ArrayBuffer(byteString.length);
const ia = new Uint8Array(ab);

for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], { type: "audio/mp3" });
}

if (usableData?.message === "success") {
const v_str = usableData.data.v_str;

const audioBlob = b64toBlob(v_str);
console.log(audioBlob);

saveAs(audioBlob, `${selectedVoice.label}.mp3`);

setNotice("success");
} else {
setNotice(`Error: ${usableData.message}`);
console.log("[warn](tiktok-tts) failed to get audio", usableData);
}
}

return (
<div>
<Head>
Expand Down Expand Up @@ -287,7 +137,7 @@ export default function TikTokTTS({ voices, darkMode }) {

<CreatableSelect
className={styles.select}
options={voices}
options={["I'm telling you it's broken"]}
noOptionsMessage={() => "No results"}
placeholder="Select a voice"
menuPlacement="top"
Expand All @@ -297,52 +147,21 @@ export default function TikTokTTS({ voices, darkMode }) {
styles={
darkMode ? customDropdownStyles.dark : customDropdownStyles.light
}
onChange={setSelectedVoice}
/>
<textarea
className={styles.textarea}
placeholder="Type the text to be read"
rows="3"
onChange={(e) => setText(e.target.value)}
maxLength="300"
/>
<button
className={styles.button}
onClick={() => {
if (selectedVoice && text) {
setNotice("Downloading...");
getAudio();
} else {
setNotice(
`Please${!selectedVoice ? " select a voice" : ""}${
!selectedVoice && !text ? " and" : ""
}${!text ? " enter some text" : ""}!`
);
}
onClick={(e) => {
e.preventDefault();
}}
>
Download
</button>
{notice === "success" ? (
<p className={styles.notice}>
Done! Make sure to check out the{" "}
<span
style={{ cursor: "pointer", color: "var(--accent)" }}
onClick={() =>
document.querySelector("#credits button").click()
}
>
awesome people who made this possible
</span>
!
</p>
) : (
<p
className={styles.notice}
style={{ visibility: notice ? "visible" : "hidden" }}
dangerouslySetInnerHTML={{ __html: notice || "hi" }}
/>
)}
</div>

<div id="credits" className={styles.guide}>
Expand Down

0 comments on commit 180a205

Please sign in to comment.