O vikendu jsem strávil jednu noc u monitoru, dalsi tri dny usilovne testoval a nova verze je zde. Rozdeluje text vytazeny ze schranky na casti, ktere zpracovava seriove, takze dusledkem je:
- Dovede prevest na hlas velice dlouhe useky textu (omezeni je jenom v kapacite schranky)
- Prehravani i extremne dlouhych textu se spusti za par vterin (na mem PC za 15 s pri jakekoliv delce textu)
S vychozim nastavenim jsem zatim naraz bez problemu nacetl 80 stran z e-booku v pdf, coz odpovidalo:
- 200 kB textu
- 180 000 znaku
- 40 souboru po 5 minutach
- 800 MB vysledneho zvukoveho zaznamu ve .wav
- Celkem 3 h 40 min prednesu
Temito parametry se da nastavit chovani skriptku:
l=5k # text bude delen na casti po "l" bytech. 1 kB textu ~ 915 znaků ~ 1 min zvuku ~ 4 MB zvukoveho zaznamu ve .wav formatu
n=5 # pocet pokusu o prevedeni textu na zvuk, nez to skript vzdaMensi "l" vyusti v hodne rychle zpracovani textu, ale zase vysledkem bude vice souboru (hur se v nich orientuje)
Vetsi "l" ma vetsi chybovost a neuskodi zvyseni parametru "n"
- Predem je treba nainstalovat: gawk, xsel, sox, cstocs, epos, libnotify-bin, VLC (teoreticky misto VLC i jiny prehravac, ale musi podporovat ovladani z prikazove radky)
- Kod ulozte pod libovolnym nazvem a nastavte mu spustitelny priznak (treba pres kontextove menu --> vlastnosti --> opravneni).
- Prvni spusteni skriptu nacte oznaceny text, druhe spusteni (pokud skript jeste bezi z minula) vyusti v zalohovani zvuku na plochu.
#!/bin/bash
# skript na cteni textu ze schranky pomoci TTS programu Epos hlasem violka
# potreba je: gawk, xsel, sox, cstocs, epos, VLC
# hlasy z http://epos.ufe.cz/download/inv/epos-tdp.tgz rozbalit do /usr/share/epos/inv/
# neni nutne,ale hodi se k zobrazovani bublinovych informaci: libnotify-bin
#TODO
# pro chybe zkontrolovat, elsi vse nainsatlovane; / instalacni skript ?
# zmensit i éíáščě kapitalky? - awk - Je potreba?
# function s vicesovnymi argumenty - zbytecne
# Plocha/Desktop atd. - unverzalni nazev
# backup mode - ukoncit VLC / nahradit jeho Playlist aktualnim umistenim souboru.
# backup mode - sloucit vysledek do jednoho souboru a enkodovat do ogg/mp3.
# pri ukonceni VLC v prubehu zpracovani prerusit dalsi zpracovavani textu.
echo '- Jde se na vec:-)'
echo '- Nastaveni promennych'
icon="/usr/share/icons/Humanity/devices/48/audio-input-microphone.svg" # ikona zobrazena v bublinove napovede
Jmeno=$(basename "$0") # nazev souboru skriptu
time=$(date +%d.%m_%T) # cas spusteni skriptu
l=5k # text bude delen na casti po "l" bytech. 1 kB textu ~ 915 znaků ~ 1 min zvuku ~ 4 MB zvukoveho zaznamu ve .wav formatu
n=5 # pocet pokusu o prevedeni textu na zvuk, nez to skript vzda
echo '- Nastaveni adresare pro docasne soubory'
mkdir -p /tmp/$Jmeno/
cd /tmp/$Jmeno
echo '- Zacatek logovani chyb'
#exec 1>log 2>&1
#exec 2>log
#exec 2>&1 | tee -a log
#exec 3>&1 > >(tee -a /dev/fd/3 | logger -p "$LOG_FACILITY" -t "$LOG_TOPIC_OUT" )
exec 2> >(tee -a log)
# Overime, zda skript byl minule ukoncen normalnim zpusobem
if [ -e /tmp/$Jmeno/$Jmeno.pid ]; then
echo '! Po predchozim spusteni nebyl skript korektne ukoncen'
# notify-send --urgency=low --icon=$icon "Naposledy nebyl skript korektně ukončen" "Pokusím se obnovit data z minula"
PID1=$(ps -p $(cat $Jmeno.pid)) # zjisti, zda je zjistene PID aktivni
# echo '- PID1 = '$PID1
PID2=$(echo $PID1 | gawk '{print $8}') # zjisti nazev programu s danym PID
# echo '- PID2 = '$PID2
PID3=$(echo $Jmeno | gawk '{print substr($(basename "$0"),1,15)}') # oreze na 15 znaku (protoze 'ps' mi vyhazuje nazev kdoviproc zkraceny)
# echo '- PID3 = '$PID3
if [ "$PID2" == "$PID3" ]; then # porovnanim overi, zda se pod danym PID neskryva jiz jiny program
echo ' ! Skript jiz jednou bezi s PID '$(cat $Jmeno.pid)', pred pokracovanim je nutno ho sestrelit'
kill -9 $(cat $Jmeno.pid)
echo ' - Prave se tak stalo, muzeme pokracovat'
fi
fi
# Skript stoprocentne bezi pouze jednou, nastala vhodna chvile se podepsat
echo $$ > $Jmeno.pid
# FUNKCE
# pauza pro odhmyzovaci ucely
function pauza(){
read -p “$*”
}
# osekani moc dlouhych pauz
function trim() {
echo '- Osekani zbytecne dlouhych mezer na konci kazde vety'
#sox said.wav $1.wav silence 0 -1 00:00:00.9 1%
sox said.wav $1 silence -l 1 0.1 1% -1 0.6 1%
# vysvetleni parametru modulu silence: -l = orezat mezery na jistou mez, 1 = oriznout pripadnou mezeru na zacatku zvukove stopy, 0.1 = minimalni delka zvuku, po niz se prestava orezavat, 1% = prah citlivost k sumu, -1 = odstranovat vsechny ostatni mezery az do konce, 0.6 = nastaveni delky ponechaneho useku ticha, 1% = prah citlivosti k sumu
}
# zpracovani hlasu 1 - nacteni
function Voice_read() {
nn=$n
echo '- Zacina synteza zvuku. Obcas to nevyjde napoprve, zkusime to nanejvys '$nn' krat.'
while [ $nn -gt 0 ]; do
echo '- Zbyva' $nn 'pokusu'
#let n=n-1
let nn=nn-1
echo '- Spusteni eposd'
eposd --voice violka
echo '- Vygenerovani wav'
cstocs utf8 il2 $1 | say-epos -w -
echo '- Pokus o syntezu ukoncen'
if [ -e said.wav ]; then
echo '- Surovy zvukovy zaznam je hotov'
nn=0;
fi
done;
}
# zpracovani hlasu 2 - zkraceni mezer a vlozeni do fronty k prehrani
function Voice_process() {
if [ -z $1 ]; then
echo '! Chybi vstupni parameter s nazvem souboru ke zpracovani, zkusime vychozi surovy zaznam.'
set 1=said.wav
fi
if [ ! -e $1 ]; then
echo '- Pokus o zpracovani '$1
trim $1
if [ -e $1 ]; then
echo '- Finalni zaznam '$1' je hotovy, nyni bude prehran'
vlc --started-from-file --playlist-enqueue "/tmp/$Jmeno/$1" & # Spust v rezimu jedine instance, pridej do playlistu a pokracuj
if [ -z "$pid_player" ]; then
pid_player=$!
echo '- Spusten prehravac s PID='$pid_player
fi
else
chyba=$(sed 2q log)
notify-send --urgency=low --icon=$icon "Text se nepodařilo převést na hlas" "$chyba"
cp -u log ~/Plocha/Precti_to_log_$time
notify-send --urgency=low --icon=$icon "Chyby byly zaznamenány do logu" "Právě byl zálohován na plochu pod jménem 'Precti_to_log_$time'"
fi
else
echo '! Nalezen z minula zvuk jiz uspesne upraveny do finalni podoby'
if [ ! "$backup" = "1" ]; then
echo ' - prepnuto do modu zalohovani'
backup=1
mkdir -p ~/Plocha/$Jmeno-$time/
notify-send --urgency=low --icon=$icon "Z minula zůstal zvukový záznam" "Zpracovaný záznam bude zálohován na Plochu do adresáře jménem '$Jmeno-$time'"
fi
fi
#pauza 'enter'
}
# zobrazeni bublinove zpravy
#function notify() {
# notify-send --urgency=$1 --icon=$icon $2 $3
#}
#HLAVNI CAST
if [ ! -e $Jmeno ]; then
echo '- Ziskani obsahu clipboardu'
xsel -o > $Jmeno # Pokud by nefungovalo, "Kocuro Pablo" by misto tohoto pouzil nasledujici radek
# xsel -o -b -t 1500 > $Jmeno
text=$(sed 2q $Jmeno) # oznameni, co se bude predcitat
notify-send --urgency=low --icon=$icon "Bude přečten text:" "$text"
else
echo '! Nalezen surovy text z minula'
text=$(sed 2q $Jmeno) # oznameni, co se bude predcitat
notify-send --urgency=low --icon=$icon "Bude obnoven text:" "$text"
fi
#pauza 'enter'
if [ ! -e $Jmeno.2 ]; then
echo '- Upravy textu pro srozumitelnejsi prednes'
# všechno malým, ať Violka nehláskuje?
#tr '[:upper:]' '[:lower:]' < $Jmeno > $Jmeno.1
awk '{print tolower($0)}' < $Jmeno > $Jmeno.1
sed -e :a -e '$!N;s/\n/. /;ta' -e 'P;D' $Jmeno.1 | sed 's/"/ /g;s/(/ /g;s/)/ /g;s/atd\./ a tak dále /g;s/mj\./ mimo jiné /g;s/apod\./ a podobně /g;s/aj\./ a jiné /g' > $Jmeno.2 # Nahrazeni koncu radku teckou, nahrada nekterych obvyklych zkratek celymi frazemi, odstraneni zavorek, uvozovek...
else
echo '! Nalezen upraveny text z minula'
fi
#pauza 'enter'
if [ ! -e $Jmeno.2.aa ]; then
echo '- Rozdeleni textu na casti po '$l' bytech'
split --bytes=$l $Jmeno.2 $Jmeno.2.
else
echo '! Nalezen rozdeleny text z minula'
fi
#pauza 'enter'
for f in $Jmeno.2.??; do
rm -rf /tmp/$Jmeno/said.wav
if [ ! -e $f.wav ]; then
Voice_read $f
fi
Voice_process $f.wav
if [ "$backup" = "1" ]; then
echo ' - Zaznam zkopirovan do ~/Plocha/'$Jmeno'-'$time'/'$f'.wav'
cp $f.wav ~/Plocha/$Jmeno-$time/$f.wav
fi
done
#pauza 'enter'
echo '- Ceka se na ukonceni prehravace s PID='$pid_player
wait $pid_player
echo '- Prehravac ukoncen'
echo '- Zacinaji uklidove prace'
echo '- Ukonceni zbylych procesu'
killall say-epos
#killall eposd
echo '- Odstraneni nepotrebnych souboru'
rm -rf /tmp/$Jmeno/
echo '- Tak zase nekdy...'
exit
Preji prijemny poslech.