from utils import settings import requests from requests.adapters import HTTPAdapter, Retry from attr import attrs, attrib from attr.validators import instance_of from TTS.common import BaseApiTTS, get_random_voice # TTS examples: https://twitter.com/scanlime/status/1512598559769702406 voices = dict() voices["nonhuman"] = [ # DISNEY VOICES "en_us_ghostface", # Ghost Face "en_us_chewbacca", # Chewbacca "en_us_c3po", # C3PO "en_us_stitch", # Stitch "en_us_stormtrooper", # Stormtrooper "en_us_rocket", # Rocket # ENGLISH VOICES ] voices["human"] = [ "en_au_001", # English AU - Female "en_au_002", # English AU - Male "en_uk_001", # English UK - Male 1 "en_uk_003", # English UK - Male 2 "en_us_001", # English US - Female (Int. 1) "en_us_002", # English US - Female (Int. 2) "en_us_006", # English US - Male 1 "en_us_007", # English US - Male 2 "en_us_009", # English US - Male 3 "en_us_010", ] voices["non_eng"] = [ "fr_001", # French - Male 1 "fr_002", # French - Male 2 "de_001", # German - Female "de_002", # German - Male "es_002", # Spanish - Male # AMERICA VOICES "es_mx_002", # Spanish MX - Male "br_001", # Portuguese BR - Female 1 "br_003", # Portuguese BR - Female 2 "br_004", # Portuguese BR - Female 3 "br_005", # Portuguese BR - Male # ASIA VOICES "id_001", # Indonesian - Female "jp_001", # Japanese - Female 1 "jp_003", # Japanese - Female 2 "jp_005", # Japanese - Female 3 "jp_006", # Japanese - Male "kr_002", # Korean - Male 1 "kr_003", # Korean - Female "kr_004", # Korean - Male 2 ] # good_voices: 'en_us_002', 'en_us_006' # ok: 'en_au_002', 'en_uk_001' # less: en_us_stormtrooper # more or less: en_us_rocket, en_us_ghostface @attrs class TikTok(BaseApiTTS): # TikTok Text-to-Speech Wrapper random_voice: bool = attrib( validator=instance_of(bool), default=False ) uri_base: str = "https://api16-normal-useast5.us.tiktokv.com/media/api/text/speech/invoke/" max_chars: int = 300 decode_base64: bool = True def make_request( self, text: str, ): """ Makes a requests to remote TTS service Args: text: text to be voice over Returns: Request's response """ voice = ( get_random_voice(voices, "human") if self.random_voice else str(settings.config["settings"]["tts"]["tiktok_voice"]).lower() if str(settings.config["settings"]["tts"]["tiktok_voice"]).lower() in [ voice.lower() for dict_title in voices for voice in voices[dict_title]] else get_random_voice(voices, "human") ) try: r = requests.post( self.uri_base, params={ "text_speaker": voice, "req_text": text, "speaker_map_type": 0, }) except requests.exceptions.SSLError: # https://stackoverflow.com/a/47475019/18516611 session = requests.Session() retry = Retry(connect=3, backoff_factor=0.5) adapter = HTTPAdapter(max_retries=retry) session.mount("http://", adapter) session.mount("https://", adapter) r = session.post(f"{self.uri_base}{voice}&req_text={text}&speaker_map_type=0") # print(r.text) return r.json()["data"]["v_str"]