Skip to content
This repository was archived by the owner on Dec 12, 2024. It is now read-only.
Open
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
40 changes: 22 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,59 @@
# Ren-Py-15.ai-Dubber

A python script that uses wafflecomposite/15.ai-Python-API to dub your Ren'Py game.

# Requirements

* csv
* re
* [wafflecomposite's 15.ai-Python-API](https://github.com/wafflecomposite/15.ai-Python-API)
- csv
- re
- [ffmpeg](https://www.wikihow.com/Install-FFmpeg-on-Windows)
- [wafflecomposite's 15.ai-Python-API](https://github.com/wafflecomposite/15.ai-Python-API)

# Installation

Open your project in the Ren'Py launcher. Click on "Extract Dialogue", then on "Tab-delimited Spreadsheet (dialogue.tab)", then on Continue.

Still on the launcher, click on "base". The root folder of your project will open. Inside the "game" folder, create a new folder named "voice"

Move the "dialogue.tab" file, located at the root of your game, into the "voice" folder you just created.

Back to the launcher, open your "options.rpy" file. Find the "init python:" header, and in it type ``config.auto_voice = "voice/{id}.ogg"``, like so:
Back to the launcher, open your "options.rpy" file. Find the "init python:" header, and in it type `config.auto_voice = "voice/{id}.ogg"`, like so:

**`options.rpy`**

**``options.rpy``**
```py
init python:

#Enables automatic voice
#Enables automatic voice
config.auto_voice = "voice/{id}.ogg"


## The following functions take file patterns. File patterns are case-
## insensitive, and matched against the path relative to the base directory,
## with and without a leading /. If multiple patterns match, the first is
## used.
```

Download both the ``VoiceMaker.py`` script from this repo, and [wafflecomposite's 15.ai-Python-API](https://github.com/wafflecomposite/15.ai-Python-API) ``fifteen_api.py``
Download both the `VoiceMaker.py` script from this repo, and [wafflecomposite's 15.ai-Python-API](https://github.com/wafflecomposite/15.ai-Python-API) `fifteen_api.py`

Place them both on the "voice" folder.

Open ``VoiceMaker.py`` and edit the "characters" list to the character call and the voice you want them to have. For example, I have a character who's identifier is "a", and nother who's identifier is "b". I want a to have Twilight's voice, and I want b to have Rise's. So I edit it like so: ``characters = [['a','Twilight Sparkle'],['b','Rise Kujikawa']]``. You can add as meny as you want.
Open `VoiceMaker.py` and edit the "characters" list to the character call and the voice you want them to have. For example, I have a character who's identifier is "a", and nother who's identifier is "b". I want a to have Twilight's voice, and I want b to have Rise's. So I edit it like so: `characters = [['a','Twilight Sparkle'],['b','Rise Kujikawa']]`. You can add as meny as you want.

Save and run ``VoiceMaker.py``. It will take a while. Like, a LONG while.
Save and run `VoiceMaker.py`. It will take a while. Like, a LONG while.

Once the script ends, launch your game and enjoy!

# To-Do's

If you wanna help out, look no further!

* Once all the voices have been created, it'd be nice to have some sort of check to make sure that all voices are there, since 15.ai's servers like to return a 502 error from time to time
If you wanna help out, look no further!

- Once all the voices have been created, it'd be nice to have some sort of check to make sure that all voices are there, since 15.ai's servers like to return a 502 error from time to time

# Extra Notes:

This code can also be used with [My vo.codes API](https://github.com/TheSmallBlue/Vo.codes-Python-API) just change the following lines in ``VoiceMaker.py``:
* ``from fifteen_api import FifteenAPI`` to ``from vocodes_api import VocodesAPI``
* ``tts_api = FifteenAPI()`` to ``tts_api = VocodesAPI()``
* ``tts_api.save_to_file(final_character,"Neutral",final_text,line[0] + '.wav')`` to ``tts_api.save_to_file(final_character,final_text,line[0] + '.wav')``
This code can also be used with [My vo.codes API](https://github.com/TheSmallBlue/Vo.codes-Python-API) just change the following lines in `VoiceMaker.py`:

- `from fifteen_api import FifteenAPI` to `from vocodes_api import VocodesAPI`
- `tts_api = FifteenAPI()` to `tts_api = VocodesAPI()`
- `tts_api.save_to_file(final_character,"Neutral",final_text,line[0] + '.wav')` to `tts_api.save_to_file(final_character,final_text,line[0] + '.wav')`
107 changes: 57 additions & 50 deletions VoiceMaker.py
Original file line number Diff line number Diff line change
@@ -1,67 +1,74 @@
import os
import subprocess
from fifteen_api import FifteenAPI
import csv
import re

tts_api = FifteenAPI()

characters = [['c','Twilight Sparkle'],['i','Daring Do'],['a','Adagio Dazzle'],['h','Lyra'],['n','Maud Pie']]
characters = [['c', 'Twilight Sparkle'], ['i', 'Daring Do'],
['a', 'Adagio Dazzle'], ['h', 'Lyra'], ['n', 'Maud Pie']]

previous_character = ''

def ChooseCharacter(char):
global previous_character
if char == 'extend':
return previous_character
else:
for character in characters:
if char[0] == character[0]:
current_character = character[1]
previous_character = current_character
break

return current_character

def TextCorrector(txt):
result = txt.replace("{w}","...")
result = result.replace("{i}","")
result = re.sub(r"\s*{.*}\s*", " ", result)
result = re.sub(r"\s*\[.*\]\s*", " ", result)
print(result)
return result

with open('dialogue.tab', newline='') as dialogue:
dialogue_reader = csv.reader(dialogue, delimiter='\t')

firstline = True
i = 0

for line in dialogue_reader:

if firstline:
firstline = False
continue

#Get the character
if line[1] != 'centered' and line[1] != '':

final_character = ChooseCharacter(line[1])
else:
def ChooseCharacter(char):
global previous_character
if char == 'extend':
return previous_character
else:
for character in characters:
if char == character[0]:
current_character = character[1]
previous_character = current_character
break

continue
return current_character

#Correct the text

if re.search('[a-zA-Z]',line[2]):
def TextCorrector(txt):
result = txt.replace("{w}", "...")
result = result.replace("{i}", "")
result = re.sub(r"\s*{.*}\s*", " ", result)
result = re.sub(r"\s*\[.*\]\s*", " ", result)
print(result)
return result

final_text = TextCorrector(line[2])
else:

continue
firstline = True
i = 0
full_length = 0

tts_api.save_to_file(final_character,"Neutral",final_text,line[0] + '.wav')
with open('dialogue.tab', newline='') as dialogue:
full_length = len(dialogue.readlines())

os.system("ffmpeg -i " + line[0] + ".wav " + line[0] + ".ogg")
os.remove(line[0] + ".wav")
i = i + 1
print(str(i) + '/' + str(3252))
with open('dialogue.tab', newline='') as dialogue:
dialogue_reader = csv.reader(dialogue, delimiter='\t')
for line in dialogue_reader:
id = line[0]
speaker = line[1]
dialogue = line[2]

if firstline:
firstline = False
continue

# Get the character
if speaker != '':
final_character = ChooseCharacter(speaker)
else:
continue

# Correct the text
if re.search('[a-zA-Z]', dialogue):
final_text = TextCorrector(dialogue)
else:
continue

tts_api.save_to_file(final_character,
final_text, f"{id}.wav")

subprocess.call(
f"ffmpeg -i {id}.wav -acodec libvorbis {id}.ogg", shell=True)
subprocess.call(f"del {id}.wav", shell=True)
i = i + 1
print(f"{i} / {full_length}")