Skip to content

Consistency and volume is no consistent #40

Description

@moh1tx

i tried a lot to fix Consistency but i can't
if anyone can fix please do, i want it can generate longer text with pretty consistency

import json
import torch
import nltk
import soundfile as sf
import uuid
import os
import aiofiles
import asyncio
from transformers import AutoTokenizer, AutoFeatureExtractor
from parler_tts import ParlerTTSForConditionalGeneration

class TTS:
    @classmethod
    async def create(cls, config_path="config.json"):
        instance = cls()
        await instance._initialize(config_path)
        return instance

    def __init__(self):
        pass

    async def _initialize(self, config_path="config.json"):
        async with aiofiles.open(config_path, 'r') as f:
            self.config = json.loads(await f.read())

        self.models_dir = self.config['models']['src']
        self.model_name = self.config['models']['model']

        self.device = "cuda:0" if torch.cuda.is_available() else "cpu"

        self.model = await asyncio.to_thread(
            ParlerTTSForConditionalGeneration.from_pretrained,
            self.model_name, cache_dir=self.models_dir
        )
        self.model = self.model.to(self.device)

        self.tokenizer = await asyncio.to_thread(
            AutoTokenizer.from_pretrained,
            self.model_name, cache_dir=self.models_dir
        )
        self.description_tokenizer = await asyncio.to_thread(
            AutoTokenizer.from_pretrained,
            self.model.config.text_encoder._name_or_path, cache_dir=self.models_dir
        )
        self.feature_extractor = await asyncio.to_thread(
            AutoFeatureExtractor.from_pretrained,
            self.model_name, cache_dir=self.models_dir
        )
        self.sampling_rate = self.feature_extractor.sampling_rate

    def chunk_text(self, text, max_chunk_size=25):
        sentences = nltk.sent_tokenize(text)
        chunks = []
        current_chunk = []
        current_word_count = 0

        for sentence in sentences:
            sentence_words = sentence.split()
            sentence_word_count = len(sentence_words)

            if sentence_word_count > max_chunk_size:
                if current_chunk:
                    chunks.append(" ".join(current_chunk))
                    current_chunk = []
                    current_word_count = 0
                words = sentence_words
                while words:
                    chunk = words[:max_chunk_size]
                    chunks.append(" ".join(chunk))
                    words = words[max_chunk_size:]
                continue

            if current_word_count + sentence_word_count > max_chunk_size:
                if current_chunk:
                    chunks.append(" ".join(current_chunk))
                current_chunk = [sentence]
                current_word_count = sentence_word_count
            else:
                current_chunk.append(sentence)
                current_word_count += sentence_word_count

        if current_chunk:
            chunks.append(" ".join(current_chunk))

        return chunks

    @torch.inference_mode()
    async def generate(self, text, description, output_folder, seed=42, pitch_scale=1.0, speed_scale=1.0, energy_scale=1.0):
        await asyncio.to_thread(nltk.download, 'punkt_tab', quiet=True)

        chunks = self.chunk_text(text)

        # Use the provided seed, defaulting to 42
        torch.manual_seed(seed)
        if torch.cuda.is_available():
            torch.cuda.manual_seed(seed)  # Set seed for CUDA as well

        # Prepare description input
        description_input = await asyncio.to_thread(
            self.description_tokenizer,
            description, return_tensors="pt"
        )
        description_input = description_input.to(self.device)

        audio_chunks = []

        for chunk in chunks:
            # Reset the seed before each chunk to ensure consistency
            torch.manual_seed(seed)
            if torch.cuda.is_available():
                torch.cuda.manual_seed(seed)

            prompt_input = await asyncio.to_thread(
                self.tokenizer,
                chunk, return_tensors="pt"
            )
            prompt_input = prompt_input.to(self.device)

            generation = await asyncio.to_thread(
                self.model.generate,
                input_ids=description_input.input_ids,
                attention_mask=description_input.attention_mask,
                prompt_input_ids=prompt_input.input_ids,
                prompt_attention_mask=prompt_input.attention_mask,
                do_sample=True,
                temperature=0.7,
                top_p=0.95,
                return_dict_in_generate=True,
                pitch_scale=pitch_scale,
                speed_scale=speed_scale,
                energy_scale=energy_scale
            )

            audio = generation.sequences[0, :generation.audios_length[0]]
            audio_chunks.append(audio.to(torch.float32))

        final_audio = torch.cat(audio_chunks)
        audio_array = final_audio.cpu().numpy().squeeze().tolist()
        output_file = os.path.join(output_folder, f"{uuid.uuid4().hex}.wav")
        await asyncio.to_thread(sf.write, output_file, audio_array, self.sampling_rate)
        return audio_array, self.sampling_rate```

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions