Skip to content
This repository has been archived by the owner on Jan 30, 2024. It is now read-only.

add TikTok TTS #232

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"discord.enabled": true
"discord.enabled": true,
"python.formatting.provider": "black"
}
21 changes: 21 additions & 0 deletions API/tiktok.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
import httpx


class Tiktok:
def get_tts(text: str, voice_name: str) -> str or None:
"""Get the TikTok Voice TTS.

:param text: The text to be spoken.
:param voice_name: The name of the voice to be used.
:return: The Base64 encoded mp3.

Returns:
--------
return "..."
"""

response = httpx.get(
f"https://tiktokaittsdonations.mmattdonk.workers.dev/?text={text}&voice={voice_name.split(':')[1]}",
)
return None if response.status_code != 200 else response.text
137 changes: 83 additions & 54 deletions bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-

import asyncio
import base64
import contextlib
import json
import logging
Expand All @@ -17,11 +18,10 @@
from tkinter import Button, Canvas, Entry, PhotoImage, Tk
from typing import Optional
from uuid import UUID
import sentry_sdk


import httpx
import nest_asyncio
import sentry_sdk
import simpleaudio
import socketio
import soundfile as sf
Expand All @@ -44,8 +44,8 @@
from twitchAPI.twitch import Twitch
from twitchAPI.types import AuthScope


from API.fakeyou import Fakeyou
from API.tiktok import Tiktok
from API.uberduck import Uberduck

VERSION: str = "3.1.5"
Expand Down Expand Up @@ -239,6 +239,48 @@ def post_version_number(twitch_id: int, version: str) -> bool:
return response.status_code == 200


def apply_voice_effect(date_string, voice_effect) -> str:
audio, sample_rate = sf.read(f"./voice_files/AI_voice_{date_string}.wav")
board = Pedalboard([])

for effect in voice_effect:
if effect.lower() in VOICE_EFFECTS:
log.info(f"Voice Effect Detected: {effect}")
if type(VOICE_EFFECTS[effect]) == list:
for effect_func in VOICE_EFFECTS[effect]:
board.append(effect_func)
else:
board.append(VOICE_EFFECTS[effect])

effected = board(audio, sample_rate)
sf.write(
f"./voice_files/AI_voice_{date_string}.wav",
effected,
sample_rate,
)

for effect in voice_effect:
if effect.lower() in VOICE_EFFECTS and effect == "loud":
# Making the "loud" effect quieter because it's too loud.
# If anyone knows how to work a limiter or a compressor you can edit the VOICE_EFFECTS if you want :p
# Also there is probably a way to make this work in the loop above, but idk.
# So if anyone wants to take a shot at that, then go ahead
# I love free labor / code
# FeelsGoodMan

board.append(Gain(gain_db=-15))

effected = board(audio, sample_rate)
log.debug("?")
sf.write(
f"./voice_files/AI_voice_{date_string}.wav",
effected,
sample_rate,
)

return f"./voice_files/AI_voice_{date_string}.wav"


def request_tts(message: str, failed: Optional[bool] = False) -> None:
# sourcery no-metrics
messages: list = message.split("||")
Expand Down Expand Up @@ -339,15 +381,47 @@ def request_tts(message: str, failed: Optional[bool] = False) -> None:

if voice_name.startswith("TM:"):
tts_provider = Fakeyou
elif voice_name.startswith("TT:"):
tts_provider = Tiktok
else:
tts_provider = Uberduck
voice_name.lower()

job_response: dict = tts_provider.get_job(text, voice_name)
if tts_provider is not Tiktok:
job_response: dict = tts_provider.get_job(text, voice_name)
elif tts_provider is Tiktok:
base64_data: str = tts_provider.get_tts(text, voice_name)

if base64_data is None:
try:
fallback_voice: str = config["FALLBACK_VOICE"]
except:
fallback_voice: str = "kanye-west-rap"

log.info(
"Couldn't find voice specified, using fallback voice: "
+ fallback_voice
)
job_response: dict = Uberduck.get_job(text, fallback_voice)
else:
date_string: str = datetime.now().strftime("%d%m%Y%H%M%S")
file_name = f"./voice_files/AI_voice_{date_string}.wav"

decode_string = base64.b64decode(base64_data)
sf.write(file_name, decode_string, 24000)

# this entire script needs a rewrite SO bad.
job_response = {"detail": None, "uuid": None}

log.debug(job_response)
if voice_effect:
apply_voice_effect(date_string, voice_effect)

if job_response["detail"] != None:
voice_files.append(file_name)

# if job_response != None:
# log.debug(job_response)

if tts_provider is not Tiktok or job_response["detail"] != None:
if job_response["detail"] == "That voice does not exist":
try:
fallback_voice: str = config["FALLBACK_VOICE"]
Expand All @@ -360,7 +434,7 @@ def request_tts(message: str, failed: Optional[bool] = False) -> None:
)
job_response: dict = Uberduck.get_job(text, fallback_voice)

if job_response["uuid"] is not None:
if tts_provider is not Tiktok or job_response["detail"] != None:
log.info("UUID recieved. Waiting for TTS to process")
checkCount: int = 0
waitingToProcess: bool = True
Expand All @@ -381,53 +455,7 @@ def request_tts(message: str, failed: Optional[bool] = False) -> None:
reset_overlay()

if voice_effect:
audio, sample_rate = sf.read(
f"./voice_files/AI_voice_{date_string}.wav"
)
board = Pedalboard([])

for effect in voice_effect:
if effect.lower() in VOICE_EFFECTS:
log.info("Voice Effect Detected: " + effect)
if type(VOICE_EFFECTS[effect]) == list:
for effect_func in VOICE_EFFECTS[effect]:
board.append(effect_func)
else:
board.append(VOICE_EFFECTS[effect])
else:
pass

effected = board(audio, sample_rate)
sf.write(
f"./voice_files/AI_voice_{date_string}.wav",
effected,
sample_rate,
)

for effect in voice_effect:
if effect.lower() in VOICE_EFFECTS:
if effect == "loud":
# Making the "loud" effect quieter because it's too loud.
# If anyone knows how to work a limiter or a compressor you can edit the VOICE_EFFECTS if you want :p
# Also there is probably a way to make this work in the loop above, but idk.
# So if anyone wants to take a shot at that, then go ahead
# I love free labor / code
# FeelsGoodMan

board.append(Gain(gain_db=-15))

effected = board(audio, sample_rate)
log.debug("?")
sf.write(
f"./voice_files/AI_voice_{date_string}.wav",
effected,
sample_rate,
)
else:
pass
else:
pass

apply_voice_effect(date_string, voice_effect)
else:
pass

Expand Down Expand Up @@ -473,6 +501,7 @@ def thread_function():
sound = q.get()
if sound is None:
return
print(sound)
sound_obj = simpleaudio.WaveObject.from_wave_file(sound)
play_obj = sound_obj.play()
play_obj.wait_done()
Expand Down