Created
February 26, 2025 21:00
-
-
Save loretoparisi/e01f09a9b4de27e262bedc059012bf5c to your computer and use it in GitHub Desktop.
saymp3: TSS to mp3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Function to display usage instructions | |
usage() { | |
echo "Usage: $0 [options] [\"Text to speak\"]" | |
echo "" | |
echo "Options:" | |
echo " -o, --output FILE Output file name (default: output.mp3)" | |
echo " -l, --language CODE Language code (en, es, fr, de, it, ja, zh, etc.)" | |
echo " -h, --help Display this help message" | |
echo "" | |
echo "Examples:" | |
echo " $0 \"Hello World\" # Basic usage" | |
echo " $0 \"Hola Mundo\" -o greeting.mp3 -l es # Spanish with custom filename" | |
echo " echo \"Hello\" | $0 # Pipe input" | |
echo " cat file.txt | $0 -l fr # Pipe from file with French language" | |
echo " $0 -l list # List all available voices" | |
exit 1 | |
} | |
# Default values | |
OUTPUT_FILE="output.mp3" | |
LANGUAGE="" | |
VOICE="" | |
TEXT="" | |
# Check if we have stdin input (piped) | |
if [ -p /dev/stdin ]; then | |
# Read from stdin | |
TEXT=$(cat) | |
PIPE_MODE=true | |
else | |
PIPE_MODE=false | |
fi | |
# Parse arguments | |
while [[ $# -gt 0 ]]; do | |
case $1 in | |
-o|--output) | |
OUTPUT_FILE="$2" | |
shift 2 | |
;; | |
-l|--language) | |
LANGUAGE="$2" | |
shift 2 | |
;; | |
-h|--help) | |
usage | |
;; | |
*) | |
# If we didn't get text from pipe, use this argument | |
if [ "$PIPE_MODE" = false ]; then | |
TEXT="$1" | |
fi | |
shift | |
;; | |
esac | |
done | |
# Check if we have text to speak | |
if [ -z "$TEXT" ]; then | |
echo "Error: No text provided to speak. Use piped input or provide text as an argument." | |
usage | |
fi | |
# Select voice based on language code | |
if [ -n "$LANGUAGE" ]; then | |
case "$LANGUAGE" in | |
"en") VOICE="Alex" ;; # English | |
"es") VOICE="Juan" ;; # Spanish | |
"fr") VOICE="Thomas" ;; # French | |
"de") VOICE="Anna" ;; # German | |
"it") VOICE="Luca" ;; # Italian | |
"ja") VOICE="Kyoko" ;; # Japanese | |
"zh") VOICE="Tingting" ;; # Chinese | |
"pt") VOICE="Joana" ;; # Portuguese | |
"ru") VOICE="Milena" ;; # Russian | |
"ar") VOICE="Maged" ;; # Arabic | |
"nl") VOICE="Claire" ;; # Dutch | |
"sv") VOICE="Alva" ;; # Swedish | |
"da") VOICE="Magnus" ;; # Danish | |
"fi") VOICE="Satu" ;; # Finnish | |
"no") VOICE="Nora" ;; # Norwegian | |
"ko") VOICE="Yuna" ;; # Korean | |
"pl") VOICE="Zosia" ;; # Polish | |
"cs") VOICE="Zuzana" ;; # Czech | |
"el") VOICE="Melina" ;; # Greek | |
"tr") VOICE="Yelda" ;; # Turkish | |
"hu") VOICE="Mariska" ;; # Hungarian | |
"list") | |
echo "Available voices on your system:" | |
say -v "?" | |
exit 0 | |
;; | |
*) echo "Warning: Unknown language code '$LANGUAGE'. Using system default voice." | |
VOICE="" ;; | |
esac | |
if [ -n "$VOICE" ]; then | |
VOICE_PARAM="-v $VOICE" | |
echo "Using voice: $VOICE for language: $LANGUAGE" | |
fi | |
fi | |
# Remove .mp3 extension if present to avoid issues | |
BASE_NAME="${OUTPUT_FILE%.mp3}" | |
TEMP_AIFF="${BASE_NAME}_temp.aiff" | |
# Check if ffmpeg is installed | |
if ! command -v ffmpeg &> /dev/null; then | |
echo "Error: ffmpeg is not installed. Please install it first." | |
echo "You can install it with: brew install ffmpeg" | |
exit 1 | |
fi | |
# Use the say command to save the text as temporary aiff audio | |
if [ -n "$VOICE_PARAM" ]; then | |
say $VOICE_PARAM -o "$TEMP_AIFF" "$TEXT" | |
else | |
say -o "$TEMP_AIFF" "$TEXT" | |
fi | |
# Check if the say command was successful | |
if [ $? -ne 0 ]; then | |
echo "Error: Failed to create audio file with say command" | |
exit 1 | |
fi | |
# Convert the aiff to mp3 using ffmpeg | |
ffmpeg -i "$TEMP_AIFF" -y -acodec libmp3lame -ab 128k "${BASE_NAME}.mp3" -loglevel error | |
# Check if the conversion was successful | |
if [ $? -eq 0 ]; then | |
# Remove the temporary aiff file | |
rm "$TEMP_AIFF" | |
echo "Audio successfully saved to: ${BASE_NAME}.mp3" | |
else | |
echo "Error: Failed to convert to mp3" | |
# Keep the aiff file in case user wants it | |
echo "Temporary AIFF file is available at: $TEMP_AIFF" | |
exit 1 | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Basic usage
./sayit.sh "Hello World"
Pipe input
echo "Ciao" | ./sayit.sh
Pipe input with language specification
echo "Hola mundo" | ./sayit.sh --language es
Pipe from a file with custom output name
cat message.txt | ./sayit.sh --output message.mp3
List available voices
./sayit.sh --language list