From f9e5d51bb25e878ea4d2eb4ba08be72e329fd333 Mon Sep 17 00:00:00 2001 From: Alexei Bezborodov Date: Wed, 3 Jan 2024 15:47:19 +0300 Subject: [PATCH 01/15] text2mp3 --- Script/text2mp3 | 8 ++++++ Script/txt3mp3_by_yatts | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100755 Script/text2mp3 create mode 100755 Script/txt3mp3_by_yatts diff --git a/Script/text2mp3 b/Script/text2mp3 new file mode 100755 index 0000000..f859e94 --- /dev/null +++ b/Script/text2mp3 @@ -0,0 +1,8 @@ +#!/bin/sh +in_file=$1 +out_wav_file_name="$1.wav" +out_mp3_file_name="$1.mp3" +cat "$1" | sed 's/[^a-zA-ZА-Яа-я0-9., ]//g' | text2wave -o "$out_wav_file_name" +lame "$out_wav_file_name" "$out_mp3_file_name" +rm "$out_wav_file_name" + diff --git a/Script/txt3mp3_by_yatts b/Script/txt3mp3_by_yatts new file mode 100755 index 0000000..fcf3289 --- /dev/null +++ b/Script/txt3mp3_by_yatts @@ -0,0 +1,72 @@ +#!/bin/bash +# Озвучивание русского текста из файла +input_file_name="$1" + +source_text=$(cat "${input_file_name}") + +#{ # GUI + +# Удаляем все пробелы в начале и в конце строк и заменяем два и более пробелов на один +source_text="$(echo -n "$source_text" | sed 's/^ *//;s/[ ^]*$//;s/ */ /g')" + +#echo "Исходный текст $source_text" + +ping -c 3 ya.ru &>/dev/null || { echo "Интернет недоступен."; exit; } + +audio_file_names_array=() + +split_size=1450 +echo "Длина текста ${#source_text}: Разбиваем на части по $split_size" + +space_char=" " +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 ]; then + + let file_index+=1 + echo "Часть номер $file_index" + echo "------------------------------" + echo $cur_text + echo "------------------------------" + + # Максимальная длина SEND_IRI - 1590 символов, длина SEND_IRI без текста = 75 символов + # Максимальная длина текста = 1590 - 75 = 1515 символов + text_count=$(echo "$cur_text" | wc -m) + [ $text_count -ge 1515 ] && { echo "Превышено максимальное колличество символов - 1515"; exit; } + + audio_file_name="${input_file_name}_${file_index}.mp3" + 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&text=${cur_text}" || { echo "Ошибка при загрузке аудио."; exit; } + echo "Файл '$audio_file_name' загружен." + IFS="" + audio_file_names_array+=($audio_file_name) + + cur_text="" + fi +done + +cmd="" +for ((i = 0; i < ${#audio_file_names_array[@]}; i++)) do + cmd="$cmd|${audio_file_names_array[$i]}" +done +cmd=${cmd:1} + +out_file="${input_file_name}_yatts.mp3" + +echo "Объединяем файлы $cmd в $out_file" +ffmpeg -i "concat:$cmd" -acodec copy "$out_file" + +IFS="" +for ((i = 0; i < ${#audio_file_names_array[@]}; i++)) do + f="${audio_file_names_array[$i]}" + echo "Удаляем файл '$f'" + rm "$f" +done + +echo "Конечный файл создан '$out_file'!" + +#} | zenity --source_text-info --width=550 --height=450 --title="Озвучивание текста при помощи YaTTS" # GUI + From 119011731471244c54f1bf632e19e149a978a86b Mon Sep 17 00:00:00 2001 From: Alexei Bezborodov Date: Wed, 3 Jan 2024 16:25:32 +0300 Subject: [PATCH 02/15] txt2mp3 parametrs --- Script/txt3mp3_by_yatts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Script/txt3mp3_by_yatts b/Script/txt3mp3_by_yatts index fcf3289..a9634e3 100755 --- a/Script/txt3mp3_by_yatts +++ b/Script/txt3mp3_by_yatts @@ -1,5 +1,11 @@ #!/bin/bash # Озвучивание русского текста из файла +# Параметры +emotion='neutral' #'Default is neutral. Also supported are good (friendly) and evil (angry)' +speaker='ermil' # (Optional): Speaker voice. Default is zahar. Supported female voices are jane, oksana, alyss, omazh and male voices are zahar and ermil. +#["oksana","jane","omazh","zahar","ermil","silaerkan","erkanyavas","alyss", "nick","alena","filipp"] +speed='1.0' + input_file_name="$1" source_text=$(cat "${input_file_name}") @@ -23,7 +29,7 @@ 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 ]; then + if [ "$cur_char" = "$space_char" ] && [ ${#cur_text} -ge $split_size ] || [ $i = ${#source_text} ]; then let file_index+=1 echo "Часть номер $file_index" @@ -35,11 +41,11 @@ for ((i=1;i<=${#source_text};i++)); do # Максимальная длина текста = 1590 - 75 = 1515 символов text_count=$(echo "$cur_text" | wc -m) [ $text_count -ge 1515 ] && { echo "Превышено максимальное колличество символов - 1515"; exit; } - + audio_file_name="${input_file_name}_${file_index}.mp3" 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&text=${cur_text}" || { echo "Ошибка при загрузке аудио."; exit; } + 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; } echo "Файл '$audio_file_name' загружен." IFS="" audio_file_names_array+=($audio_file_name) From 0ef2e6f2393fcfeceabfd69ee5f12bdb3afefa50 Mon Sep 17 00:00:00 2001 From: Alexei Bezborodov Date: Wed, 3 Jan 2024 16:55:05 +0300 Subject: [PATCH 03/15] rename --- Script/{txt3mp3_by_yatts => txt2mp3_by_yatts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Script/{txt3mp3_by_yatts => txt2mp3_by_yatts} (100%) diff --git a/Script/txt3mp3_by_yatts b/Script/txt2mp3_by_yatts similarity index 100% rename from Script/txt3mp3_by_yatts rename to Script/txt2mp3_by_yatts From 0c986558b03b121d95a3b6eef8b0a86a294dbdae Mon Sep 17 00:00:00 2001 From: Alexei Bezborodov Date: Wed, 3 Jan 2024 22:00:52 +0300 Subject: [PATCH 04/15] =?UTF-8?q?=D0=9F=D0=B4=D1=84=20=D0=B2=20=D0=B2?= =?UTF-8?q?=D0=B8=D0=B4=D0=B5=D0=BE=20=D1=84=D0=B0=D0=B9=D0=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Script/pdf2video | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100755 Script/pdf2video diff --git a/Script/pdf2video b/Script/pdf2video new file mode 100755 index 0000000..0b83969 --- /dev/null +++ b/Script/pdf2video @@ -0,0 +1,113 @@ +#!/bin/bash +# Озвучивание русского текста из файла pdf и сохранение в видео +# Параметры +emotion='neutral' #'Default is neutral. Also supported are good (friendly) and evil (angry)' +speaker='ermil' # (Optional): Speaker voice. Default is zahar. Supported female voices are jane, oksana, alyss, omazh and male voices are zahar and ermil. +#["oksana","jane","omazh","zahar","ermil","silaerkan","erkanyavas","alyss", "nick","alena","filipp"] +speed='1.0' + +use_half="no" # yes or no + +input_pdf_file_name="$1" + +page_count=$(pdfinfo "$input_pdf_file_name" | awk '/^Pages:/ {print $2}') + +video_file_names_array=() + +echo "Всего страниц $page_count" + +for ((page=1;page<=${page_count};page++)); do + + echo "------------------------------------------------" + echo "Обрабатываем страницу №$page" + + page_text_file="${input_pdf_file_name}_${page}.txt" + page_image_file="${input_pdf_file_name}_${page}" + pdftotext -f $page -l $page "$input_pdf_file_name" "$page_text_file" + pdftoppm -f $page -l $page -png -singlefile "$input_pdf_file_name" "$page_image_file" + + page_image_file="${page_image_file}.png" + + ~/txt2mp3_by_yatts "$page_text_file" + + page_mp3_file="${page_text_file}_yatts.mp3" + + if [ "$use_half"="yes"]; then + + width=$(identify -format "%w" "$page_image_file")> /dev/null + height=$(identify -format "%h" "$page_image_file")> /dev/null + + height_half=$(($height/2)) + + 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_half "$page_image_file_half2" + + audio_length=$(mp3info -p "%S" sample.mp3) + audio_length_half=$(($audio_length/2)) + + page_mp3_file_half1="${page_mp3_file}_half1.mp3" + page_mp3_file_half2="${page_mp3_file}_half2.mp3" + + ffmpeg -i "$page_mp3_file" -acodec copy -ss "0" -to "$audio_length_half" "$page_mp3_file_half1" + ffmpeg -i "$page_mp3_file" -acodec copy -ss "$audio_length_half" -to "$audio_length" "$page_mp3_file_half2" + + page_mp4_file_half1="${input_pdf_file_name}_${page}_half1.mp4" + + ffmpeg -loop 1 -i "$page_image_file_half1" -i "$page_mp3_file_half1" -c:v libx264 -tune stillimage -c:a copy -pix_fmt yuv420p -s 1920*1080 -shortest "$page_mp4_file_half1" + + IFS="" + video_file_names_array+=($page_mp4_file_half1) + + page_mp4_file_half2="${input_pdf_file_name}_${page}_half2.mp4" + + ffmpeg -loop 1 -i "$page_image_file_half2" -i "$page_mp3_file_half2" -c:v libx264 -tune stillimage -c:a copy -pix_fmt yuv420p -s 1920*1080 -shortest "$page_mp4_file_half2" + + IFS="" + video_file_names_array+=($page_mp4_file_half2) + + rm "$page_mp3_file_half1" + rm "$page_mp3_file_half2" + rm "$page_image_file_half1" + rm "$page_image_file_half2" + else + + page_mp4_file="${input_pdf_file_name}_${page}.mp4" + + ffmpeg -loop 1 -i "$page_image_file" -i "$page_mp3_file" -c:v libx264 -tune stillimage -c:a copy -pix_fmt yuv420p -s 1920*1080 -shortest "$page_mp4_file" + + IFS="" + video_file_names_array+=($page_mp4_file) + + fi + + rm "$page_mp3_file" + rm "$page_image_file" + rm "$page_text_file" + + +done + +cmd="" +for ((i = 0; i < ${#video_file_names_array[@]}; i++)) do + cmd="$cmd|${video_file_names_array[$i]}" +done +cmd=${cmd:1} + +out_file="${input_pdf_file_name}.mp4" + +echo "Объединяем файлы $cmd в $out_file" +ffmpeg -i "concat:$cmd" -acodec copy -vcodec copy "$out_file" + +IFS="" +for ((i = 0; i < ${#video_file_names_array[@]}; i++)) do + f="${video_file_names_array[$i]}" + echo "Удаляем файл '$f'" + rm "$f" +done + +echo "Конечный файл создан '$out_file'!" + From b5d41eabdabf678ab0822061eb888bd54a802498 Mon Sep 17 00:00:00 2001 From: Alexei Bezborodov Date: Wed, 3 Jan 2024 22:09:13 +0300 Subject: [PATCH 05/15] =?UTF-8?q?ffmgeg=20=D0=BE=D0=BF=D1=82=D0=B8=D0=BC?= =?UTF-8?q?=D0=B8=D0=B7=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Script/pdf2video | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Script/pdf2video b/Script/pdf2video index 0b83969..60a453d 100755 --- a/Script/pdf2video +++ b/Script/pdf2video @@ -5,8 +5,11 @@ emotion='neutral' #'Default is neutral. Also supported are good (friendly) and e speaker='ermil' # (Optional): Speaker voice. Default is zahar. Supported female voices are jane, oksana, alyss, omazh and male voices are zahar and ermil. #["oksana","jane","omazh","zahar","ermil","silaerkan","erkanyavas","alyss", "nick","alena","filipp"] speed='1.0' - use_half="no" # yes or no +ffmpeg_pre_options="-loop 1" +ffmpeg_options="-c:v libx264 -tune stillimage -c:a copy -pix_fmt yuv420p -s 1920*1080 -shortest" + +#---------------------------------------------------- input_pdf_file_name="$1" @@ -57,14 +60,14 @@ for ((page=1;page<=${page_count};page++)); do page_mp4_file_half1="${input_pdf_file_name}_${page}_half1.mp4" - ffmpeg -loop 1 -i "$page_image_file_half1" -i "$page_mp3_file_half1" -c:v libx264 -tune stillimage -c:a copy -pix_fmt yuv420p -s 1920*1080 -shortest "$page_mp4_file_half1" + ffmpeg $ffmpeg_pre_options -i "$page_image_file_half1" -i "$page_mp3_file_half1" $ffmpeg_options "$page_mp4_file_half1" IFS="" video_file_names_array+=($page_mp4_file_half1) page_mp4_file_half2="${input_pdf_file_name}_${page}_half2.mp4" - ffmpeg -loop 1 -i "$page_image_file_half2" -i "$page_mp3_file_half2" -c:v libx264 -tune stillimage -c:a copy -pix_fmt yuv420p -s 1920*1080 -shortest "$page_mp4_file_half2" + ffmpeg $ffmpeg_pre_options -i "$page_image_file_half2" -i "$page_mp3_file_half2" $ffmpeg_options "$page_mp4_file_half2" IFS="" video_file_names_array+=($page_mp4_file_half2) @@ -77,7 +80,7 @@ for ((page=1;page<=${page_count};page++)); do page_mp4_file="${input_pdf_file_name}_${page}.mp4" - ffmpeg -loop 1 -i "$page_image_file" -i "$page_mp3_file" -c:v libx264 -tune stillimage -c:a copy -pix_fmt yuv420p -s 1920*1080 -shortest "$page_mp4_file" + ffmpeg $ffmpeg_pre_options -i "$page_image_file" -i "$page_mp3_file" $ffmpeg_options "$page_mp4_file" IFS="" video_file_names_array+=($page_mp4_file) From b2237d10d6a3dd2e012b7ce3b8ec3c4a364a6ca3 Mon Sep 17 00:00:00 2001 From: Alexei Bezborodov Date: Wed, 3 Jan 2024 23:41:18 +0300 Subject: [PATCH 06/15] =?UTF-8?q?Half=20=D1=80=D0=B5=D0=B6=D0=B8=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Script/pdf2video | 62 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/Script/pdf2video b/Script/pdf2video index 60a453d..ecff9c5 100755 --- a/Script/pdf2video +++ b/Script/pdf2video @@ -5,9 +5,9 @@ emotion='neutral' #'Default is neutral. Also supported are good (friendly) and e speaker='ermil' # (Optional): Speaker voice. Default is zahar. Supported female voices are jane, oksana, alyss, omazh and male voices are zahar and ermil. #["oksana","jane","omazh","zahar","ermil","silaerkan","erkanyavas","alyss", "nick","alena","filipp"] speed='1.0' -use_half="no" # yes or no -ffmpeg_pre_options="-loop 1" -ffmpeg_options="-c:v libx264 -tune stillimage -c:a copy -pix_fmt yuv420p -s 1920*1080 -shortest" +use_half="yes" # yes or no +ffmpeg_pre_options="-loop 1 -r 2" # "-loop 1" +ffmpeg_options="-c:v libx264 -tune stillimage -preset ultrafast -crf 20 -c:a copy -shortest -pix_fmt yuv420p -s 1920*1080" #---------------------------------------------------- @@ -31,11 +31,33 @@ for ((page=1;page<=${page_count};page++)); do page_image_file="${page_image_file}.png" - ~/txt2mp3_by_yatts "$page_text_file" + if [ "$use_half"="yes" ]; then - page_mp3_file="${page_text_file}_yatts.mp3" + source_text=$(cat "${page_text_file}") + + space_char=" " + split_size=$(( ${#source_text} / 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_mp3_half1="${page_text_file}_half1" + file_mp3_half2="${page_text_file}_half2" + + ~/txt2mp3_by_yatts "${file_mp3_half1}" + ~/txt2mp3_by_yatts "${file_mp3_half2}" - if [ "$use_half"="yes"]; then + page_mp3_file_half1="${file_mp3_half1}_yatts.mp3" + page_mp3_file_half2="${file_mp3_half2}_yatts.mp3" width=$(identify -format "%w" "$page_image_file")> /dev/null height=$(identify -format "%h" "$page_image_file")> /dev/null @@ -49,35 +71,38 @@ for ((page=1;page<=${page_count};page++)); do 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_half "$page_image_file_half2" - audio_length=$(mp3info -p "%S" sample.mp3) - audio_length_half=$(($audio_length/2)) - - page_mp3_file_half1="${page_mp3_file}_half1.mp3" - page_mp3_file_half2="${page_mp3_file}_half2.mp3" - - ffmpeg -i "$page_mp3_file" -acodec copy -ss "0" -to "$audio_length_half" "$page_mp3_file_half1" - ffmpeg -i "$page_mp3_file" -acodec copy -ss "$audio_length_half" -to "$audio_length" "$page_mp3_file_half2" - page_mp4_file_half1="${input_pdf_file_name}_${page}_half1.mp4" ffmpeg $ffmpeg_pre_options -i "$page_image_file_half1" -i "$page_mp3_file_half1" $ffmpeg_options "$page_mp4_file_half1" + SAVE_IFS=$IFS IFS="" video_file_names_array+=($page_mp4_file_half1) + IFS=$SAVE_IFS page_mp4_file_half2="${input_pdf_file_name}_${page}_half2.mp4" ffmpeg $ffmpeg_pre_options -i "$page_image_file_half2" -i "$page_mp3_file_half2" $ffmpeg_options "$page_mp4_file_half2" + SAVE_IFS=$IFS IFS="" video_file_names_array+=($page_mp4_file_half2) + IFS=$SAVE_IFS - rm "$page_mp3_file_half1" - rm "$page_mp3_file_half2" rm "$page_image_file_half1" rm "$page_image_file_half2" + + rm "$file_mp3_half1" + rm "$file_mp3_half2" + rm "$page_mp3_file_half1" + rm "$page_mp3_file_half2" + else + ~/txt2mp3_by_yatts "$page_text_file" + + page_mp3_file="${page_text_file}_yatts.mp3" + page_mp4_file="${input_pdf_file_name}_${page}.mp4" ffmpeg $ffmpeg_pre_options -i "$page_image_file" -i "$page_mp3_file" $ffmpeg_options "$page_mp4_file" @@ -85,9 +110,10 @@ for ((page=1;page<=${page_count};page++)); do IFS="" video_file_names_array+=($page_mp4_file) + rm "$page_mp3_file" + fi - rm "$page_mp3_file" rm "$page_image_file" rm "$page_text_file" From ce3f7791d7dd4ae93bcc46a39c44a24c02ffb7ca Mon Sep 17 00:00:00 2001 From: Alexei Bezborodov Date: Thu, 4 Jan 2024 01:01:27 +0300 Subject: [PATCH 07/15] =?UTF-8?q?=D0=9E=D0=BF=D1=82=D0=B8=D0=BC=D0=B8?= =?UTF-8?q?=D0=B7=D0=B0=D1=86=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Script/pdf2video | 4 +++- Script/txt2mp3_by_yatts | 22 ++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Script/pdf2video b/Script/pdf2video index ecff9c5..77c28bd 100755 --- a/Script/pdf2video +++ b/Script/pdf2video @@ -36,7 +36,7 @@ for ((page=1;page<=${page_count};page++)); do source_text=$(cat "${page_text_file}") space_char=" " - split_size=$(( ${#source_text} / 2 )) + split_size=$(( ${#source_text} / 2 + 2)) # Половина с небольшим запасом file_index=0 for ((i=1;i<=${#source_text};i++)); do cur_char=${source_text:$i-1:1} @@ -107,8 +107,10 @@ for ((page=1;page<=${page_count};page++)); do ffmpeg $ffmpeg_pre_options -i "$page_image_file" -i "$page_mp3_file" $ffmpeg_options "$page_mp4_file" + SAVE_IFS=$IFS IFS="" video_file_names_array+=($page_mp4_file) + IFS=$SAVE_IFS rm "$page_mp3_file" diff --git a/Script/txt2mp3_by_yatts b/Script/txt2mp3_by_yatts index a9634e3..f288d59 100755 --- a/Script/txt2mp3_by_yatts +++ b/Script/txt2mp3_by_yatts @@ -6,12 +6,12 @@ speaker='ermil' # (Optional): Speaker voice. Default is zahar. Supported female #["oksana","jane","omazh","zahar","ermil","silaerkan","erkanyavas","alyss", "nick","alena","filipp"] speed='1.0' +# https://stackoverflow.com/questions/16483119/an-example-of-how-to-use-getopts-in-bash + input_file_name="$1" source_text=$(cat "${input_file_name}") -#{ # GUI - # Удаляем все пробелы в начале и в конце строк и заменяем два и более пробелов на один source_text="$(echo -n "$source_text" | sed 's/^ *//;s/[ ^]*$//;s/ */ /g')" @@ -47,32 +47,30 @@ for ((i=1;i<=${#source_text};i++)); do #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; } echo "Файл '$audio_file_name' загружен." + + SAVE_IFS=$IFS IFS="" audio_file_names_array+=($audio_file_name) + IFS=$SAVE_IFS cur_text="" fi done -cmd="" -for ((i = 0; i < ${#audio_file_names_array[@]}; i++)) do - cmd="$cmd|${audio_file_names_array[$i]}" -done -cmd=${cmd:1} - out_file="${input_file_name}_yatts.mp3" -echo "Объединяем файлы $cmd в $out_file" -ffmpeg -i "concat:$cmd" -acodec copy "$out_file" - +SAVE_IFS=$IFS IFS="" +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 "$out_file" + for ((i = 0; i < ${#audio_file_names_array[@]}; i++)) do f="${audio_file_names_array[$i]}" echo "Удаляем файл '$f'" rm "$f" done +IFS=$SAVE_IFS echo "Конечный файл создан '$out_file'!" -#} | zenity --source_text-info --width=550 --height=450 --title="Озвучивание текста при помощи YaTTS" # GUI From 040032afcdfddca06783735d3246c0d4eb7d4942 Mon Sep 17 00:00:00 2001 From: Alexei Bezborodov Date: Thu, 4 Jan 2024 23:37:13 +0300 Subject: [PATCH 08/15] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=BE=20=D0=BC=D0=BD=D0=BE=D0=B6=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=B2=D0=BE=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Script/pdf2video | 94 +++++++++++++++++++++++++++---------------------- Script/txt2mp3_by_yatts | 70 +++++++++++++++++++++++------------- 2 files changed, 97 insertions(+), 67 deletions(-) diff --git a/Script/pdf2video b/Script/pdf2video index 77c28bd..5e30b67 100755 --- a/Script/pdf2video +++ b/Script/pdf2video @@ -6,17 +6,50 @@ speaker='ermil' # (Optional): Speaker voice. Default is zahar. Supported female #["oksana","jane","omazh","zahar","ermil","silaerkan","erkanyavas","alyss", "nick","alena","filipp"] speed='1.0' use_half="yes" # yes or no -ffmpeg_pre_options="-loop 1 -r 2" # "-loop 1" -ffmpeg_options="-c:v libx264 -tune stillimage -preset ultrafast -crf 20 -c:a copy -shortest -pix_fmt yuv420p -s 1920*1080" +video_width=1920 +video_height=1080 +ffmpeg_pre_options="-loop 1 -r 2" +ffmpeg_options="-c:v libx264 -tune stillimage -preset ultrafast -crf 20 -shortest -pix_fmt yuv420p -s ${video_width}*${video_height}" +minimum_text_on_page=1000 +minimum_time_on_page=5 #---------------------------------------------------- input_pdf_file_name="$1" +out_file="$input_pdf_file_name.mp4" + page_count=$(pdfinfo "$input_pdf_file_name" | awk '/^Pages:/ {print $2}') video_file_names_array=() +function make_video { + 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 - ${time_play} )) + time_opt="-c:a mp3 -af adelay=${add_time}s:all=true" # + 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}" +} + echo "Всего страниц $page_count" for ((page=1;page<=${page_count};page++)); do @@ -26,14 +59,14 @@ for ((page=1;page<=${page_count};page++)); do page_text_file="${input_pdf_file_name}_${page}.txt" page_image_file="${input_pdf_file_name}_${page}" - pdftotext -f $page -l $page "$input_pdf_file_name" "$page_text_file" - pdftoppm -f $page -l $page -png -singlefile "$input_pdf_file_name" "$page_image_file" + pdftotext -f $page -l $page "${input_pdf_file_name}" "$page_text_file" + pdftoppm -r 300 -f $page -l $page -png -singlefile "${input_pdf_file_name}" "$page_image_file" page_image_file="${page_image_file}.png" - if [ "$use_half"="yes" ]; then - - source_text=$(cat "${page_text_file}") + source_text=$(cat "${page_text_file}") + + if [ "$use_half"="yes" ] && [ ${#source_text} -ge $minimum_text_on_page ]; then space_char=" " split_size=$(( ${#source_text} / 2 + 2)) # Половина с небольшим запасом @@ -62,32 +95,21 @@ for ((page=1;page<=${page_count};page++)); do width=$(identify -format "%w" "$page_image_file")> /dev/null height=$(identify -format "%h" "$page_image_file")> /dev/null - height_half=$(($height/2)) + height_half=$(( $height / 2 + $height / 10 )) 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_half "$page_image_file_half2" + convert "$page_image_file" -crop ${width}x${height_half}+0+$(( $height - $height_half )) "$page_image_file_half2" page_mp4_file_half1="${input_pdf_file_name}_${page}_half1.mp4" - - ffmpeg $ffmpeg_pre_options -i "$page_image_file_half1" -i "$page_mp3_file_half1" $ffmpeg_options "$page_mp4_file_half1" - - SAVE_IFS=$IFS - IFS="" - video_file_names_array+=($page_mp4_file_half1) - IFS=$SAVE_IFS - page_mp4_file_half2="${input_pdf_file_name}_${page}_half2.mp4" - ffmpeg $ffmpeg_pre_options -i "$page_image_file_half2" -i "$page_mp3_file_half2" $ffmpeg_options "$page_mp4_file_half2" + make_video "$page_image_file_half1" "$page_mp3_file_half1" "$page_mp4_file_half1" - SAVE_IFS=$IFS - IFS="" - video_file_names_array+=($page_mp4_file_half2) - IFS=$SAVE_IFS + make_video "$page_image_file_half2" "$page_mp3_file_half2" "$page_mp4_file_half2" rm "$page_image_file_half1" rm "$page_image_file_half2" @@ -98,20 +120,14 @@ for ((page=1;page<=${page_count};page++)); do rm "$page_mp3_file_half2" else - ~/txt2mp3_by_yatts "$page_text_file" page_mp3_file="${page_text_file}_yatts.mp3" page_mp4_file="${input_pdf_file_name}_${page}.mp4" - - ffmpeg $ffmpeg_pre_options -i "$page_image_file" -i "$page_mp3_file" $ffmpeg_options "$page_mp4_file" - - SAVE_IFS=$IFS - IFS="" - video_file_names_array+=($page_mp4_file) - IFS=$SAVE_IFS - + + make_video "$page_image_file" "$page_mp3_file" "$page_mp4_file" + rm "$page_mp3_file" fi @@ -122,23 +138,17 @@ for ((page=1;page<=${page_count};page++)); do done -cmd="" -for ((i = 0; i < ${#video_file_names_array[@]}; i++)) do - cmd="$cmd|${video_file_names_array[$i]}" -done -cmd=${cmd:1} - -out_file="${input_pdf_file_name}.mp4" - -echo "Объединяем файлы $cmd в $out_file" -ffmpeg -i "concat:$cmd" -acodec copy -vcodec copy "$out_file" - +SAVE_IFS=$IFS IFS="" +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]}" echo "Удаляем файл '$f'" rm "$f" done +IFS=$SAVE_IFS echo "Конечный файл создан '$out_file'!" diff --git a/Script/txt2mp3_by_yatts b/Script/txt2mp3_by_yatts index f288d59..7c800af 100755 --- a/Script/txt2mp3_by_yatts +++ b/Script/txt2mp3_by_yatts @@ -5,72 +5,92 @@ emotion='neutral' #'Default is neutral. Also supported are good (friendly) and e speaker='ermil' # (Optional): Speaker voice. Default is zahar. Supported female voices are jane, oksana, alyss, omazh and male voices are zahar and ermil. #["oksana","jane","omazh","zahar","ermil","silaerkan","erkanyavas","alyss", "nick","alena","filipp"] speed='1.0' +verbose=true +ffmpeg_opt="" # https://stackoverflow.com/questions/16483119/an-example-of-how-to-use-getopts-in-bash input_file_name="$1" +out_file="${input_file_name}_yatts.mp3" source_text=$(cat "${input_file_name}") -# Удаляем все пробелы в начале и в конце строк и заменяем два и более пробелов на один -source_text="$(echo -n "$source_text" | sed 's/^ *//;s/[ ^]*$//;s/ */ /g')" +# Удаляем все пробелы в начале и в конце строк и заменяем два и более пробелов на один, удаляем все непечатаемые символы +source_text="$(echo "${source_text//[$'\t\r\n']}" | sed 's/^ *//;s/[ ^]*$//;s/ */ /;s/[^[:blank:][:print:]]//g')" -#echo "Исходный текст $source_text" +#[ $verbose ] && echo "Исходный текст $source_text" >> "out.txt" ping -c 3 ya.ru &>/dev/null || { echo "Интернет недоступен."; exit; } -audio_file_names_array=() - split_size=1450 echo "Длина текста ${#source_text}: Разбиваем на части по $split_size" +txt_array=() + space_char=" " -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 "Часть номер $file_index" - echo "------------------------------" - echo $cur_text - echo "------------------------------" - # Максимальная длина SEND_IRI - 1590 символов, длина SEND_IRI без текста = 75 символов # Максимальная длина текста = 1590 - 75 = 1515 символов - text_count=$(echo "$cur_text" | wc -m) + text_count=${#cur_text} [ $text_count -ge 1515 ] && { echo "Превышено максимальное колличество символов - 1515"; exit; } - audio_file_name="${input_file_name}_${file_index}.mp3" - 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; } - echo "Файл '$audio_file_name' загружен." - SAVE_IFS=$IFS IFS="" - audio_file_names_array+=($audio_file_name) + txt_array+=($cur_text) IFS=$SAVE_IFS cur_text="" fi done -out_file="${input_file_name}_yatts.mp3" +audio_file_names_array=() + +[ ${#txt_array[@]} -le 0 ] && { txt_array+="."; } SAVE_IFS=$IFS IFS="" -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 "$out_file" +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_name}_${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]}" - echo "Удаляем файл '$f'" + [ $verbose ] && echo "Удаляем файл '$f'" rm "$f" done IFS=$SAVE_IFS -echo "Конечный файл создан '$out_file'!" +[ $verbose ] && echo "Конечный файл создан '$out_file'!" From c1b847c64e71ff7d48f33fe890d4cebacb07697d Mon Sep 17 00:00:00 2001 From: Alexei Bezborodov Date: Fri, 5 Jan 2024 10:35:38 +0300 Subject: [PATCH 09/15] =?UTF-8?q?=D0=98=D0=BD=D1=82=D0=B5=D1=80=D1=84?= =?UTF-8?q?=D0=B5=D0=B9=D1=81=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B0=D0=BD=D0=B4?= =?UTF-8?q?=D0=BD=D0=BE=D0=B9=20=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B8.=20?= =?UTF-8?q?=D0=A2=D0=B5=D1=81=D1=82=20=D0=B3=D0=BE=D0=BB=D0=BE=D1=81=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Script/pdf2video | 2 +- Script/test_speakers | 20 ++++++++ Script/txt2mp3_by_yatts | 123 +++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 132 insertions(+), 13 deletions(-) create mode 100755 Script/test_speakers diff --git a/Script/pdf2video b/Script/pdf2video index 5e30b67..313bf01 100755 --- a/Script/pdf2video +++ b/Script/pdf2video @@ -95,7 +95,7 @@ for ((page=1;page<=${page_count};page++)); do width=$(identify -format "%w" "$page_image_file")> /dev/null height=$(identify -format "%h" "$page_image_file")> /dev/null - height_half=$(( $height / 2 + $height / 10 )) + height_half=$(( $height / 2 + $height / 20 )) page_image_file_half1="${page_image_file}_half1.png" page_image_file_half2="${page_image_file}_half2.png" diff --git a/Script/test_speakers b/Script/test_speakers new file mode 100755 index 0000000..7b47e8e --- /dev/null +++ b/Script/test_speakers @@ -0,0 +1,20 @@ +#!/bin/sh +# Общественное достояние, 2024, Алексей Безбородов (Alexei Bezborodov) + +# Тест всех голосов + +in_file=$1 + +declare -a speaker_arr=("oksana" "jane" "omazh" "zahar" "ermil" "silaerkan" "erkanyavas" "alyss" "nick") +declare -a emotion_arr=("neutral" "good" "evil") + +for s in "${speaker_arr[@]}" +do + for e in "${emotion_arr[@]}" + do + echo "speaker ${s} emotion ${e}" + echo "~/txt2mp3_by_yatts -i \"${in_file}\" -o \"${in_file}_${s}_${e}.mp3\" -e \"${e}\" -s \"${s}\"" + ~/txt2mp3_by_yatts -i "${in_file}" -o "${in_file}_${s}_${e}.mp3" -e "${e}" -s "${s}" + done +done + diff --git a/Script/txt2mp3_by_yatts b/Script/txt2mp3_by_yatts index 7c800af..c7d18c5 100755 --- a/Script/txt2mp3_by_yatts +++ b/Script/txt2mp3_by_yatts @@ -1,19 +1,117 @@ #!/bin/bash -# Озвучивание русского текста из файла -# Параметры -emotion='neutral' #'Default is neutral. Also supported are good (friendly) and evil (angry)' -speaker='ermil' # (Optional): Speaker voice. Default is zahar. Supported female voices are jane, oksana, alyss, omazh and male voices are zahar and ermil. -#["oksana","jane","omazh","zahar","ermil","silaerkan","erkanyavas","alyss", "nick","alena","filipp"] +# Общественное достояние, 2024, Алексей Безбородов (Alexei Bezborodov) + +# Озвучивание текста из файла + +# Параметры по умолчанию +emotion='neutral' +speaker='ermil' speed='1.0' -verbose=true +verbose= ffmpeg_opt="" +version=1.0 +input_file="" +out_file="" +format="mp3" +quality="hi" +lang="ru_RU" + +ShowHelp() { +cat << EOF +Использование: txt2mp3 -i [-o ] [-hV] +Озвучивание текста + +-h, -help, --help Посмотреть помощь. +-v, -version, --version Посмотреть версию программы. +-i, -input, --input Входной текстовый файл. +-o, -output, --output Выходной файл звуковой. +-e, -emotion, --emotion Эмоциональный настрой говорящего. Может принимать значения "neutral", "good", "evil". По умолчанию "$emotion". +-s, -speaker, --speaker Голос говорящего. Может принимать значения "oksana","jane","omazh","zahar","ermil","silaerkan","erkanyavas","alyss", "nick". По умолчанию "$speaker". +-S, -speed, --speed Скорость озвучки. По умолчанию "$speed". +-O, -ffmpeg_opt, --ffmpeg_opt Дополнительные параметры ffmpeg. +-f, -format, --format Выходной формат. Может быть либо "mp3", либо "wav". По умолчанию "$format". +-q, -quality, --quality Качество выходного файла. Может быть либо "hi", либо "lo". По умолчанию "$quality". +-l, -lang, --lang Язык озвучки. По умолчанию "$lang". +-V, -verbose, --verbose Подробный вывод. +EOF +} + +# $@ 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. + + +options=$(getopt --long "help,version,verbose,input:,output:,emotion:,speaker:,speed:,ffmpeg_opt:,format:,quality:,lang:" -o "hvVi:o:e:s:S:O:f:q:l:" -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" + +while true +do +case "$1" in +-h|--help) + ShowHelp + exit + ;; +-v|--version) + echo $version + exit + ;; +-V|--verbose) + verbose=true + ;; +-i|--input) + input_file="$2" + ;; +-o|--output) + out_file="$2" + ;; +-e|--emotion) + emotion="$2" + ;; +-s|--speaker) + speaker="$2" + ;; +-S|--speed) + speed="$2" + ;; +-O|--ffmpeg_opt) + ffmpeg_opt="$2" + ;; +-f|--format) + format="$2" + ;; +-q|--quality) + quality="$2" + ;; +-l|--lang) + lang="$2" + ;; +--) + shift + break;; +esac +shift +done -# https://stackoverflow.com/questions/16483119/an-example-of-how-to-use-getopts-in-bash +unuse_param="$*" +if [ "${input_file}" = "" ] || [ "$unuse_param" != "" ]; then + [ "$unuse_param" != "" ] && echo "Параметры не расшифрованы \"$unuse_param\"" + ShowHelp + exit +fi -input_file_name="$1" -out_file="${input_file_name}_yatts.mp3" +[ "$out_file" = "" ] && { out_file="$input_file.mp3"; [ $verbose ] && echo "Выходное имя файла \"$out_file\""; } -source_text=$(cat "${input_file_name}") +source_text=$(cat "${input_file}") # Удаляем все пробелы в начале и в конце строк и заменяем два и более пробелов на один, удаляем все непечатаемые символы source_text="$(echo "${source_text//[$'\t\r\n']}" | sed 's/^ *//;s/[ ^]*$//;s/ */ /;s/[^[:blank:][:print:]]//g')" @@ -23,7 +121,7 @@ source_text="$(echo "${source_text//[$'\t\r\n']}" | sed 's/^ *//;s/[ ^]*$//;s/ ping -c 3 ya.ru &>/dev/null || { echo "Интернет недоступен."; exit; } split_size=1450 -echo "Длина текста ${#source_text}: Разбиваем на части по $split_size" +[ $verbose ] && echo "Длина текста ${#source_text}: Разбиваем на части по $split_size" txt_array=() @@ -49,6 +147,7 @@ done audio_file_names_array=() +# Если текст пустой, то всё равно создаём выходной файл [ ${#txt_array[@]} -le 0 ] && { txt_array+="."; } SAVE_IFS=$IFS @@ -65,7 +164,7 @@ for ((i = 0; i < ${#txt_array[@]}; i++)) do #[ $verbose ] && echo $cur_text >> "out.txt" - audio_file_name="${input_file_name}_${file_index}.mp3" + audio_file_name="${input_file}_${file_index}.mp3" [ $verbose ] && echo -en "\nЗагрузка аудио в файл '$audio_file_name'...\n" From f9db393df09df2f58d68a7e93e7d7024feca3a21 Mon Sep 17 00:00:00 2001 From: Alexei Bezborodov Date: Fri, 5 Jan 2024 12:26:47 +0300 Subject: [PATCH 10/15] =?UTF-8?q?=D0=9F=D0=B0=D1=80=D0=B0=D0=BC=D0=B5?= =?UTF-8?q?=D1=82=D1=80=D1=8B=20=D0=B2=D0=B8=D0=B4=D0=B5=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Script/pdf2video | 259 ++++++++++++++++++++++++++++------- Script/{txt2mp3_by_yatts => txt2mp3} | 2 +- install.sh | 2 +- 3 files changed, 211 insertions(+), 52 deletions(-) rename Script/{txt2mp3_by_yatts => txt2mp3} (99%) diff --git a/Script/pdf2video b/Script/pdf2video index 313bf01..39e9c92 100755 --- a/Script/pdf2video +++ b/Script/pdf2video @@ -1,28 +1,171 @@ #!/bin/bash +# Общественное достояние, 2024, Алексей Безбородов (Alexei Bezborodov) + # Озвучивание русского текста из файла pdf и сохранение в видео -# Параметры -emotion='neutral' #'Default is neutral. Also supported are good (friendly) and evil (angry)' -speaker='ermil' # (Optional): Speaker voice. Default is zahar. Supported female voices are jane, oksana, alyss, omazh and male voices are zahar and ermil. -#["oksana","jane","omazh","zahar","ermil","silaerkan","erkanyavas","alyss", "nick","alena","filipp"] + +# Параметры по умолчанию +emotion='neutral' +speaker='erkanyavas' speed='1.0' -use_half="yes" # yes or no +verbose= +ffmpeg_opt="" +version=1.0 +input_file="" +out_file="" +format="mp3" +quality="hi" +lang="ru_RU" + +half="yes" video_width=1920 video_height=1080 ffmpeg_pre_options="-loop 1 -r 2" -ffmpeg_options="-c:v libx264 -tune stillimage -preset ultrafast -crf 20 -shortest -pix_fmt yuv420p -s ${video_width}*${video_height}" +ffmpeg_options="-c:v libx264 -tune stillimage -preset ultrafast -crf 20 -shortest -pix_fmt yuv420p" minimum_text_on_page=1000 minimum_time_on_page=5 +page_range="" -#---------------------------------------------------- +ShowHelp() { +cat << EOF +Использование: pdf2video -i [-o ] [-hV] +Озвучивание текста + +Общие параметры +-h, -help, --help Посмотреть помощь. +-v, -version, --version Посмотреть версию программы. +-V, -verbose, --verbose Подробный вывод. + +Параметры звука +-i, -input, --input Входной текстовый файл. +-o, -output, --output Выходной файл звуковой. +-e, -emotion, --emotion Эмоциональный настрой говорящего. Может принимать значения "neutral", "good", "evil". По умолчанию "$emotion". +-s, -speaker, --speaker Голос говорящего. Может принимать значения "oksana","jane","omazh","zahar","ermil","silaerkan","erkanyavas","alyss", "nick". По умолчанию "$speaker". +-S, -speed, --speed Скорость озвучки. По умолчанию "$speed". +-O, -ffmpeg_opt, --ffmpeg_opt Дополнительные параметры ffmpeg. +-f, -format, --format Выходной формат. Может быть либо "mp3", либо "wav". По умолчанию "$format". +-q, -quality, --quality Качество выходного файла. Может быть либо "hi", либо "lo". По умолчанию "$quality". +-l, -lang, --lang Язык озвучки. По умолчанию "$lang". + +Параметры видео +-k, -half, --half Деление страницы пополам. Может быть либо "yes", либо "no". По умолчанию "$half". +-W, -video_width, --video_width Размер видео в пикселях по ширине. По умолчанию "$video_width". +-H, -video_height, --video_height Размер видео в пикселях по высоте. По умолчанию "$video_height". +-p, -ffmpeg_pre_options, --ffmpeg_pre_options + Опции ffmpeg в самом начале. По умолчанию "$ffmpeg_pre_options". +-P, -ffmpeg_options, --ffmpeg_options Опции ffmpeg. По умолчанию "$ffmpeg_options". +-r, -page_range, --page_range Указывает страницы из выходного файла для обработки. Пример "{1..32}", "{2..10..2}", "\$(seq 5 3 30)" + +EOF +} + +# $@ 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. + + +options=$(getopt --long "help,version,verbose,input:,output:,emotion:,speaker:,speed:,ffmpeg_opt:,format:,quality:,lang:,half:,video_width:,video_height:, ffmpeg_pre_options:,ffmpeg_options:,page_range:" -o "hvVi:o:e:s:S:O:f:q:l:k:W:H:p:P:r:" -a -- "$@") -input_pdf_file_name="$1" +# 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" -out_file="$input_pdf_file_name.mp4" +while true +do +case "$1" in +-h|--help) + ShowHelp + exit + ;; +-v|--version) + echo $version + exit + ;; +-V|--verbose) + verbose=true + ;; +-i|--input) + input_file="$2" + ;; +-o|--output) + out_file="$2" + ;; +-e|--emotion) + emotion="$2" + ;; +-s|--speaker) + speaker="$2" + ;; +-S|--speed) + speed="$2" + ;; +-O|--ffmpeg_opt) + ffmpeg_opt="$2" + ;; +-f|--format) + format="$2" + ;; +-q|--quality) + quality="$2" + ;; +-l|--lang) + lang="$2" + ;; +-H|--half) + half="$2" + ;; +-W|--video_width) + video_width="$2" + ;; +-H|--video_height) + video_height="$2" + ;; +-p|--ffmpeg_pre_options) + ffmpeg_pre_options="$2" + ;; +-P|--ffmpeg_options) + ffmpeg_options="$2" + ;; +-r|--page_range) + page_range="$2" + ;; +--) + shift + break;; +esac +shift +done + +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_pdf_file_name" | awk '/^Pages:/ {print $2}') +#---------------------------------------------------- + +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" + + ~/txt2mp3 -i "$text_file" -o "$mp3_file" -e $emotion -s $speaker -S $speed -f $format -q $quality -l $lang $verb +} + function make_video { local page_image_file=$1 local page_mp3_file=$2 @@ -31,7 +174,7 @@ function make_video { 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 @@ -39,35 +182,51 @@ function make_video { time_opt="-c:a mp3 -af adelay=${add_time}s:all=true" # 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}" } -echo "Всего страниц $page_count" +[ $verbose ] && echo "Всего страниц $page_count" for ((page=1;page<=${page_count};page++)); do - - echo "------------------------------------------------" - echo "Обрабатываем страницу №$page" - - page_text_file="${input_pdf_file_name}_${page}.txt" - page_image_file="${input_pdf_file_name}_${page}" - pdftotext -f $page -l $page "${input_pdf_file_name}" "$page_text_file" - pdftoppm -r 300 -f $page -l $page -png -singlefile "${input_pdf_file_name}" "$page_image_file" + + 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 [ "$use_half"="yes" ] && [ ${#source_text} -ge $minimum_text_on_page ]; then - + if [ "$half"="yes" ] && [ ${#source_text} -ge $minimum_text_on_page ]; then + space_char=" " split_size=$(( ${#source_text} / 2 + 2)) # Половина с небольшим запасом file_index=0 @@ -76,27 +235,27 @@ for ((page=1;page<=${page_count};page++)); do 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_mp3_half1="${page_text_file}_half1" - file_mp3_half2="${page_text_file}_half2" - - ~/txt2mp3_by_yatts "${file_mp3_half1}" - ~/txt2mp3_by_yatts "${file_mp3_half2}" - - page_mp3_file_half1="${file_mp3_half1}_yatts.mp3" - page_mp3_file_half2="${file_mp3_half2}_yatts.mp3" + 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" @@ -104,27 +263,27 @@ for ((page=1;page<=${page_count};page++)); do 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_pdf_file_name}_${page}_half1.mp4" - page_mp4_file_half2="${input_pdf_file_name}_${page}_half2.mp4" - + page_mp4_file_half1="${input_file}_${page}_half1.mp4" + page_mp4_file_half2="${input_file}_${page}_half2.mp4" + make_video "$page_image_file_half1" "$page_mp3_file_half1" "$page_mp4_file_half1" - + make_video "$page_image_file_half2" "$page_mp3_file_half2" "$page_mp4_file_half2" - + rm "$page_image_file_half1" rm "$page_image_file_half2" - - rm "$file_mp3_half1" - rm "$file_mp3_half2" + + rm "$file_txt_half1" + rm "$file_txt_half2" rm "$page_mp3_file_half1" rm "$page_mp3_file_half2" else - ~/txt2mp3_by_yatts "$page_text_file" - - page_mp3_file="${page_text_file}_yatts.mp3" + page_mp3_file="${page_text_file}.mp3" + + Text2mp3 "$page_text_file" "$page_mp3_file" - page_mp4_file="${input_pdf_file_name}_${page}.mp4" + page_mp4_file="${input_file}_${page}.mp4" make_video "$page_image_file" "$page_mp3_file" "$page_mp4_file" @@ -140,15 +299,15 @@ done SAVE_IFS=$IFS IFS="" -echo "Объединяем файлы ${video_file_names_array[*]} в $out_file" +[ $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]}" - echo "Удаляем файл '$f'" + [ $verbose ] && echo "Удаляем файл '$f'" rm "$f" done IFS=$SAVE_IFS -echo "Конечный файл создан '$out_file'!" +[ $verbose ] && echo "Конечный файл создан '$out_file'!" diff --git a/Script/txt2mp3_by_yatts b/Script/txt2mp3 similarity index 99% rename from Script/txt2mp3_by_yatts rename to Script/txt2mp3 index c7d18c5..3a133d5 100755 --- a/Script/txt2mp3_by_yatts +++ b/Script/txt2mp3 @@ -5,7 +5,7 @@ # Параметры по умолчанию emotion='neutral' -speaker='ermil' +speaker='erkanyavas' speed='1.0' verbose= ffmpeg_opt="" diff --git a/install.sh b/install.sh index 2f66905..7584bbb 100644 --- a/install.sh +++ b/install.sh @@ -39,7 +39,7 @@ sudo apt-get install \ texlive texstudio \ systemd-settings-disable-kill-user-processes \ retext \ - gedit gedit-plugins gedit-plugins-latex \ + gedit gedit-plugins gedit-plugin-devhelp gedit-plugins-latex \ cinnamon-full idesk icewm pcmanfm volumeicon mc \ nemo nemo-emblems nemo-fileroller \ nemo-compare nemo-share-common nemo-arronax nemo-preview nemo-python-devel \ From 343d915615f4f12ae2030d7124329f1405de4e03 Mon Sep 17 00:00:00 2001 From: Alexei Bezborodov Date: Fri, 5 Jan 2024 22:56:01 +0300 Subject: [PATCH 11/15] =?UTF-8?q?=D0=90=D0=B2=D1=82=D0=BE=D0=BC=D0=B0?= =?UTF-8?q?=D1=82=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B0=D1=8F=20=D0=BE=D0=B1?= =?UTF-8?q?=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B0=20=D0=BF=D0=B0=D1=80?= =?UTF-8?q?=D0=B0=D0=BC=D0=B5=D1=82=D1=80=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Script/{text2mp3 => festival_txt2mp3} | 0 Script/pdf2video | 287 ++++++++++++++++++++-------------- Script/txt2mp3 | 2 +- 3 files changed, 170 insertions(+), 119 deletions(-) rename Script/{text2mp3 => festival_txt2mp3} (100%) diff --git a/Script/text2mp3 b/Script/festival_txt2mp3 similarity index 100% rename from Script/text2mp3 rename to Script/festival_txt2mp3 diff --git a/Script/pdf2video b/Script/pdf2video index 39e9c92..da0adc9 100755 --- a/Script/pdf2video +++ b/Script/pdf2video @@ -3,58 +3,131 @@ # Озвучивание русского текста из файла pdf и сохранение в видео -# Параметры по умолчанию -emotion='neutral' -speaker='erkanyavas' -speed='1.0' -verbose= -ffmpeg_opt="" version=1.0 -input_file="" -out_file="" -format="mp3" -quality="hi" -lang="ru_RU" - -half="yes" -video_width=1920 -video_height=1080 -ffmpeg_pre_options="-loop 1 -r 2" -ffmpeg_options="-c:v libx264 -tune stillimage -preset ultrafast -crf 20 -shortest -pix_fmt yuv420p" -minimum_text_on_page=1000 -minimum_time_on_page=5 -page_range="" - -ShowHelp() { + +# Формат: +# "Однобуквенная комманда|Расширенная комманда|Справка|Параметр|Значение по умолчанию|Команда на исполнение" +# Параметр: Пусто - нет параметров, : - есть параметр, :: - параметр не обязателен + +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 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 +} + +function Params2InitVar { + local small_cmd="$1" + local large_cmd="$2" + local comment="$3" + local use_param="$4" + local default="$5" + local custom_cmd="$6" + if [ "$use_param" != '' ]; then + eval "${large_cmd}=${default}" + fi +} + +function Params2Help { + local small_cmd="$1" + local large_cmd="$2" + local comment="$3" + local use_param="$4" + local default="$5" + local custom_cmd="$6" + echo "-${small_cmd}, -${large_cmd}, --${large_cmd}" + echo " ${comment/"!DEFAULT!"/"${!large_cmd}"}" +} + +function Params2small_list { + local small_cmd="$1" + local large_cmd="$2" + local comment="$3" + local use_param="$4" + local default="$5" + local custom_cmd="$6" + echo -n "${small_cmd}${use_param}" +} + +function Params2large_list { + local small_cmd="$1" + local large_cmd="$2" + local comment="$3" + local use_param="$4" + local default="$5" + local custom_cmd="$6" + echo -n ",${large_cmd}${use_param}" +} + +# Инициализация переменных +ProcessParams all_params Params2InitVar + +function ShowHelp() { cat << EOF Использование: pdf2video -i [-o ] [-hV] -Озвучивание текста +Озвучивание русского текста из файла pdf и сохранение в видео Общие параметры --h, -help, --help Посмотреть помощь. --v, -version, --version Посмотреть версию программы. --V, -verbose, --verbose Подробный вывод. +$(ProcessParams common_params Params2Help) Параметры звука --i, -input, --input Входной текстовый файл. --o, -output, --output Выходной файл звуковой. --e, -emotion, --emotion Эмоциональный настрой говорящего. Может принимать значения "neutral", "good", "evil". По умолчанию "$emotion". --s, -speaker, --speaker Голос говорящего. Может принимать значения "oksana","jane","omazh","zahar","ermil","silaerkan","erkanyavas","alyss", "nick". По умолчанию "$speaker". --S, -speed, --speed Скорость озвучки. По умолчанию "$speed". --O, -ffmpeg_opt, --ffmpeg_opt Дополнительные параметры ffmpeg. --f, -format, --format Выходной формат. Может быть либо "mp3", либо "wav". По умолчанию "$format". --q, -quality, --quality Качество выходного файла. Может быть либо "hi", либо "lo". По умолчанию "$quality". --l, -lang, --lang Язык озвучки. По умолчанию "$lang". +$(ProcessParams sound_params Params2Help) Параметры видео --k, -half, --half Деление страницы пополам. Может быть либо "yes", либо "no". По умолчанию "$half". --W, -video_width, --video_width Размер видео в пикселях по ширине. По умолчанию "$video_width". --H, -video_height, --video_height Размер видео в пикселях по высоте. По умолчанию "$video_height". --p, -ffmpeg_pre_options, --ffmpeg_pre_options - Опции ffmpeg в самом начале. По умолчанию "$ffmpeg_pre_options". --P, -ffmpeg_options, --ffmpeg_options Опции ffmpeg. По умолчанию "$ffmpeg_options". --r, -page_range, --page_range Указывает страницы из выходного файла для обработки. Пример "{1..32}", "{2..10..2}", "\$(seq 5 3 30)" - +$(ProcessParams video_params Params2Help) EOF } @@ -67,81 +140,50 @@ EOF # '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 "help,version,verbose,input:,output:,emotion:,speaker:,speed:,ffmpeg_opt:,format:,quality:,lang:,half:,video_width:,video_height:, ffmpeg_pre_options:,ffmpeg_options:,page_range:" -o "hvVi:o:e:s:S:O:f:q:l:k:W:H:p:P:r:" -a -- "$@") +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" +function Params2Case { + 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" + + 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 +} + while true do -case "$1" in --h|--help) - ShowHelp - exit - ;; --v|--version) - echo $version - exit - ;; --V|--verbose) - verbose=true - ;; --i|--input) - input_file="$2" - ;; --o|--output) - out_file="$2" - ;; --e|--emotion) - emotion="$2" - ;; --s|--speaker) - speaker="$2" - ;; --S|--speed) - speed="$2" - ;; --O|--ffmpeg_opt) - ffmpeg_opt="$2" - ;; --f|--format) - format="$2" - ;; --q|--quality) - quality="$2" - ;; --l|--lang) - lang="$2" - ;; --H|--half) - half="$2" - ;; --W|--video_width) - video_width="$2" - ;; --H|--video_height) - video_height="$2" - ;; --p|--ffmpeg_pre_options) - ffmpeg_pre_options="$2" - ;; --P|--ffmpeg_options) - ffmpeg_options="$2" - ;; --r|--page_range) - page_range="$2" - ;; ---) - shift - break;; -esac +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\"" @@ -157,16 +199,26 @@ page_count=$(pdfinfo "${input_file}" | awk '/^Pages:/ {print $2}') video_file_names_array=() +function GetExec { + local exec_file_name=$1 + + exec="$exec_file_name" + [ ! -f "$exec" ] && exec="./$exec" + [ ! -f "$exec" ] && exec="~/$exec" + + echo "$exec" +} + function Text2mp3 { local text_file=$1 local mp3_file=$2 verb="" [ $verbose ] && verb="-V" - ~/txt2mp3 -i "$text_file" -o "$mp3_file" -e $emotion -s $speaker -S $speed -f $format -q $quality -l $lang $verb + $(GetExec "txt2mp3") -i "$text_file" -o "$mp3_file" -e $emotion -s $speaker -S $speed -f $format -q $quality -l $lang $verb } -function make_video { +function MakeVideo { local page_image_file=$1 local page_mp3_file=$2 local page_mp4_file=$3 @@ -178,9 +230,9 @@ function make_video { 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 - ${time_play} )) + local add_time=5 # $(( 5 - ${time_play} )) time_opt="-c:a mp3 -af adelay=${add_time}s:all=true" # - echo "time_opt ${time_opt}" + [ $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}" @@ -223,9 +275,9 @@ for ((page=1;page<=${page_count};page++)); do page_image_file="${page_image_file}.png" - source_text=$(cat "${page_text_file}") + source_text="$(cat "${page_text_file}")" - if [ "$half"="yes" ] && [ ${#source_text} -ge $minimum_text_on_page ]; then + if [ "$split" = "yes" ] && [ ${#source_text} -ge $minimum_text_on_page ]; then space_char=" " split_size=$(( ${#source_text} / 2 + 2)) # Половина с небольшим запасом @@ -266,9 +318,9 @@ for ((page=1;page<=${page_count};page++)); do page_mp4_file_half1="${input_file}_${page}_half1.mp4" page_mp4_file_half2="${input_file}_${page}_half2.mp4" - make_video "$page_image_file_half1" "$page_mp3_file_half1" "$page_mp4_file_half1" + MakeVideo "$page_image_file_half1" "$page_mp3_file_half1" "$page_mp4_file_half1" - make_video "$page_image_file_half2" "$page_mp3_file_half2" "$page_mp4_file_half2" + MakeVideo "$page_image_file_half2" "$page_mp3_file_half2" "$page_mp4_file_half2" rm "$page_image_file_half1" rm "$page_image_file_half2" @@ -285,16 +337,15 @@ for ((page=1;page<=${page_count};page++)); do page_mp4_file="${input_file}_${page}.mp4" - make_video "$page_image_file" "$page_mp3_file" "$page_mp4_file" - + 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 diff --git a/Script/txt2mp3 b/Script/txt2mp3 index 3a133d5..0c2fae1 100755 --- a/Script/txt2mp3 +++ b/Script/txt2mp3 @@ -114,7 +114,7 @@ fi source_text=$(cat "${input_file}") # Удаляем все пробелы в начале и в конце строк и заменяем два и более пробелов на один, удаляем все непечатаемые символы -source_text="$(echo "${source_text//[$'\t\r\n']}" | sed 's/^ *//;s/[ ^]*$//;s/ */ /;s/[^[:blank:][:print:]]//g')" +source_text="$(echo "${source_text//[$'\t\r\n']/' '}" | sed 's/^ *//;s/[ ^]*$//;s/ */ /;s/[^[:blank:][:print:]]//g')" #[ $verbose ] && echo "Исходный текст $source_text" >> "out.txt" From 469e703b203113bab1da50bf48769c0f155a4a70 Mon Sep 17 00:00:00 2001 From: Alexei Bezborodov Date: Fri, 5 Jan 2024 23:38:16 +0300 Subject: [PATCH 12/15] =?UTF-8?q?=D0=91=D0=B8=D0=B1=D0=BB=D0=B8=D0=BE?= =?UTF-8?q?=D1=82=D0=B5=D0=BA=D0=B0=20=D0=B4=D0=BB=D1=8F=20=D0=BE=D0=B1?= =?UTF-8?q?=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B8=20=D0=B0=D1=80=D0=B3?= =?UTF-8?q?=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Script/parse_arg_lib | 104 ++++++++++++++++++++++++++++++++++++++++ Script/pdf2video | 106 ++++------------------------------------ Script/txt2mp3 | 133 ++++++++++++++++++++++++--------------------------- 3 files changed, 176 insertions(+), 167 deletions(-) create mode 100755 Script/parse_arg_lib diff --git a/Script/parse_arg_lib b/Script/parse_arg_lib new file mode 100755 index 0000000..dc4e8d9 --- /dev/null +++ b/Script/parse_arg_lib @@ -0,0 +1,104 @@ +#!/bin/bash +# Общественное достояние, 2024, Алексей Безбородов (Alexei Bezborodov) + +# Обработка входных параметров + +# Формат: +# "Однобуквенная комманда|Расширенная комманда|Справка|Параметр|Значение по умолчанию|Команда на исполнение" +# Параметр: Пусто - нет параметров, : - есть параметр, :: - параметр не обязателен + +# Пример +#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 +} + +function Params2InitVar { + local small_cmd="$1" + local large_cmd="$2" + local comment="$3" + local use_param="$4" + local default="$5" + local custom_cmd="$6" + if [ "$use_param" != '' ]; then + eval "${large_cmd}=${default}" + fi +} + +function Params2Help { + local small_cmd="$1" + local large_cmd="$2" + local comment="$3" + local use_param="$4" + local default="$5" + local custom_cmd="$6" + echo "-${small_cmd}, -${large_cmd}, --${large_cmd}" + echo " ${comment/"!DEFAULT!"/"${!large_cmd}"}" +} + +function Params2small_list { + local small_cmd="$1" + local large_cmd="$2" + local comment="$3" + local use_param="$4" + local default="$5" + local custom_cmd="$6" + echo -n "${small_cmd}${use_param}" +} + +function Params2large_list { + local small_cmd="$1" + local large_cmd="$2" + local comment="$3" + local use_param="$4" + local default="$5" + local custom_cmd="$6" + echo -n ",${large_cmd}${use_param}" +} + +function Params2Case { + 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" + + 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 +} + diff --git a/Script/pdf2video b/Script/pdf2video index da0adc9..1e939c0 100755 --- a/Script/pdf2video +++ b/Script/pdf2video @@ -42,75 +42,18 @@ video_params=( all_params=("${common_params[@]}" "${sound_params[@]}" "${video_params[@]}") -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 -} - -function Params2InitVar { - local small_cmd="$1" - local large_cmd="$2" - local comment="$3" - local use_param="$4" - local default="$5" - local custom_cmd="$6" - if [ "$use_param" != '' ]; then - eval "${large_cmd}=${default}" - fi -} +# Загружаем библиотеку +function GetExec { + local exec_file_name="$1" -function Params2Help { - local small_cmd="$1" - local large_cmd="$2" - local comment="$3" - local use_param="$4" - local default="$5" - local custom_cmd="$6" - echo "-${small_cmd}, -${large_cmd}, --${large_cmd}" - echo " ${comment/"!DEFAULT!"/"${!large_cmd}"}" -} + exec="$exec_file_name" + [ ! -f "$exec" ] && exec="./$exec_file_name" + [ ! -f "$exec" ] && exec="~/$exec_file_name" -function Params2small_list { - local small_cmd="$1" - local large_cmd="$2" - local comment="$3" - local use_param="$4" - local default="$5" - local custom_cmd="$6" - echo -n "${small_cmd}${use_param}" + echo "$exec" } -function Params2large_list { - local small_cmd="$1" - local large_cmd="$2" - local comment="$3" - local use_param="$4" - local default="$5" - local custom_cmd="$6" - echo -n ",${large_cmd}${use_param}" -} +eval "source $(GetExec "parse_arg_lib")" # Инициализация переменных ProcessParams all_params Params2InitVar @@ -153,26 +96,6 @@ options=$(getopt --long "$large_params_list" -o "$small_params_list" -a -- "$@") # are set to the arguments, even if some of them begin with a ‘-’. eval set -- "$options" -function Params2Case { - 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" - - 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 -} - while true do cur_arg="$1" @@ -199,23 +122,14 @@ page_count=$(pdfinfo "${input_file}" | awk '/^Pages:/ {print $2}') video_file_names_array=() -function GetExec { - local exec_file_name=$1 - - exec="$exec_file_name" - [ ! -f "$exec" ] && exec="./$exec" - [ ! -f "$exec" ] && exec="~/$exec" - - echo "$exec" -} - function Text2mp3 { local text_file=$1 local mp3_file=$2 verb="" [ $verbose ] && verb="-V" - $(GetExec "txt2mp3") -i "$text_file" -o "$mp3_file" -e $emotion -s $speaker -S $speed -f $format -q $quality -l $lang $verb + [ $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 { diff --git a/Script/txt2mp3 b/Script/txt2mp3 index 0c2fae1..ed13682 100755 --- a/Script/txt2mp3 +++ b/Script/txt2mp3 @@ -3,36 +3,60 @@ # Озвучивание текста из файла -# Параметры по умолчанию -emotion='neutral' -speaker='erkanyavas' -speed='1.0' -verbose= -ffmpeg_opt="" version=1.0 -input_file="" -out_file="" -format="mp3" -quality="hi" -lang="ru_RU" -ShowHelp() { +# Формат: +# "Однобуквенная комманда|Расширенная комманда|Справка|Параметр|Значение по умолчанию|Команда на исполнение" +# Параметр: Пусто - нет параметров, : - есть параметр, :: - параметр не обязателен + +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")" + +# Инициализация переменных +ProcessParams all_params Params2InitVar + +function ShowHelp() { cat << EOF -Использование: txt2mp3 -i [-o ] [-hV] -Озвучивание текста - --h, -help, --help Посмотреть помощь. --v, -version, --version Посмотреть версию программы. --i, -input, --input Входной текстовый файл. --o, -output, --output Выходной файл звуковой. --e, -emotion, --emotion Эмоциональный настрой говорящего. Может принимать значения "neutral", "good", "evil". По умолчанию "$emotion". --s, -speaker, --speaker Голос говорящего. Может принимать значения "oksana","jane","omazh","zahar","ermil","silaerkan","erkanyavas","alyss", "nick". По умолчанию "$speaker". --S, -speed, --speed Скорость озвучки. По умолчанию "$speed". --O, -ffmpeg_opt, --ffmpeg_opt Дополнительные параметры ffmpeg. --f, -format, --format Выходной формат. Может быть либо "mp3", либо "wav". По умолчанию "$format". --q, -quality, --quality Качество выходного файла. Может быть либо "hi", либо "lo". По умолчанию "$quality". --l, -lang, --lang Язык озвучки. По умолчанию "$lang". --V, -verbose, --verbose Подробный вывод. +Использование: pdf2mp3 -i [-o ] [-hV] +Озвучивание текста из файла + +Общие параметры +$(ProcessParams common_params Params2Help) + +Параметры звука +$(ProcessParams sound_params Params2Help) EOF } @@ -45,9 +69,13 @@ EOF # '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 "help,version,verbose,input:,output:,emotion:,speaker:,speed:,ffmpeg_opt:,format:,quality:,lang:" -o "hvVi:o:e:s:S:O:f:q:l:" -a -- "$@") +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 @@ -56,52 +84,15 @@ eval set -- "$options" while true do -case "$1" in --h|--help) - ShowHelp - exit - ;; --v|--version) - echo $version - exit - ;; --V|--verbose) - verbose=true - ;; --i|--input) - input_file="$2" - ;; --o|--output) - out_file="$2" - ;; --e|--emotion) - emotion="$2" - ;; --s|--speaker) - speaker="$2" - ;; --S|--speed) - speed="$2" - ;; --O|--ffmpeg_opt) - ffmpeg_opt="$2" - ;; --f|--format) - format="$2" - ;; --q|--quality) - quality="$2" - ;; --l|--lang) - lang="$2" - ;; ---) - shift - break;; -esac +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\"" From 92af14c2faf527f15469e4c804e2d4ecc3f8b302 Mon Sep 17 00:00:00 2001 From: Alexei Bezborodov Date: Sun, 7 Jan 2024 10:59:26 +0300 Subject: [PATCH 13/15] =?UTF-8?q?=D0=9E=D0=BF=D1=82=D0=B8=D0=BC=D0=B8?= =?UTF-8?q?=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D0=BA=D0=BE=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Script/parse_arg_lib | 68 +++++++++++++++++++++++++++------------------------- Script/pdf2video | 25 +------------------ Script/txt2mp3 | 25 +------------------ 3 files changed, 38 insertions(+), 80 deletions(-) diff --git a/Script/parse_arg_lib b/Script/parse_arg_lib index dc4e8d9..7aefba9 100755 --- a/Script/parse_arg_lib +++ b/Script/parse_arg_lib @@ -39,58 +39,37 @@ function ProcessParams { 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 { - local small_cmd="$1" - local large_cmd="$2" - local comment="$3" - local use_param="$4" - local default="$5" - local custom_cmd="$6" + eval "$param_var" + if [ "$use_param" != '' ]; then eval "${large_cmd}=${default}" fi } function Params2Help { - local small_cmd="$1" - local large_cmd="$2" - local comment="$3" - local use_param="$4" - local default="$5" - local custom_cmd="$6" + eval "$param_var" + echo "-${small_cmd}, -${large_cmd}, --${large_cmd}" echo " ${comment/"!DEFAULT!"/"${!large_cmd}"}" } function Params2small_list { - local small_cmd="$1" - local large_cmd="$2" - local comment="$3" - local use_param="$4" - local default="$5" - local custom_cmd="$6" + eval "$param_var" + echo -n "${small_cmd}${use_param}" } function Params2large_list { - local small_cmd="$1" - local large_cmd="$2" - local comment="$3" - local use_param="$4" - local default="$5" - local custom_cmd="$6" + eval "$param_var" + echo -n ",${large_cmd}${use_param}" } function Params2Case { - 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" + 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 ']/}" @@ -102,3 +81,28 @@ function Params2Case { 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" + diff --git a/Script/pdf2video b/Script/pdf2video index 1e939c0..e28c9d5 100755 --- a/Script/pdf2video +++ b/Script/pdf2video @@ -55,9 +55,6 @@ function GetExec { eval "source $(GetExec "parse_arg_lib")" -# Инициализация переменных -ProcessParams all_params Params2InitVar - function ShowHelp() { cat << EOF Использование: pdf2video -i [-o ] [-hV] @@ -74,27 +71,7 @@ $(ProcessParams video_params Params2Help) EOF } -# $@ 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" +# ------------------------------------------- while true do diff --git a/Script/txt2mp3 b/Script/txt2mp3 index ed13682..df0a468 100755 --- a/Script/txt2mp3 +++ b/Script/txt2mp3 @@ -44,9 +44,6 @@ function GetExec { eval "source $(GetExec "parse_arg_lib")" -# Инициализация переменных -ProcessParams all_params Params2InitVar - function ShowHelp() { cat << EOF Использование: pdf2mp3 -i [-o ] [-hV] @@ -60,27 +57,7 @@ $(ProcessParams sound_params Params2Help) EOF } -# $@ 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" +# ------------------------------------------- while true do From b4c0cc2dfe84256b085964784fededd3c3c9d13b Mon Sep 17 00:00:00 2001 From: Alexei Bezborodov Date: Fri, 9 Feb 2024 15:35:24 +0300 Subject: [PATCH 14/15] image wav 2 video --- Script/pdf2video | 255 ---------------------------------- Script/txt2mp3 | 163 ---------------------- video_tools/img_and_wav2video | 129 +++++++++++++++++ {Script => video_tools}/parse_arg_lib | 6 +- 4 files changed, 133 insertions(+), 420 deletions(-) delete mode 100755 Script/pdf2video delete mode 100755 Script/txt2mp3 create mode 100755 video_tools/img_and_wav2video rename {Script => video_tools}/parse_arg_lib (89%) diff --git a/Script/pdf2video b/Script/pdf2video deleted file mode 100755 index e28c9d5..0000000 --- a/Script/pdf2video +++ /dev/null @@ -1,255 +0,0 @@ -#!/bin/bash -# Общественное достояние, 2024, Алексей Безбородов (Alexei Bezborodov) - -# Озвучивание русского текста из файла 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 [-o ] [-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'!" - diff --git a/Script/txt2mp3 b/Script/txt2mp3 deleted file mode 100755 index df0a468..0000000 --- a/Script/txt2mp3 +++ /dev/null @@ -1,163 +0,0 @@ -#!/bin/bash -# Общественное достояние, 2024, Алексей Безбородов (Alexei Bezborodov) - -# Озвучивание текста из файла - -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 [-o ] [-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'!" - - diff --git a/video_tools/img_and_wav2video b/video_tools/img_and_wav2video new file mode 100755 index 0000000..a1d42c5 --- /dev/null +++ b/video_tools/img_and_wav2video @@ -0,0 +1,129 @@ +#!/bin/bash +# Общественное достояние, 2024, Алексей Безбородов (Alexei Bezborodov) + +# Озвучивание русского текста из файла pdf и сохранение в видео + +version=1.0 + +# Формат: +# "Однобуквенная команда|Расширенная команда|Справка|Параметр|Значение по умолчанию|Команда на исполнение" +# Параметр: Пусто - нет параметров, : - есть параметр, :: - параметр не обязателен + +common_params=( + "h|help|Посмотреть помощь.|||ShowHelp; exit;" + "v|version|Посмотреть версию программы.|||echo \$version; exit;" + "V|verbose|Подробный вывод.|||verbose=true" + ) + +sound_params=( + "a|audio|Входной файл с аудиодорожкой.|:||" + "b|audio_options||:|'-c:a aac -b:a 128k'|" + ) + +video_params=( + "i|image|Входной файл с изображением.|:||" + "o|output|Выходной видео файл.|:|''|" + "W|video_width|Размер видео в пикселях по ширине. По умолчанию '!DEFAULT!'.|:|1920|" + "H|video_height|Размер видео в пикселях по высоте. По умолчанию '!DEFAULT!'.|:|1080|" + "p|ffmpeg_pre_options|Опции ffmpeg в самом начале. По умолчанию '!DEFAULT!'.|:|'-loop 1 -r 1'|" + "P|ffmpeg_options|Опции ffmpeg. По умолчанию '!DEFAULT!'.|:|'-c:v libx264 -tune stillimage -preset ultrafast -crf 20 -shortest -pix_fmt yuv420p'|" + ) + +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" + + echo "$exec" +} + +eval "source $(GetExec "parse_arg_lib")" + +function ShowHelp() { +cat << EOF +Использование: pdf2video -i [-o ] [-hV] +Озвучивание русского текста из файла pdf и сохранение в видео + +Общие параметры +$(ProcessParams common_params Params2Help) + +Параметры звука +$(ProcessParams sound_params Params2Help) + +Параметры видео +$(ProcessParams video_params Params2Help) + +Примеры: + +# Расширенный вывод +img_and_wav2video -i image.jpg -a audio.wav -o out.mp4 -V + +EOF +} + +# ------------------------------------------- + +# Главный цикл обработки входных параметров +eval "$main_loop" + +image_file="$image" +audio_file="$audio" +out_file="$output" + +unuse_param="$*" +if [ "${image_file}" = "" ] || [ "${audio_file}" = "" ] || [ "${unuse_param}" != "" ]; then + [ "${unuse_param}" != "" ] && echo "Параметры не расшифрованы \"$unuse_param\"" + ShowHelp + exit +fi + +[ "$out_file" = "" ] && { out_file="${image_file}.mp4"; +[ $verbose ] && echo "Выходное имя файла \"$out_file\""; } + +#---------------------------------------------------- + +function PlayTime { + local audio_file=$1 + + out=$(soxi -D "${audio_file}") + int=$(echo "$out/1" | bc) + echo "$int" +} + +function MakeVideo { + local image_file=$1 + local audio_file=$2 + local mp4_file=$3 + + local resized_image_file=$(mktemp -t "MakeVideo_resized_page_image_XXXXXXXXXXX.png" +) + + local cmd="ffmpeg -y -i \"${image_file}\" -filter_complex \"[0]scale=${video_width}:${video_height}:force_original_aspect_ratio=decrease,pad=${video_width}:${video_height}:(ow-iw)/2:(oh-ih)/2[scale];[scale]split=2[bg][fg];[bg]drawbox=c=white@1:replace=1:t=fill[bg];[bg][fg]overlay=format=auto\" \"${resized_image_file}\"" + [ $verbose ] && echo "cmd $cmd" + eval "$cmd" + [ $verbose ] && echo "ffmpeg $?" + + local play_time=$(PlayTime "${audio_file}") + [ $verbose ] && echo "play_time ${play_time}" + play_time_plus1=$(( $play_time + 1 )) + + water_mark='' + float_image='' +# video_filter="-filter_complex \"${water_mark}\" -map \"1:a\"" + video_filter="-map 0 -map \"1:a\"" + + cmd="ffmpeg -y ${ffmpeg_pre_options} -i \"${resized_image_file}\" ${float_image} -i \"${audio_file}\" ${video_filter} ${ffmpeg_options} ${audio_options} -t \"${play_time}\" \"${mp4_file}\"" + [ $verbose ] && echo "cmd $cmd" + eval "$cmd" + [ $verbose ] && echo "ffmpeg $?" + + rm "${resized_image_file}" +} + +MakeVideo "${image_file}" "${audio_file}" "${out_file}" + + diff --git a/Script/parse_arg_lib b/video_tools/parse_arg_lib similarity index 89% rename from Script/parse_arg_lib rename to video_tools/parse_arg_lib index 7aefba9..05f3c12 100755 --- a/Script/parse_arg_lib +++ b/video_tools/parse_arg_lib @@ -1,10 +1,10 @@ #!/bin/bash -# Общественное достояние, 2024, Алексей Безбородов (Alexei Bezborodov) +# Общественное достояние, 2024, Алексей Безбородов (Alexei Bezborodov) # Обработка входных параметров # Формат: -# "Однобуквенная комманда|Расширенная комманда|Справка|Параметр|Значение по умолчанию|Команда на исполнение" +# "Однобуквенная команда|Расширенная команда|Справка|Параметр|Значение по умолчанию|Команда на исполнение" # Параметр: Пусто - нет параметров, : - есть параметр, :: - параметр не обязателен # Пример @@ -106,3 +106,5 @@ options=$(getopt --long "$large_params_list" -o "$small_params_list" -a -- "$@") # are set to the arguments, even if some of them begin with a ‘-’. eval set -- "$options" +main_loop='while true; do cur_arg="$1"; [ "$cur_arg" = "--" ] && { shift; break; }; ProcessParams all_params Params2Case "$cur_arg" "$2"; shift; done' + From bd413729073640483cd433c1a519048b628c32c5 Mon Sep 17 00:00:00 2001 From: Alexei Bezborodov Date: Mon, 12 Feb 2024 12:23:11 +0300 Subject: [PATCH 15/15] pdf script --- Script/a5_pdf.bash | 4 ++++ Script/a6_pdf.bash | 4 ++++ Script/all_pdf_to_one_file.bash | 4 ++++ Script/pagenum_pdf.bash | 4 ++++ 4 files changed, 16 insertions(+) create mode 100755 Script/a5_pdf.bash create mode 100755 Script/a6_pdf.bash create mode 100755 Script/all_pdf_to_one_file.bash create mode 100755 Script/pagenum_pdf.bash diff --git a/Script/a5_pdf.bash b/Script/a5_pdf.bash new file mode 100755 index 0000000..2d2dcdd --- /dev/null +++ b/Script/a5_pdf.bash @@ -0,0 +1,4 @@ +#!/bin/bash + +pdfjam "$1" --scale 0.71 --offset '0 50mm' -o "a5_$1" + diff --git a/Script/a6_pdf.bash b/Script/a6_pdf.bash new file mode 100755 index 0000000..013adee --- /dev/null +++ b/Script/a6_pdf.bash @@ -0,0 +1,4 @@ +#!/bin/bash + +pdfjam "$1" --scale 0.5 --offset '0 75mm' -o "a6_$1" + diff --git a/Script/all_pdf_to_one_file.bash b/Script/all_pdf_to_one_file.bash new file mode 100755 index 0000000..089d5f2 --- /dev/null +++ b/Script/all_pdf_to_one_file.bash @@ -0,0 +1,4 @@ +#!/bin/bash + +convert -density 300 '*.pdf' -density 300 all.pdf + diff --git a/Script/pagenum_pdf.bash b/Script/pagenum_pdf.bash new file mode 100755 index 0000000..9d24095 --- /dev/null +++ b/Script/pagenum_pdf.bash @@ -0,0 +1,4 @@ +#!/bin/bash + +# +pdfjam --preamble '\usepackage{fancyhdr} \pagestyle{fancy} \topmargin -65pt \oddsidemargin 150pt \rfoot{} \cfoot{} \rhead{} \chead{\Large\thepage} \renewcommand {\headrulewidth}{0pt} \renewcommand {\footrulewidth}{0pt} ' --pagecommand '\thispagestyle{fancy}' -o "pagenum_$1" "$1"