Skip to content
Merged
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 .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"vscode": {
"extensions": [
"mechatroner.rainbow-csv",
"eamodio.gitlens"
"eamodio.gitlens",
"charliermarsh.ruff"
]
}
}
Expand Down
6 changes: 5 additions & 1 deletion .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@ sudo apt-get update && sudo apt-get install -y dotnet-sdk-6.0
dotnet tool install --global Microsoft.CognitiveServices.Speech.CLI

# Install the Azure Speech SDK for Python
python -m pip install azure-cognitiveservices-speech
python -m pip install azure-cognitiveservices-speech ffmpeg-normalize

# Install ffmpeg for GLaDOS post-processing and release generation
sudo apt-get install -y ffmpeg
python -m pip install ffmpeg-normalize
111 changes: 71 additions & 40 deletions generate.sh
Original file line number Diff line number Diff line change
@@ -1,50 +1,81 @@
#!/bin/bash

working_dir=$(pwd)
# Get the directory of the script
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Change to the script's directory
cd "${script_dir}" || exit 1

check_dependencies() {
if [ ! -f "${working_dir}/voice-gen.py" ]; then
echo "Script halt: voice-gen.py not found in '${working_dir}'"
if [ ! -f "${script_dir}/voice-gen.py" ]; then
echo "Script halt: voice-gen.py not found in '${script_dir}'"
exit 1
fi
}

check_file_exists() {
if [ ! -f "$1" ]; then
echo "Error: File $1 not found!" >&2
exit 1
fi
}

check_dependencies
check_file_exists "${script_dir}/voice-gen.py"
check_file_exists "${script_dir}/voice-gen-glados.py"

# Delete logs from previous pass
find . -name "*.log" -delete

# Azure TTS voice configurations
voices=(
"./voices/cs-CZ.csv cs-CZ-VlastaNeural cz"
"./voices/da_DK.csv da-DK-ChristelNeural da"
"./voices/da_DK_scripts.csv da-DK-ChristelNeural da/SCRIPTS"
"./voices/de-DE.csv de-DE-KatjaNeural de"
"./voices/en-GB.csv en-IE-EmilyNeural en"
"./voices/en-GB_scripts.csv en-IE-EmilyNeural en/SCRIPTS"
"./voices/en-GB.csv en-GB-LibbyNeural en_gb-libby"
"./voices/en-GB_scripts.csv en-GB-LibbyNeural en_gb-libby/SCRIPTS"
"./voices/en-GB.csv en-GB-RyanNeural en_gb-ryan"
"./voices/en-GB_scripts.csv en-GB-RyanNeural en_gb-ryan/SCRIPTS"
"./voices/en-US.csv en-US-GuyNeural en_us-guy"
"./voices/en-US_scripts.csv en-US-GuyNeural en_us-guy/SCRIPTS"
"./voices/en-US.csv en-US-MichelleNeural en_us-michelle"
"./voices/en-US_scripts.csv en-US-MichelleNeural en_us-michelle/SCRIPTS"
"./voices/en-US.csv en-US-SaraNeural en_us-sara"
"./voices/en-US_scripts.csv en-US-SaraNeural en_us-sara/SCRIPTS"
"./voices/es-CL.csv es-CL-CatalinaNeural es_cl-catalina"
"./voices/es-ES.csv es-ES-ElviraNeural es"
"./voices/fr-FR.csv fr-FR-DeniseNeural fr"
"./voices/it-IT.csv it-IT-ElsaNeural it"
"./voices/it-IT_scripts.csv it-IT-ElsaNeural it/SCRIPTS"
"./voices/ja-JP.csv ja-JP-NanamiNeural jp"
"./voices/ja-JP_scripts.csv ja-JP-NanamiNeural jp/SCRIPTS"
"./voices/pt-PT.csv pt-BR-FranciscaNeural pt"
"./voices/ru-RU.csv ru-RU-SvetlanaNeural ru"
"./voices/sv-SE.csv sv-SE-SofieNeural se --pitch 'dn10%' --rate 'dn0.9'"
"./voices/sv-SE_scripts.csv sv-SE-SofieNeural se/SCRIPTS --pitch 'dn10%' --rate 'dn0.9'"
"./voices/uk-UA.csv uk-UA-OstapNeural ua-ostap"
"./voices/uk-UA.csv uk-UA-PolinaNeural ua-polina"
"./voices/zh-CN.csv zh-CN-XiaoxiaoNeural cn"
"./voices/zh-TW.csv zh-TW-HsiaoChenNeural tw"
"./voices/zh-HK.csv zh-HK-HiuGaaiNeural hk --rate 'dn1.2'"
)

# Loop through the Azure TTS configurations
for voice in "${voices[@]}"; do
# Use eval to handle parameters with spaces (e.g., --pitch and --rate)
eval "./voice-gen.py ${voice}" || exit 1
done

# GLaDOS-specific configurations
glados_voices=(
"./voices/en-GB.csv en_gb-glados"
"./voices/en-GB_scripts.csv en_gb-glados/SCRIPTS"
)

# delete logs from previous pass
find "$(dirname "$0")" -name "*.log" -delete

./voice-gen.py voices/cs-CZ.csv cs-CZ-VlastaNeural cz || exit 1
./voice-gen.py voices/da_DK.csv da-DK-ChristelNeural da || exit 1
./voice-gen.py voices/da_DK_scripts.csv da-DK-ChristelNeural da/SCRIPTS || exit 1
./voice-gen.py voices/de-DE.csv de-DE-KatjaNeural de || exit 1
./voice-gen.py voices/en-GB.csv en-IE-EmilyNeural en || exit 1
./voice-gen.py voices/en-GB_scripts.csv en-IE-EmilyNeural en/SCRIPTS || exit 1
./voice-gen.py voices/en-GB.csv en-GB-LibbyNeural en_gb-libby || exit 1
./voice-gen.py voices/en-GB_scripts.csv en-GB-LibbyNeural en_gb-libby/SCRIPTS || exit 1
./voice-gen.py voices/en-GB.csv en-GB-RyanNeural en_gb-ryan || exit 1
./voice-gen.py voices/en-GB_scripts.csv en-GB-RyanNeural en_gb-ryan/SCRIPTS || exit 1
./voice-gen-glados.py voices/en-GB.csv en_gb-glados || exit 1
./voice-gen-glados.py voices/en-GB_scripts.csv en_gb-glados/SCRIPTS || exit 1
./voice-gen.py voices/en-US.csv en-US-GuyNeural en_us-guy || exit 1
./voice-gen.py voices/en-US_scripts.csv en-US-GuyNeural en_us-guy/SCRIPTS || exit 1
./voice-gen.py voices/en-US.csv en-US-MichelleNeural en_us-michelle || exit 1
./voice-gen.py voices/en-US_scripts.csv en-US-MichelleNeural en_us-michelle/SCRIPTS || exit 1
./voice-gen.py voices/en-US.csv en-US-SaraNeural en_us-sara || exit 1
./voice-gen.py voices/en-US_scripts.csv en-US-SaraNeural en_us-sara/SCRIPTS || exit 1
./voice-gen.py voices/es-CL.csv es-CL-CatalinaNeural es_cl-catalina || exit 1
./voice-gen.py voices/es-ES.csv es-ES-ElviraNeural es || exit 1
./voice-gen.py voices/fr-FR.csv fr-FR-DeniseNeural fr || exit 1
./voice-gen.py voices/it-IT.csv it-IT-ElsaNeural it || exit 1
./voice-gen.py voices/it-IT_scripts.csv it-IT-ElsaNeural it/SCRIPTS || exit 1
./voice-gen.py voices/ja-JP.csv ja-JP-NanamiNeural jp || exit 1
./voice-gen.py voices/ja-JP_scripts.csv ja-JP-NanamiNeural jp/SCRIPTS || exit 1
./voice-gen.py voices/pt-PT.csv pt-BR-FranciscaNeural pt || exit 1
./voice-gen.py voices/ru-RU.csv ru-RU-SvetlanaNeural ru || exit 1
./voice-gen.py voices/sv-SE.csv sv-SE-SofieNeural se --pitch "dn10%" --rate "dn0.9" || exit 1
./voice-gen.py voices/sv-SE_scripts.csv sv-SE-SofieNeural se/SCRIPTS --pitch "dn10%" --rate "dn0.9" || exit 1
./voice-gen.py voices/uk-UA.csv uk-UA-OstapNeural ua-ostap || exit 1
./voice-gen.py voices/uk-UA.csv uk-UA-PolinaNeural ua-polina || exit 1
./voice-gen.py voices/zh-CN.csv zh-CN-XiaoxiaoNeural cn || exit 1
./voice-gen.py voices/zh-TW.csv zh-TW-HsiaoChenNeural tw || exit 1
./voice-gen.py voices/zh-HK.csv zh-HK-HiuGaaiNeural hk --rate "dn1.2" || exit 1
# Loop through the GLaDOS configurations
for glados_voice in "${glados_voices[@]}"; do
eval "./voice-gen-glados.py ${glados_voice}" || exit 1
done
20 changes: 11 additions & 9 deletions voice-gen-glados.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@
import argparse
import csv
import os
import re
import sys
import tempfile
import time
from pathlib import Path
import urllib.request
import urllib.parse
import tempfile
import urllib.request


def init_argparse() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
usage="%(prog)s [FILE] [LANGDIR]",
usage="%(prog)s [FILE] [LANGDIR] [-s DELAY]",
description="Generate voice packs from CSV list using https://glados.c-net.org/"
)

Expand All @@ -34,9 +33,9 @@ def init_argparse() -> argparse.ArgumentParser:
parser.add_argument('-s',
'--delay',
type=int,
help="Sleep time processing each translation",
help="Sleep time (in seconds) between processing each translation",
required=False,
default='3'
default=3
)

return parser
Expand All @@ -51,7 +50,7 @@ def try_fetch_sample(req: urllib.request.Request, outfile_fd):
out.write(content)
return
else:
raise ValueError(f"Content returned isn't a WAV file")
raise ValueError("Content returned isn't a WAV file!")
raise ValueError(f"Speech synthesis failed with status code: {response.status}")

def fetch_sample(text: str, outfile_fd, delay_time: int):
Expand All @@ -76,6 +75,9 @@ def main() -> None:
parser = init_argparse()
args = parser.parse_args()

# Print which script is running and the file being processed
print(f"Running {os.path.basename(__file__)} to process file: {args.file}")

csv_file = args.file
csv_rows = 0
langdir = args.langdir
Expand Down Expand Up @@ -135,7 +137,7 @@ def main() -> None:

line_count += 1

print(f'Finished processing {csv_rows} entries from "{csv_file}".')
print(f'Finished processing {csv_rows} entries from "{csv_file}" using {os.path.basename(__file__)}.')


if __name__ == "__main__":
Expand Down
15 changes: 9 additions & 6 deletions voice-gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

def init_argparse() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
usage="%(prog)s [FILE] [VOICE] [LANGDIR]",
usage="%(prog)s [FILE] [VOICE] [LANGDIR] [-l LOCALE] [-p PITCH] [-r RATE] [-s DELAY]",
description="Generate voice packs from CSV list."
)

Expand Down Expand Up @@ -54,22 +54,22 @@ def init_argparse() -> argparse.ArgumentParser:

parser.add_argument('-p',
'--pitch',
help="Pitch adjustment",
help="Pitch adjustment (e.g., 'up10%', 'dn5%')",
type=str,
default="default")

parser.add_argument('-r',
'--rate',
help="Rate adjustment",
help="Rate adjustment (e.g., 'up10%', 'dn5%')",
type=str,
default="default")

parser.add_argument('-s',
'--delay',
type=int,
help="Sleep time processing each translation",
help="Sleep time (in seconds) between processing each translation",
required=False,
default='3'
default=3
)

return parser
Expand All @@ -79,6 +79,9 @@ def main() -> None:
parser = init_argparse()
args = parser.parse_args()

# Print which script is running and the file being processed
print(f"Running {os.path.basename(__file__)} to process file: {args.file}")

csv_file = args.file
csv_rows = 0
voice = args.voice
Expand Down Expand Up @@ -194,7 +197,7 @@ def main() -> None:

line_count += 1

print(f'Finished processing {csv_rows} entries from "{csv_file}".')
print(f'Finished processing {csv_rows} entries from "{csv_file}" using {os.path.basename(__file__)}.')


if __name__ == "__main__":
Expand Down