From 040032afcdfddca06783735d3246c0d4eb7d4942 Mon Sep 17 00:00:00 2001 From: Alexei Bezborodov Date: Thu, 4 Jan 2024 23:37:13 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=20=D0=BC=D0=BD=D0=BE=D0=B6=D0=B5=D1=81=D1=82?= =?UTF-8?q?=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'!"