Hello everyone,
This is not a question about third-party scripts, but I would like to provide you my "bash" script, which I am using to generate ".talk" files using "espeak" and rockbox's "rbspeexenc" program for my SanDisk Sansa Clip+ on Linux.
Prerequisites:
Compile "rbspeexenc":
$ make --directory="<some_path>/rockbox/tools/rbspeex"
The script expects, that every music file is saved as ".aac".
It checks, if the following directories in the current working directory exist: "audiobooks", "normal_music", "unusual_music" and "podcasts".
After that it searches for every subdirectory of these four directories.
Then, it navigates to each directory saving its name as variable and listing all ".aac" files.
It then generates a mono 16bit ".wav" file, called "_dirname.wav" via "espeak" with the variable, which is then immediately encoded via "rbspeexenc" as ".talk" file. After that the ".wav" file is removed.
The same process applies to each music file as well, but the suffix ".aac" is not spoken by "espeak".
Finally, the script navigates back to current working directory and then enters the next directory of the list.
Be aware, that "find" and Bash arrays do not sort alphabetically!
Example output:
Entering directory: 'normal_music/Digimon'.
Generating 'espeak' voice file: '_dirname.wav'.
Encoding 'espeak' voice file: '_dirname.wav' to 'rockbox' voice file: '_dirname.talk'.
Removing 'espeak' voice file: '_dirname.wav'.
Leaving directory: 'normal_music/Digimon'.
Entering directory: 'normal_music/Digimon/1Digimon Vol.1'.
Generating 'espeak' voice file: '_dirname.wav'.
Encoding 'espeak' voice file: '_dirname.wav' to 'rockbox' voice file: '_dirname.talk'.
Removing 'espeak' voice file: '_dirname.wav'.
Generating 'espeak' voice file: '01. Leb deinen Traum.aac.wav'.
Encoding 'espeak' voice file: '01. Leb deinen Traum.aac.wav' to 'rockbox' voice file: '01. Leb deinen Traum.aac.talk'.
Removing 'espeak' voice file: '01. Leb deinen Traum.aac.wav'.
Generating 'espeak' voice file: '02. Wir werden siegen.aac.wav'.
Encoding 'espeak' voice file: '02. Wir werden siegen.aac.wav' to 'rockbox' voice file: '02. Wir werden siegen.aac.talk'.
Removing 'espeak' voice file: '02. Wir werden siegen.aac.wav
[...]
Leaving directory: 'normal_music/Digimon/1Digimon Vol.1'.
Script:
#!/bin/bash
#############################################################################
# Copyright 2021 Ramon Fischer #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
# You may obtain a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#############################################################################
declare -a command_array
command_array=("/usr/bin/espeak" "/usr/bin/find" "/home/ramon/git/external/github.com/rockbox/tools/rbspeexenc" "/bin/rm")
checkCommands()
{
unalias "${command_array[@]##*/}" >/dev/null 2>&1
for current_command in "${command_array[@]}"
do
if ! command -v ${current_command} >/dev/null 2>&1
then
echo -e "\e[01;31mCould not find command '${current_command}'.\e[0m" >&2
echo -e "\e[01;33mIf 'rbspeexenc' is missing, it must be compiled like so:\e[0m" >&2
echo -e "\e[01;33mmake --directory='/home/ramon/git/external/github.com/rockbox/tools/rbspeex'\e[0m" >&2
exit 1
fi
done
}
checkCommands
# define global variables
declare -a music_directory_array
music_directory_array=("audiobooks" "normal_music" "playlists" "podcasts" "record" "unusual_music")
music_filename_suffix="aac"
rockbox_directory_filename="_dirname"
rockbox_filename_suffix="talk"
rockbox_directory_voice_file="${rockbox_directory_filename}.${rockbox_filename_suffix}"
rockbox_complexity_value="8"
rockbox_volume_value="1.2"
espeak_directory_filename="${rockbox_directory_filename}"
# must be a mono 16 bit wav file!
# see also "rbspeexenc --help"
espeak_filename_suffix="wav"
espeak_directory_voice_file="${espeak_directory_filename}.${espeak_filename_suffix}"
espeak_reading_speed="125"
# uncomment for debugging. also uncomment at the end of the loop
#debug_counter="1"
for music_directory in "${music_directory_array[@]}"
do
if [[ ! -d "${music_directory}" ]]
then
echo -e "\e[01;31mCould not find directory: '${music_directory}'." >&2
exit 1
fi
done
main()
{
local directory_path
while read -r directory_path
do
echo "Entering directory: '${directory_path}'."
pushd "${directory_path}" >/dev/null
local directory_name="${directory_path##*/}"
local music_file_list=$(/usr/bin/find . -maxdepth 1 -type f -name "*.${music_filename_suffix}" -printf "%f\n")
# create ".wav" files for rockbox's "rbspeexenc" program and encode them to ".talk" files
if [[ ! -f "${rockbox_directory_voice_file}" ]]
then
echo -e " \e[01;34mGenerating\e[0m\t'espeak' voice file: '${espeak_directory_voice_file}'."
/usr/bin/espeak -s "${espeak_reading_speed}" -b 1 -z -w "${espeak_directory_voice_file}" -- "${directory_name}"
echo -e " \e[01;35mEncoding\e[0m\t'espeak' voice file: '${espeak_directory_voice_file}' to 'rockbox' voice file: '${rockbox_directory_voice_file}'."
"/home/ramon/git/external/github.com/rockbox/tools/rbspeexenc" -c "${rockbox_complexity_value}" -v "${rockbox_volume_value}" "${espeak_directory_voice_file}" "${rockbox_directory_voice_file}"
echo -e " \e[01;31mRemoving\e[0m\t'espeak' voice file: '${espeak_directory_voice_file}'."
/bin/rm --force -- "${espeak_directory_voice_file}"
fi
if [[ "${music_file_list}" != "" ]]
then
local music_file
while read -r music_file
do
local rockbox_voice_file="${music_file}.${rockbox_filename_suffix}"
if [[ ! -f "${rockbox_voice_file}" ]]
then
local espeak_voice_file="${music_file}.${espeak_filename_suffix}"
echo -e " \e[01;34mGenerating\e[0m\t'espeak' voice file: '${espeak_voice_file}'."
/usr/bin/espeak -s "${espeak_reading_speed}" -b 1 -z -w "${espeak_voice_file}" -- "${music_file/\.${music_filename_suffix}/}"
echo -e " \e[01;35mEncoding\e[0m\t'espeak' voice file: '${espeak_voice_file}' to 'rockbox' voice file: '${rockbox_voice_file}'."
"/home/ramon/git/external/github.com/rockbox/tools/rbspeexenc" -c "${rockbox_complexity_value}" -v "${rockbox_volume_value}" "${espeak_voice_file}" "${rockbox_voice_file}"
echo -e " \e[01;31mRemoving\e[0m\t'espeak' voice file: '${espeak_voice_file}'."
/bin/rm --force -- "${espeak_voice_file}"
fi
done <<< "${music_file_list}"
# wildcards are dangerous!
#/bin/rm --force -- *."${espeak_filename_suffix}"
fi
echo -e "Leaving directory: '${directory_path}'.\n"
popd >/dev/null
# uncomment for debugging. cleanup must be done manually afterwards!
#if [[ "${debug_counter}" == "10" ]]
#then
# break
#fi
#(( debug_counter++ ))
done <<< $(/usr/bin/find "${music_directory_array[@]}" -type d)
}
main
In the future I am going to maintain this script in my
Git repository, but adaptations must be done manually! This repository is also available on github.com and gitlab.com; the URL only needs to be adapted.
-Ramon