Files for 4577 and 4596 and new host names and images

This commit is contained in:
2026-02-04 09:49:08 +01:00
parent 65e798615a
commit 6a97973c6d
38 changed files with 359 additions and 0 deletions

BIN
www/correspondents/441.flac Normal file

Binary file not shown.

BIN
www/correspondents/442.flac Normal file

Binary file not shown.

BIN
www/correspondents/452.flac Normal file

Binary file not shown.

BIN
www/correspondents/452.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

BIN
www/correspondents/454.flac Normal file

Binary file not shown.

BIN
www/correspondents/459.flac Normal file

Binary file not shown.

BIN
www/correspondents/459.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

View File

@@ -0,0 +1,359 @@
#!/usr/bin/env bash
debug="1"
padding="10"
piper_bin="/opt/bin/piper/piper/piper" # The location of the text to speech engine
piper_voice="/opt/bin/piper/piper/piper-voices/en/en_US/lessac/medium/en_US-lessac-medium.onnx"
silence_mp3="silence.mp3"
source_volume="0"
srt_volume="0"
if [ "${debug}" -ne "1" ]
then
ffmpeg_debug="-hide_banner -loglevel error"
else
ffmpeg_debug=""
fi
#################################################
function echo_error() {
echo -e "ERROR: $@" 1>&2
display_help_and_exit
exit 1
}
#################################################
function echo_debug() {
if [ "${debug}" == "2" ]
then
echo -e "INFO: $@" 1>&2
fi
}
#################################################
function echo_status() {
if [ "${debug}" -le "1" ]
then
echo -ne "\r$@" 1>&2
else
echo -e "INFO: $@" 1>&2
fi
}
#################################################
function echo_info() {
if [ "${debug}" != "0" ]
then
echo "INFO: $@" 1>&2
fi
}
#################################################
function display_help_and_exit() {
echo_debug "For more information see "
exit 1
}
#################################################
function check_variable() {
for variable in "$@"
do
if [[ -z ${!variable+x} ]]
then # indirect expansion here
echo_error "The variable \"${variable}\" is missing."
else
echo_debug "The variable \"${variable}\" is set to \"${!variable}\".~"
fi
done
}
#################################################
function timestamp_to_sec() {
this_timestamp="${1}"
this_in_sec="$( echo "${this_timestamp}" | sed 's/,/./g' | awk -F ":" '{ printf ($1 * 3600) + ($2 * 60) + $3, $0}' )"
echo "${this_in_sec}"
}
#################################################
function timestamp_to_millisec() {
printf '%.*f\n' 0 $( echo "$( timestamp_to_sec "${1}" ) * 1000" | bc --mathlib )
}
#################################################
function update_playhead() {
play_head="$( mediainfo --full --Output=JSON "${this_srt_wav_file}" | jq --raw-output '.media.track | .[] | select(."@type"=="Audio") | .Duration_String3' )"
echo_status "Play head: ${play_head} .. ${movie_duration}"
play_head_seconds="$( timestamp_to_sec "${play_head}" )"
play_head_milliseconds="$( timestamp_to_millisec "${play_head}" )"
}
#################################################
function get_movie_duration() {
movie_duration="$( mediainfo --full --Output=JSON "${this_movie_file}" | jq --raw-output '.media.track | .[] | select(."@type"=="Audio") | .Duration_String3' )"
movie_duration_seconds="$( timestamp_to_sec "${movie_duration}" )"
movie_duration_milliseconds="$( timestamp_to_millisec "${movie_duration}" )"
}
#################################################
function check_movie() {
check_variable this_movie_file
if [ ! -s "${this_movie_file}" ]
then
echo_error "The \"this_movie_file\" file is missing."
fi
if [ "$( file --brief --mime-type "${this_movie_file}" | grep --count --perl-regexp 'video/mp4|video/x-matroska' )" -ne "1" ]
then
echo_error "The \"this_movie_file\" variable has not a valid \"video/mp4\" or \"video/x-matroska\" mime type."
fi
get_movie_duration
check_variable movie_duration
}
#################################################
function check_srt() {
check_variable this_srt_file movie_duration
if [ ! -s "${this_srt_file}" ]
then
echo_debug "No srt found trying: ffmpeg -y -hide_banner -loglevel error -txt_format text -i \"${this_movie_file}\" \"${this_srt_file}\""
ffmpeg -y -hide_banner -loglevel error -txt_format text -i "${this_movie_file}" "${this_srt_file}"
check_srt this_srt_file
fi
if [ "$( file --brief --mime-type "${this_srt_file}" | grep --count 'application/x-subrip' )" -ne "1" ]
then
echo_error "The \"this_srt_file\" variable has not a valid \"application/json\" mime type."
fi
cp "${this_srt_file}" "${this_srt_temp_file}" 1>&2
if [ ! -s "${this_srt_temp_file}" ]
then
echo_error "The temp file is missing \"${this_srt_temp_file}\".~"
fi
if [ "$( file "${this_srt_temp_file}" | grep --count 'CRLF' )" -eq "1" ]
then
dos2unix "${this_srt_temp_file}" 1>&2
fi
python3 -c "from bs4 import BeautifulSoup; print(BeautifulSoup(open('${this_srt_temp_file}', 'r').read(), 'html.parser').get_text())" | sponge "${this_srt_temp_file}"
if [ "$( grep -c "⋄⋄⋄ Fin ⋄⋄⋄" "${this_srt_temp_file}" )" -eq "0" ]
then
last_srt_index="$( tail "${this_srt_temp_file}" | grep --perl-regexp '^[0-9]+$' | tail -1 )"
echo "" >> "${this_srt_temp_file}"
echo $(( ${last_srt_index} + 1 )) >> "${this_srt_temp_file}"
echo "$( \date --date="${movie_duration} today - 2 seconds" +%H:%M:%S,000 ) --> $( \date --date="${movie_duration} today - 1 seconds" +%H:%M:%S,000 )" >> "${this_srt_temp_file}"
echo "The End." >> "${this_srt_temp_file}"
echo "" >> "${this_srt_temp_file}"
echo $(( ${last_srt_index} + 2 )) >> "${this_srt_temp_file}"
echo "$( \date --date="${movie_duration} today - 1 seconds" +%H:%M:%S,000 ) --> $( \date --date="${movie_duration} today" +%H:%M:%S,000 )" >> "${this_srt_temp_file}"
echo "⋄⋄⋄ Fin ⋄⋄⋄" >> "${this_srt_temp_file}"
fi
}
#################################################
function check_mp3() {
if [ ! -s "${1}" ]
then
echo_error "The audio file \"${1}\" is missing."
fi
if [ "$( file --brief --mime-type "${1}" | grep --count 'audio/mpeg' )" -ne "1" ]
then
echo_error "The file \"${1}\" has not a valid \"audio/mpeg\" mime type."
fi
}
#################################################
function check_wav() {
if [ ! -s "${1}" ]
then
echo_error "The audio file \"${1}\" is missing."
fi
if [ "$( file --brief --mime-type "${1}" | grep --count 'audio/x-wav' )" -ne "1" ]
then
echo_error "The file \"${1}\" has not a valid \"audio/x-wav\" mime type."
fi
}
#################################################
function fill_silence() {
# ffmpeg -y -hide_banner -loglevel erroroptions
# -f fmt (input/output) Force input or output file format.
# -i url (input) input file url
# -t duration When used as an output option (before an output url), stop writing the output after its duration reaches duration.
# -q:a Set the audio quality (codec-specific, VBR). This is an alias for
subtitle_start="${1}"
if [ ! -s "${this_srt_wav_file}" ]
then
echo_debug "Creating the audio track \"${this_srt_wav_file}\".~"
ffmpeg -y -hide_banner -loglevel error -f lavfi -i anullsrc=r=22050:cl=mono -t ${subtitle_start} -q:a 9 -acodec pcm_s16le "${this_srt_wav_file}" 1>&2
else
subtitle_start_millisec="$( timestamp_to_millisec "${subtitle_start}" )"
subtitle_start_sec="$( timestamp_to_sec "${subtitle_start}" )"
if [ "${play_head_milliseconds}" -lt "${subtitle_start_millisec}" ]
then
silence_to_add="$( echo "${subtitle_start_sec} ${play_head_seconds}" | awk '{ printf ($1 - $2), $0}' )"
echo_debug "Adding \"${silence_to_add}\" seconds to the audio track \"${this_srt_wav_file}\".~"
ffmpeg -y -hide_banner -loglevel error -f lavfi -i anullsrc=r=22050:cl=mono -t "${silence_to_add}" -q:a 9 -acodec pcm_s16le "${silence_wav}" 1>&2
if [ ${?} -ne "0" ]
then
echo_debug "ffmpeg -y -hide_banner -loglevel error -f lavfi -i anullsrc=r=22050:cl=mono -t \"${silence_to_add}\" -q:a 9 -acodec pcm_s16le \"${silence_wav}\"" 1>&2
fi
sox -V2 "${this_srt_wav_file}" "${silence_wav}" "${this_srt_wav_file%.*}_combined.wav"
mv "${this_srt_wav_file%.*}_combined.wav" "${this_srt_wav_file}" 1>&2
rm "${silence_wav}" 1>&2
else
echo_debug "There is a overlap at \"${subtitle_start}\".~"
fi
fi
check_wav "${this_srt_wav_file}"
}
#################################################
function segment_to_speech() {
this_index="${1}"
this_in="${2}"
this_out="${3}"
this_segment_text="${4}"
this_in_sec="$( timestamp_to_sec "${this_in}" )"
this_out_sec="$( timestamp_to_sec "${this_out}" )"
this_in_millisec="$( timestamp_to_millisec "${this_in}" )"
this_out_millisec="$( timestamp_to_millisec "${this_out}" )"
if [ "${this_out_millisec}" -lt "${this_in_millisec}" ]
then
echo_error "The timing on segment ${this_index} is incorrect, as the end \"${this_out}\" cannot be before the start \"${this_in}\".~"
fi
if [ "${play_head_milliseconds}" -lt "${this_in_millisec}" ]
then
echo_debug "Adding space as the playhead \"${play_head_milliseconds}\" is behind the subtitles \"${this_in_millisec}\""
fill_silence "${this_in}"
#TODO calculate difference, Pass to new function which will create that lenght of silence and add to it.
fi
# this_segment_duration_sec="$( awk "BEGIN{print ${this_out_sec}-${this_in_sec}}" )"
# this_segment_duration_millisec="$( printf '%.*f\n' 0 $( echo "${this_segment_duration_sec} * 1000" | bc --mathlib ) )"
echo "${this_segment_text}" | "${piper_bin}" --model "${piper_voice}" --sentence_silence 0 --output_file "${this_srt_wav_file_next_line}" > /dev/null 2>&1
# check_wav "${this_srt_wav_file_next_line}"
sox -V2 "${this_srt_wav_file}" "${this_srt_wav_file_next_line}" "${this_srt_wav_file%.*}_combined.wav"
# check_wav "${this_srt_wav_file%.*}_combined.wav"
mv "${this_srt_wav_file%.*}_combined.wav" "${this_srt_wav_file}" 1>&2
update_playhead
rm "${this_srt_wav_file_next_line}"
}
#################################################
function create_audio() {
first_subtitle_time_stamp="$( head "${this_srt_temp_file}" | grep --perl-regexp ' --> ' | head -1 | awk -F ' --> ' '{print $1}' | sed 's/,/./g' )"
check_variable first_subtitle_time_stamp
fill_silence "${first_subtitle_time_stamp}"
padding_zero="$( echo $(( $( tail "${this_srt_temp_file}" | grep --perl-regexp '^[0-9]+$' | tail -1 ) + 1 )) | wc --chars )"
cat "${this_srt_temp_file}" | while read this_line
do
if [ "$( echo "${this_line}" | grep --count --perl-regexp '^$' )" -eq "1" ]
then
continue # Ignore Blank Lines
fi
if [ "$( echo "${this_line}" | grep --count --perl-regexp '^[0-9]+$' )" -eq "1" ]
then
# Entering a new segment
# If there are no variables set then this is the first segment
if [ ! -z "${segment_start}" ]
then
segment_index="$(printf %0${padding_zero}d $(( ${this_line} - 1 )) )"
echo_debug "Generating speech for segment ${segment_index}: \"${segment_text}\""
segment_to_speech "${segment_index}" "${segment_start}" "${segment_end}" "${segment_text}"
fi
# Now reset the variables
segment_start=""
segment_end=""
segment_text=""
update_playhead
continue # Index line
fi
if [ "$( echo "${this_line}" | grep --count ' --> ' )" -eq "1" ]
then
segment_start="$( echo "${this_line}" | awk -F ' --> ' '{print $1}' | sed 's/,/./g' )"
segment_end="$( echo "${this_line}" | awk -F ' --> ' '{print $2}' | sed 's/,/./g' )"
continue
fi
# Combine multi line
segment_text="${segment_text} ${this_line}"
done
}
#################################################
# Main
for this_movie_file in $@
do
echo "Processing \"${this_movie_file}\""
check_movie this_movie_file
this_movie_file_voice_over="${this_movie_file%.*}_voice_over.mkv"
this_movie_original_mp3_file=".~${this_movie_file%.*}_original.mp3"
this_movie_new_mp3_file=".~${this_movie_file%.*}_mixed.mp3"
this_srt_file="${this_movie_file%.*}.srt"
this_srt_temp_file=".~${this_srt_file%.*}_temp.srt"
check_srt this_srt_file
this_srt_wav_file=".~${this_srt_file%.*}_srt.wav"
this_srt_wav_file_next_line="${this_srt_temp_file%.*}_next_line.wav"
silence_wav=".~silence.wav"
play_head="00:00:00.000"
play_head_seconds="0"
play_head_milliseconds="0"
if [ ! -e "${this_srt_wav_file}" ]
then
echo_info "Creating the new media"
create_audio
fi
echo ""
echo_info "Extracting the original sound track from \"${this_movie_file}\" to \"${this_movie_original_mp3_file}\""
ffmpeg -y -hide_banner -loglevel error -txt_format text -i "${this_movie_file}" "${this_movie_original_mp3_file}"
if [ "${source_volume}" != "0" ]
then
echo_info "Changing volume of movie \"${this_movie_file}\" to \"${this_movie_original_mp3_file}\""
sox -v ${source_volume} "${this_movie_original_mp3_file}" ".~${this_movie_original_mp3_file}"
mv -v ".~${this_movie_original_mp3_file}" "${this_movie_original_mp3_file}"
fi
if [ "${srt_volume}" != "0" ]
then
echo_info "Changing volume of subtitle audio \"${this_movie_file}\" to \"${this_movie_original_mp3_file}\""
sox -v ${srt_volume} "${this_srt_wav_file}" ".~${this_srt_wav_file}"
mv -v ".~${this_srt_wav_file}" "${this_srt_wav_file}"
fi
echo_info "Combining \"${this_movie_original_mp3_file}\" and \"${this_srt_wav_file}\" into a new track \"${this_movie_new_mp3_file}\""
ffmpeg -y -hide_banner -loglevel error -txt_format text -i "${this_movie_original_mp3_file}" -i "${this_srt_wav_file}" -filter_complex "[0:a][1:a]amerge=inputs=2[a]" -map "[a]" -ac 2 "${this_movie_new_mp3_file}"
echo_info "Adding \"${this_movie_new_mp3_file}\" to \"${this_movie_file}\" to give \"${this_movie_file_voice_over}\""
ffmpeg -y -hide_banner -loglevel error -txt_format text -i "${this_movie_file}" -i "${this_movie_new_mp3_file}" -map 0 -map 1:a -c:v copy "${this_movie_file_voice_over}"
if [ "${debug}" -eq "0" ]
then
rm "${this_movie_original_mp3_file}" 1>&2
rm "${this_srt_temp_file}" 1>&2
rm "${this_srt_wav_file}" 1>&2
rm "${this_movie_new_mp3_file}" 1>&2
fi
cp -v "${this_srt_file}" "${this_srt_file%.*}_voice_over.srt"
echo_info "Finished generating \"${this_movie_file_voice_over}\""
done