С Днём России!
  • 2.582
  • 6
Дорогие друзья! Поздравляю вас с Днём России! Этот праздник напоминает нам о богатой истории и культуре нашей страны, о её величии и непоколебимом духе народа! Желаю вам крепкого здоровья...
Новости Анонсирован Atomic Heart II
Новости Анонсирован ремастер Final Fantasy Tactics
  • 961
  • 1
Культовая пошаговая тактическая RPG от Square Enix получит второе дыхание. На проходящей выставке State of Play, где анонсируются игры для Play Station, состоялся анонс ремастера Final Fantasy...
Новости Моддеры Oblivion Remastered нашли способ внедрения абсолютно любых скриптов
  • 1.157
  • 4
Сообщество моддинга Oblivion Remastered (ORM) переживает настоящий расцвет. После долгих месяцев работы, энтузиасты научили игру работать с мощным скриптовым языком Lua, открыв перед создателями...

В процессе Gothic II auto dubbing script?

rockysx27

Новичок
Регистрация
25 Мар 2023
Сообщения
4
Реакции
0
Баллы
0
Лучшие ответы
0
#1
Я написал этот Python код и создал репозиторий на GitHub для него. Для работы нужно подключить Elevenlabs API и создать там голос. Когда я тестировал его, код создал 100 файлов с речью за несколько минут, и я быстро исчерпал кредиты, но решил поделиться, потому что не видел подобного решения для Elevenlabs.

Но у меня возник вопрос: есть ли лучший способ озвучить текст? Мой код может быть не идеальным, и я был бы рад услышать предложения по улучшению.

github

Python:
import os
import uuid
import pandas as pd
import tkinter as tk
from tkinter import filedialog
from elevenlabs.client import ElevenLabs
from elevenlabs import VoiceSettings
import csv

# Set ElevenLabs API Key
ELEVENLABS_API_KEY = "API KEY"
ELEVENLABS_VOICE_KEY = "VOICE KEY"

# Initialize ElevenLabs client
client = ElevenLabs(api_key=ELEVENLABS_API_KEY)

# Function to select a folder (for the case you still want to use folder selection manually)
def select_folder(prompt):
root = tk. Tk()
    root.withdraw()
    return filedialog.askdirectory(title=prompt)

# Function to generate TTS and save it to file using the official docs method
def elevenlabs_text_to_speech(text, output_path, voice_id):
    try:
        response = client.text_to_speech.convert(
            voice_id=voice_id,
            output_format="mp3_22050_32",
            text=text,
            model_id="eleven_turbo_v2_5",  # using the turbo model for low latency
            voice_settings=VoiceSettings(
                stability=0.0,
                similarity_boost=1.0,
                style=0.0,
                use_speaker_boost=True,
            ),
        )
        with open(output_path, "wb") as f:
            for chunk in response:
                if chunk:
                    f.write(chunk)
        print(f"Generated: {output_path}")
    except Exception as e:
        print(f"❌ Failed to generate audio: {e}")

def read_and_filter_csv(csv_file):
    """
    Read the CSV file line by line and keep only the rows that:
      - Split into exactly 7 fields (tab-delimited)
      - Have the 6th column equal to "SUBTITLE" (case-insensitive)
    """
    filtered_rows = []
    with open(csv_file, 'r', encoding='utf-8') as f:
        for line in f:
            fields = line.strip().split('\t')
            if len(fields) == 7 and fields[5].strip().upper() == "SUBTITLE":
                filtered_rows.append(fields)
    return filtered_rows

# Main function
def main():
    # Set directories relative to the script
    script_dir = os.path.dirname(os.path.abspath(__file__))
    input_folder = os.path.join(script_dir, "INPUT_DUBBING")
    output_folder = os.path.join(script_dir, "OUTPUT_DUBBING")
    csv_file = os.path.join(script_dir, "DIALOGUES.csv")
    
    # Ask for the filter string (optional)
    filter_string = input("🔍 Enter filter string (only process files whose names contain this string; leave blank for all): ").strip()

    if not os.path.exists(input_folder) or not os.path.exists(output_folder) or not os.path.exists(csv_file):
        print("⚠️ Error: One or more required files/folders are missing.")
        input("Press Enter to exit...")
        return

    # Read and filter CSV file
    try:
        rows = read_and_filter_csv(csv_file)
        if not rows:
            raise ValueError("No valid rows found in CSV file with the correct format and 'SUBTITLE' type.")
df = pd. DataFrame(rows, columns=["col1", "col2", "col3", "sound_name", "ai_output", "type", "text"])
        # Create a translation map with keys in uppercase for robust matching
        translation_map = {row["sound_name"].strip().upper(): row["text"].strip()
                           for _, row in df.iterrows()}
    except Exception as e:
        print(f"⚠️ Error reading CSV file: {e}")
        input("Press Enter to exit...")
        return

    # Process files in the input folder
    for file_name in os.listdir(input_folder):
        # Remove file extension from the name
        name_without_ext = os.path.splitext(file_name)[0].strip()
        lookup_name = name_without_ext.upper()  # Ensure comparison is case-insensitive

        # Apply the filter: if a filter string is provided, only process if it is contained in the name
        if filter_string and filter_string.upper() not in lookup_name:
            print(f"Skipping {file_name} because it does not contain the filter '{filter_string}'.")
            continue

        text = None
        # Look for a CSV key that is a prefix of the lookup name (no extension in CSV)
        for key in translation_map:
            if lookup_name.startswith(key):  # Compare the name without extension
                text = translation_map[key]
                break

        if text:
            output_file = os.path.join(output_folder, f"{name_without_ext}.mp3")  # Save without extension
            if os.path.exists(output_file):
                print(f"⏭️ Skipped: {output_file} (Already exists)")
                continue
                
            elevenlabs_text_to_speech(text, output_file, voice_id=ELEVENLABS_VOICE_KEY)
        else:
            print(f"⚠️ Warning: No translation found for {name_without_ext}")

    input("\n✅ All tasks completed! Press Enter to exit...")

if __name__ == "__main__":
    main()
 
Сверху Снизу