Browse Source

Версия 1.0

master
commit
960817fdd5
  1. 3
      LICENSE
  2. BIN
      Logo.png
  3. 50
      Logo.svg
  4. 5
      README.md
  5. 108
      parse_arg_lib
  6. 255
      pdf2video
  7. 163
      txt2mp3

3
LICENSE

@ -0,0 +1,3 @@
Этот продукт является ОБЩЕСТВЕННЫМ ДОСТОЯНИЕМ и может быть использован КАК ЕСТЬ, со всеми достоинствами и недостатками, полностью или частично, кем угодно и в каких угодно целях БЕЗ КАКИХ-ЛИБО ОГРАНИЧЕНИЙ.
This product is PUBLIC DOMAIN and may be used AS IS, with all advantages and faults, in whole or in part, by anyone for any purpose, WITHOUT ANY CONDITIONS.

BIN
Logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

50
Logo.svg

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="Logo.svg"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1"
inkscape:cx="282"
inkscape:cy="605"
inkscape:window-width="1920"
inkscape:window-height="1126"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
inkscape:showpageshadow="2"
inkscape:deskcolor="#d1d1d1" /><defs
id="defs2"><clipPath
id="clipPath18"
clipPathUnits="userSpaceOnUse"><path
id="path16"
d="M 0,283.465 H 283.465 V 0 H 0 Z" /></clipPath></defs><g
inkscape:label="Слой 1"
inkscape:groupmode="layer"
id="layer1"><path
d="m 122.15742,141.47014 h -3.07976 v -2.31748 c 0,-0.43189 -0.25766,-0.82207 -0.65495,-0.99169 -6.50426,-2.77654 -14.50664,-1.59978 -21.064332,3.0514 -6.557578,-4.65118 -14.560193,-5.82761 -21.064217,-3.0514 -0.397289,0.16962 -0.654958,0.5598 -0.654958,0.99169 v 2.31748 h -3.079758 c -0.595387,0 -1.0782,0.4827 -1.0782,1.0782 v 29.80228 c 0,0.59549 0.482813,1.0782 1.0782,1.0782 h 24.799042 24.798933 c 0.59549,0 1.0782,-0.48282 1.0782,-1.0782 v -29.80217 c 0,-0.5955 -0.48271,-1.07831 -1.0782,-1.07831 z m -48.519775,29.80228 v -27.64577 h 2.001558 v 25.32828 c 0,0.36226 0.18189,0.70008 0.484018,0.89971 0.302238,0.19952 0.684306,0.23391 1.017424,0.0919 5.050436,-2.15595 11.149505,-1.61675 16.562849,1.32591 z m 22.64264,-0.98337 c -3.935229,-2.5077 -8.312742,-3.80973 -12.538265,-3.80973 -2.039995,0 -4.044291,0.30344 -5.946307,0.92128 v -24.83966 c 0,-0.005 6.62e-4,-0.008 6.62e-4,-0.0125 0,-0.005 -5.38e-4,-0.008 -6.62e-4,-0.0125 v -2.654 c 5.750948,-2.15552 12.724317,-0.95007 18.484572,3.21018 z m 2.156395,-27.1969 c 5.76016,-4.16037 12.73397,-5.36571 18.48458,-3.21018 v 2.65389 c 0,0.005 -7.3e-4,0.008 -7.3e-4,0.0125 0,0.005 4.2e-4,0.008 7.3e-4,0.0125 v 24.83955 c -5.84195,-1.89764 -12.64963,-0.82963 -18.48458,2.88856 z m 22.64254,28.18027 h -20.06596 c 5.41346,-2.94266 11.51242,-3.48176 16.56297,-1.32591 0.33311,0.14237 0.71551,0.10776 1.01742,-0.0919 0.30223,-0.19963 0.48401,-0.53756 0.48401,-0.89971 v -25.32828 h 2.00156 z"
id="path484"
style="stroke-width:1.31;stroke-dasharray:none;stroke:#000000;stroke-opacity:1" /><path
d="m 152.09068,126.00235 c -0.64686,-0.44227 -1.39353,-0.67609 -2.15913,-0.67609 -0.7658,0 -1.51247,0.23382 -2.15951,0.67645 l -14.26267,9.75637 v -4.59437 c 0,-5.42063 -4.41018,-9.83062 -9.83081,-9.83062 H 69.586412 c -5.420629,0 -9.830807,4.40999 -9.830807,9.83062 v 46.50558 c 0,5.42081 4.410178,9.83099 9.830807,9.83099 h 54.092148 c 5.42063,0 9.83081,-4.41018 9.83081,-9.83099 v -6.59082 l 14.26396,9.75746 c 0.64667,0.44172 1.39298,0.67535 2.15822,0.67535 0.76523,0 1.51172,-0.23363 2.16004,-0.67663 1.11413,-0.7623 1.77919,-2.0527 1.77919,-3.45138 v -47.93018 c 0,-1.39867 -0.66506,-2.68871 -1.7801,-3.45174 z m -4.1021,47.85499 -15.75969,-10.7806 c -0.90054,-0.61598 -2.06778,-0.6827 -3.03283,-0.17371 -0.96486,0.50918 -1.56871,1.51044 -1.56871,2.60122 v 12.16622 c 0,2.17752 -1.77146,3.9488 -3.94861,3.9488 H 69.586412 c -2.177148,-1.9e-4 -3.948609,-1.77146 -3.948609,-3.94898 v -46.50558 c 0,-2.17733 1.771461,-3.94842 3.948609,-3.94842 h 54.092148 c 2.17733,0 3.94861,1.77127 3.94861,3.94842 v 10.16958 c 0,1.09097 0.60384,2.09242 1.56889,2.60141 0.9645,0.50881 2.13229,0.44226 3.03283,-0.17389 l 15.75969,-10.7806 z"
id="path513"
style="stroke-width:1.984;stroke:#000000;stroke-opacity:1;stroke-dasharray:none" /></g></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

5
README.md

@ -0,0 +1,5 @@
# Программа для преобразования электронных книг в видео
<img src=""/>
Для помощи используйте ключ '-h'

108
parse_arg_lib

@ -0,0 +1,108 @@
#!/bin/bash
# Общественное достояние, 2024, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_parse_arg_lib@narod.ru>
# Обработка входных параметров
# Формат:
# "Однобуквенная команда|Расширенная команда|Справка|Параметр|Значение по умолчанию|Команда на исполнение"
# Параметр: Пусто - нет параметров, : - есть параметр, :: - параметр не обязателен
# Пример
#common_params=(
# "i|input|Входной текстовый файл.|:|'1.txt'|"
# )
function ProcessParams {
local iparams=$1[@]
local work_func=$2
local params=("${!iparams}")
local custom_arg1="$3"
local custom_arg2="$4"
SAVE_IFS=$IFS
IFS=""
for (( i=0; i< ${#params[*]}; i++))
do
p="${params[i]}"
readarray -d "|" -t cur_params <<< "$p"
small_cmd="${cur_params[0]}"
large_cmd="${cur_params[1]}"
comment="${cur_params[2]}"
use_param="${cur_params[3]}"
default="${cur_params[4]}"
custom_cmd="${cur_params[5]}"
$work_func "$small_cmd" "$large_cmd" "$comment" "$use_param" "$default" "$custom_cmd" "$custom_arg1" "$custom_arg2"
done
IFS=$SAVE_IFS
}
param_var='local small_cmd="$1";local large_cmd="$2";local comment="$3";local use_param="$4";local default="$5";local custom_cmd="$6";local custom_arg1="$7";local custom_arg2="$8";'
function Params2InitVar {
eval "$param_var"
if [ "$use_param" != '' ]; then
eval "${large_cmd}=${default}"
fi
}
function Params2Help {
eval "$param_var"
echo "-${small_cmd}, -${large_cmd}, --${large_cmd}"
echo " ${comment/"!DEFAULT!"/"${!large_cmd}"}"
}
function Params2small_list {
eval "$param_var"
echo -n "${small_cmd}${use_param}"
}
function Params2large_list {
eval "$param_var"
echo -n ",${large_cmd}${use_param}"
}
function Params2Case {
eval "$param_var"
if [ "$custom_arg1" = "-${small_cmd}" ] || [ "$custom_arg1" = "-${large_cmd}" ] || [ "$custom_arg1" = "--${large_cmd}" ]; then
clear_custom_cmd="${custom_cmd//[$'\t\r\n ']/}"
if [ "${clear_custom_cmd}" != "" ]; then
eval "${custom_cmd}"
else
eval "${large_cmd}=\"$custom_arg2\""
fi
fi
}
# Инициализация переменных
ProcessParams all_params Params2InitVar
# $@ is all command line parameters passed to the script.
# -o is for short options like -v
# -l is for long options with double dash like --version
# the comma separates different long options
# -a is for long options with single dash like -version
# Example
# 'h' is a no-value option.
# 'v:' implies that option -v has value and is a mandatory option. ':' means has a value.
# 't::' implies that option -t has value but is optional. '::' means optional.
small_params_list=$(ProcessParams all_params Params2small_list)
small_params_list="${small_params_list:1}"
large_params_list=$(ProcessParams all_params Params2large_list)
large_params_list="${large_params_list:1}"
options=$(getopt --long "$large_params_list" -o "$small_params_list" -a -- "$@")
# set --:
# If no arguments follow this option, then the positional parameters are unset. Otherwise, the positional parameters
# are set to the arguments, even if some of them begin with a ‘-’.
eval set -- "$options"

255
pdf2video

@ -0,0 +1,255 @@
#!/bin/bash
# Общественное достояние, 2024, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_pdf2video@narod.ru>
# Озвучивание русского текста из файла pdf и сохранение в видео
version=1.0
# Формат:
# "Однобуквенная команда|Расширенная команда|Справка|Параметр|Значение по умолчанию|Команда на исполнение"
# Параметр: Пусто - нет параметров, : - есть параметр, :: - параметр не обязателен
common_params=(
"h|help|Посмотреть помощь.|||ShowHelp; exit;"
"v|version|Посмотреть версию программы.|||echo \$version; exit;"
"V|verbose|Подробный вывод.|||verbose=true"
# "|||||"
)
sound_params=(
"i|input|Входной текстовый файл.|:||"
"e|emotion|Эмоциональный настрой говорящего. Может принимать значения 'neutral', 'good', 'evil'. По умолчанию '!DEFAULT!'.|:|'neutral'|"
"s|speaker|Голос говорящего. Может принимать значения 'oksana','jane','omazh','zahar','ermil','silaerkan','erkanyavas','alyss', 'nick'. По умолчанию '!DEFAULT!'.|:|'erkanyavas'|"
"S|speed|Скорость озвучки. По умолчанию '!DEFAULT!'.|:|'1.0'|"
"O|ffmpeg_opt|Дополнительные параметры ffmpeg.|:|''|"
"f|format|Выходной формат. Может быть либо 'mp3', либо 'wav'. По умолчанию '!DEFAULT!'.|:|'mp3'|"
"q|quality|Качество выходного файла. Может быть либо 'hi', либо 'lo'. По умолчанию '!DEFAULT!'.|:|'hi'|"
"l|lang|Язык озвучки. По умолчанию '!DEFAULT!'.|:|'ru_RU'|"
# "|||:||"
)
video_params=(
"o|output|Выходной видео файл.|:|''|"
"k|split|Деление страницы пополам. Может быть либо 'yes', либо 'no'. По умолчанию '!DEFAULT!'.|:|'yes'|"
"W|video_width|Размер видео в пикселях по ширине. По умолчанию '!DEFAULT!'.|:|1920|"
"H|video_height|Размер видео в пикселях по высоте. По умолчанию '!DEFAULT!'.|:|1080|"
"p|ffmpeg_pre_options|Опции ffmpeg в самом начале. По умолчанию '!DEFAULT!'.|:|'-loop 1 -r 2'|"
"P|ffmpeg_options|Опции ffmpeg. По умолчанию '!DEFAULT!'.|:|'-c:v libx264 -tune stillimage -preset ultrafast -crf 20 -shortest -pix_fmt yuv420p'|"
"r|page_range|Указывает страницы из выходного файла для обработки. Пример '{1..32}', '{2..10..2}', '\$(seq 5 3 30)'|:|''|"
"m|minimum_text_on_page|Минимальное количество символов на странице при котором происходит разделение страницы на две. По умолчанию '!DEFAULT!'.|:|1000|"
# "|||:||"
)
all_params=("${common_params[@]}" "${sound_params[@]}" "${video_params[@]}")
# Загружаем библиотеку
function GetExec {
local exec_file_name="$1"
exec="$exec_file_name"
[ ! -f "$exec" ] && exec="./$exec_file_name"
[ ! -f "$exec" ] && exec="~/$exec_file_name"
echo "$exec"
}
eval "source $(GetExec "parse_arg_lib")"
function ShowHelp() {
cat << EOF
Использование: pdf2video -i <text_file> [-o <mp4_file>] [-hV]
Озвучивание русского текста из файла pdf и сохранение в видео
Общие параметры
$(ProcessParams common_params Params2Help)
Параметры звука
$(ProcessParams sound_params Params2Help)
Параметры видео
$(ProcessParams video_params Params2Help)
EOF
}
# -------------------------------------------
while true
do
cur_arg="$1"
[ "$cur_arg" = '--' ] && { shift; break; }
ProcessParams all_params Params2Case "$cur_arg" "$2"
shift
done
input_file="$input"
out_file="$output"
unuse_param="$*"
if [ "${input_file}" = "" ] || [ "${unuse_param}" != "" ]; then
[ "${unuse_param}" != "" ] && echo "Параметры не расшифрованы \"$unuse_param\""
ShowHelp
exit
fi
[ "$out_file" = "" ] && { out_file="${input_file}.mp4"; [ $verbose ] && echo "Выходное имя файла \"$out_file\""; }
#----------------------------------------------------
page_count=$(pdfinfo "${input_file}" | awk '/^Pages:/ {print $2}')
video_file_names_array=()
function Text2mp3 {
local text_file=$1
local mp3_file=$2
verb=""
[ $verbose ] && verb="-V"
[ $verbose ] && echo "Найден исполняемый файл для преобразования в звук текста $(GetExec txt2mp3)"
eval "$(GetExec "txt2mp3") -i '${text_file}' -o '${mp3_file}' -e '${emotion}' -s '${speaker}' -S '${speed}' -f '${format}' -q '${quality}' -l '${lang}' '${verb}'"
}
function MakeVideo {
local page_image_file=$1
local page_mp3_file=$2
local page_mp4_file=$3
local resized_page_image_file="${page_image_file}_resized.png"
ffmpeg -y -i "${page_image_file}" -vf "scale=${video_width}:${video_height}:force_original_aspect_ratio=decrease,pad=${video_width}:${video_height}:(ow-iw)/2:(oh-ih)/2" "${resized_page_image_file}"
local time_play=$(mp3info -p "%S\n" "${page_mp3_file}")
local time_opt="-c:a copy"
if [ ${minimum_time_on_page} -ge ${time_play} ]; then
local add_time=5 # $(( 5 - ${time_play} ))
time_opt="-c:a mp3 -af adelay=${add_time}s:all=true" #
[ $verbose ] && echo "time_opt ${time_opt}"
fi
ffmpeg ${ffmpeg_pre_options} -i "${resized_page_image_file}" -i "${page_mp3_file}" ${ffmpeg_options} ${time_opt} "${page_mp4_file}"
SAVE_IFS=$IFS
IFS=""
video_file_names_array+=(${page_mp4_file})
IFS=$SAVE_IFS
rm "${resized_page_image_file}"
}
[ $verbose ] && echo "Всего страниц $page_count"
for ((page=1;page<=${page_count};page++)); do
if [ $page_range ]; then
skip="true"
for p in $(eval echo "$page_range");
do
if [ $p = $page ]; then
skip="false"
break
fi
done
if [ $skip = "true" ]; then
[ $verbose ] && echo "Пропускаем страницу №$page"
continue
fi
fi
[ $verbose ] && echo "------------------------------------------------"
[ $verbose ] && echo "Обрабатываем страницу №$page"
page_text_file="${input_file}_${page}.txt"
page_image_file="${input_file}_${page}"
pdftotext -f $page -l $page "${input_file}" "$page_text_file"
pdftoppm -r 300 -f $page -l $page -png -singlefile "${input_file}" "$page_image_file"
page_image_file="${page_image_file}.png"
source_text="$(cat "${page_text_file}")"
if [ "$split" = "yes" ] && [ ${#source_text} -ge $minimum_text_on_page ]; then
space_char=" "
split_size=$(( ${#source_text} / 2 + 2)) # Половина с небольшим запасом
file_index=0
for ((i=1;i<=${#source_text};i++)); do
cur_char=${source_text:$i-1:1}
cur_text="${cur_text}${cur_char}"
if [ "$cur_char" = "$space_char" ] && [ ${#cur_text} -ge $split_size ] || [ $i = ${#source_text} ]; then
let file_index+=1
echo "$cur_text" > "${page_text_file}_half${file_index}"
cur_text=""
fi
done
file_txt_half1="${page_text_file}_half1"
file_txt_half2="${page_text_file}_half2"
page_mp3_file_half1="${file_txt_half1}.mp3"
page_mp3_file_half2="${file_txt_half2}.mp3"
Text2mp3 "$file_txt_half1" "$page_mp3_file_half1"
Text2mp3 "$file_txt_half2" "$page_mp3_file_half2"
width=$(identify -format "%w" "$page_image_file")> /dev/null
height=$(identify -format "%h" "$page_image_file")> /dev/null
height_half=$(( $height / 2 + $height / 20 ))
page_image_file_half1="${page_image_file}_half1.png"
page_image_file_half2="${page_image_file}_half2.png"
# format (widthxheight+left+top / wxh+l+t)
convert "$page_image_file" -crop ${width}x${height_half}+0+0 "$page_image_file_half1"
convert "$page_image_file" -crop ${width}x${height_half}+0+$(( $height - $height_half )) "$page_image_file_half2"
page_mp4_file_half1="${input_file}_${page}_half1.mp4"
page_mp4_file_half2="${input_file}_${page}_half2.mp4"
MakeVideo "$page_image_file_half1" "$page_mp3_file_half1" "$page_mp4_file_half1"
MakeVideo "$page_image_file_half2" "$page_mp3_file_half2" "$page_mp4_file_half2"
rm "$page_image_file_half1"
rm "$page_image_file_half2"
rm "$file_txt_half1"
rm "$file_txt_half2"
rm "$page_mp3_file_half1"
rm "$page_mp3_file_half2"
else
page_mp3_file="${page_text_file}.mp3"
Text2mp3 "$page_text_file" "$page_mp3_file"
page_mp4_file="${input_file}_${page}.mp4"
MakeVideo "$page_image_file" "$page_mp3_file" "$page_mp4_file"
rm "$page_mp3_file"
fi
rm "$page_image_file"
rm "$page_text_file"
done
SAVE_IFS=$IFS
IFS=""
[ $verbose ] && echo "Объединяем файлы ${video_file_names_array[*]} в $out_file"
ffmpeg -f concat -safe 0 -i <(for ((i = 0; i < ${#video_file_names_array[@]}; i++)) do echo "file '$PWD/${video_file_names_array[$i]}'"; done) -acodec copy -vcodec copy "$out_file"
for ((i = 0; i < ${#video_file_names_array[@]}; i++)) do
f="${video_file_names_array[$i]}"
[ $verbose ] && echo "Удаляем файл '$f'"
rm "$f"
done
IFS=$SAVE_IFS
[ $verbose ] && echo "Конечный файл создан '$out_file'!"

163
txt2mp3

@ -0,0 +1,163 @@
#!/bin/bash
# Общественное достояние, 2024, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_txt2mp3@narod.ru>
# Озвучивание текста из файла
version=1.0
# Формат:
# "Однобуквенная команда|Расширенная команда|Справка|Параметр|Значение по умолчанию|Команда на исполнение"
# Параметр: Пусто - нет параметров, : - есть параметр, :: - параметр не обязателен
common_params=(
"h|help|Посмотреть помощь.|||ShowHelp; exit;"
"v|version|Посмотреть версию программы.|||echo \$version; exit;"
"V|verbose|Подробный вывод.|||verbose=true"
# "|||||"
)
sound_params=(
"i|input|Входной текстовый файл.|:||"
"o|output|Выходной видео файл.|:|''|"
"e|emotion|Эмоциональный настрой говорящего. Может принимать значения 'neutral', 'good', 'evil'. По умолчанию '!DEFAULT!'.|:|'neutral'|"
"s|speaker|Голос говорящего. Может принимать значения 'oksana','jane','omazh','zahar','ermil','silaerkan','erkanyavas','alyss', 'nick'. По умолчанию '!DEFAULT!'.|:|'erkanyavas'|"
"S|speed|Скорость озвучки. По умолчанию '!DEFAULT!'.|:|'1.0'|"
"O|ffmpeg_opt|Дополнительные параметры ffmpeg.|:|''|"
"f|format|Выходной формат. Может быть либо 'mp3', либо 'wav'. По умолчанию '!DEFAULT!'.|:|'mp3'|"
"q|quality|Качество выходного файла. Может быть либо 'hi', либо 'lo'. По умолчанию '!DEFAULT!'.|:|'hi'|"
"l|lang|Язык озвучки. По умолчанию '!DEFAULT!'.|:|'ru_RU'|"
# "|||:||"
)
all_params=("${common_params[@]}" "${sound_params[@]}")
# Загружаем библиотеку
function GetExec {
local exec_file_name="$1"
exec="$exec_file_name"
[ ! -f "$exec" ] && exec="./$exec_file_name"
[ ! -f "$exec" ] && exec="~/$exec_file_name"
echo "$exec"
}
eval "source $(GetExec "parse_arg_lib")"
function ShowHelp() {
cat << EOF
Использование: pdf2mp3 -i <text_file> [-o <mp4_file>] [-hV]
Озвучивание текста из файла
Общие параметры
$(ProcessParams common_params Params2Help)
Параметры звука
$(ProcessParams sound_params Params2Help)
EOF
}
# -------------------------------------------
while true
do
cur_arg="$1"
[ "$cur_arg" = '--' ] && { shift; break; }
ProcessParams all_params Params2Case "$cur_arg" "$2"
shift
done
input_file="$input"
out_file="$output"
unuse_param="$*"
if [ "${input_file}" = "" ] || [ "$unuse_param" != "" ]; then
[ "$unuse_param" != "" ] && echo "Параметры не расшифрованы \"$unuse_param\""
ShowHelp
exit
fi
[ "$out_file" = "" ] && { out_file="$input_file.mp3"; [ $verbose ] && echo "Выходное имя файла \"$out_file\""; }
source_text=$(cat "${input_file}")
# Удаляем все пробелы в начале и в конце строк и заменяем два и более пробелов на один, удаляем все непечатаемые символы
source_text="$(echo "${source_text//[$'\t\r\n']/' '}" | sed 's/^ *//;s/[ ^]*$//;s/ */ /;s/[^[:blank:][:print:]]//g')"
#[ $verbose ] && echo "Исходный текст $source_text" >> "out.txt"
ping -c 3 ya.ru &>/dev/null || { echo "Интернет недоступен."; exit; }
split_size=1450
[ $verbose ] && echo "Длина текста ${#source_text}: Разбиваем на части по $split_size"
txt_array=()
space_char=" "
for ((i=1;i<=${#source_text};i++)); do
cur_char=${source_text:$i-1:1}
cur_text="${cur_text}${cur_char}"
if [ "$cur_char" = "$space_char" ] && [ ${#cur_text} -ge $split_size ] || [ $i = ${#source_text} ]; then
# Максимальная длина SEND_IRI - 1590 символов, длина SEND_IRI без текста = 75 символов
# Максимальная длина текста = 1590 - 75 = 1515 символов
text_count=${#cur_text}
[ $text_count -ge 1515 ] && { echo "Превышено максимальное колличество символов - 1515"; exit; }
SAVE_IFS=$IFS
IFS=""
txt_array+=($cur_text)
IFS=$SAVE_IFS
cur_text=""
fi
done
audio_file_names_array=()
# Если текст пустой, то всё равно создаём выходной файл
[ ${#txt_array[@]} -le 0 ] && { txt_array+="."; }
SAVE_IFS=$IFS
IFS=""
file_index=0
for ((i = 0; i < ${#txt_array[@]}; i++)) do
cur_text="${txt_array[$i]}"
let file_index+=1
[ $verbose ] && echo "Часть номер $file_index"
[ $verbose ] && echo "------------------------------"
[ $verbose ] && echo $cur_text
[ $verbose ] && echo "------------------------------"
#[ $verbose ] && echo $cur_text >> "out.txt"
audio_file_name="${input_file}_${file_index}.mp3"
[ $verbose ] && echo -en "\nЗагрузка аудио в файл '$audio_file_name'...\n"
#touch "$audio_file_name"
wget -q -O "$audio_file_name" "http://tts.voicetech.yandex.net/tts?format=mp3&quality=hi&lang=ru_RU&speed=${speed}&speaker=${speaker}&emotion=${emotion}&text=${cur_text}" || { echo "Ошибка при загрузке аудио."; exit; }
[ $verbose ] && echo "Файл '$audio_file_name' загружен."
SAVE_IFS=$IFS
IFS=""
audio_file_names_array+=($audio_file_name)
IFS=$SAVE_IFS
done
[ $verbose ] && echo "Объединяем файлы ${audio_file_names_array[*]} в $out_file"
ffmpeg -f concat -safe 0 -i <(for ((i = 0; i < ${#audio_file_names_array[@]}; i++)) do echo "file '$PWD/${audio_file_names_array[$i]}'"; done) -acodec copy -vcodec copy ${ffmpeg_opt} "$out_file"
for ((i = 0; i < ${#audio_file_names_array[@]}; i++)) do
f="${audio_file_names_array[$i]}"
[ $verbose ] && echo "Удаляем файл '$f'"
rm "$f"
done
IFS=$SAVE_IFS
[ $verbose ] && echo "Конечный файл создан '$out_file'!"
Loading…
Cancel
Save