diff --git a/fhem/CHANGED b/fhem/CHANGED index d4d17f74d..e923a29eb 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,7 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - bugfix: 98_Text2Speech: - playing mp3files directly, eg: :ring.mp3: + - playing any mp3file only text - feature: FB_CALLMONITOR: new reading "direction" to differentiate between incoming and outgoing call. - feature: FB_CALLMONITOR: all informational readings about a call will be diff --git a/fhem/FHEM/98_Text2Speech.pm b/fhem/FHEM/98_Text2Speech.pm index 846a0b7f2..47de77fde 100644 --- a/fhem/FHEM/98_Text2Speech.pm +++ b/fhem/FHEM/98_Text2Speech.pm @@ -64,7 +64,7 @@ sub Text2Speech_Initialize($) " TTS_SentenceAppendix". " TTS_FileMapping". " TTS_FileTemplateDir". - " TTS_VolumeAdjust". + " TTS_VolumeAdjust". " ".$readingFnAttributes; } @@ -183,6 +183,7 @@ sub Text2Speech_Attr(@) { } } elsif ($a[2] eq "TTS_FileMapping") { + #Bsp: silence:silence.mp3 pling:mypling,mp3 #ueberpruefen, ob mp3 Template existiert my @FileTpl = split(" ", $TTS_FileMapping); for(my $j=0; $j<(@FileTpl); $j++) { @@ -338,6 +339,7 @@ sub Text2Speech_Set($@) ##################################### sub Text2Speech_PrepareSpeech($$) { my ($hash, $t) = @_; + my $me = $hash->{NAME}; my $TTS_Ressource = AttrVal($hash->{NAME}, "TTS_Ressource", "Google"); my $TTS_Delemiter = AttrVal($hash->{NAME}, "TTS_Delemiter", undef); @@ -364,6 +366,7 @@ sub Text2Speech_PrepareSpeech($$) { if($TTS_Ressource eq "Google") { my @text; + # ersetze Sonderzeichen die Google nicht auflösen kann $t =~ s/ä/ae/g; $t =~ s/ö/oe/g; $t =~ s/ü/ue/g; @@ -372,15 +375,32 @@ sub Text2Speech_PrepareSpeech($$) { $t =~ s/Ü/Ue/g; $t =~ s/ß/ss/g; - @text = $hash->{helper}{Text2Speech} if($hash->{helper}{Text2Speech}[0]); + @text = $hash->{helper}{Text2Speech} if($hash->{helper}{Text2Speech}[0]); #vorhandene Queue, neuen Sprachbaustein hinten anfuegen push(@text, $t); + # hole alle Filetemplates my @FileTpl = split(" ", $TTS_FileTpl); my @FileTplPc; - for(my $i=0; $i<(@FileTpl); $i++) { - #splitte bei jedem Template auf - @FileTplPc = split(/:/, $FileTpl[$i]); - @text = Text2Speech_SplitString(\@text, 100, ":".$FileTplPc[0].":", 1, "as"); # splitte bei bspw: :ring: + + # bei Angabe direkter MP3-Files wird hier ein temporäres Template vergeben + for(my $i=0; $i<(@text); $i++) { + @FileTplPc = ($text[$i] =~ /:([^:]+):/g); + for(my $j=0; $j<(@FileTplPc); $j++) { + my $tpl = "FileTpl_".time()."_#".$i; #eindeutige Templatedefinition schaffen + Log3 $hash, 4, "$me: Angabe einer direkten MP3-Datei gefunden: $FileTplPc[$i] => $tpl"; + push(@FileTpl, $tpl.":".$FileTplPc[$j]); #zb: FileTpl_123645875_#0:/ring.mp3 + $text[$i] =~ s/$FileTplPc[$j]/$tpl/g; # Ersetze die DateiDefinition gegen ein Template + } + } + + #iteriere durch die Sprachbausteine und splitte den Text bei den Filetemplates auf + for(my $i=0; $i<(@text); $i++) { + my $cutter = '#!#'; #eindeutigen Cutter als Delemiter bei den Filetemplates vergeben + @FileTplPc = ($text[$i] =~ /:([^:]+):/g); + for(my $j=0; $j<(@FileTplPc); $j++) { + $text[$i] =~ s/:$FileTplPc[$j]:/$cutter$FileTplPc[$j]$cutter/g; + } + @text = Text2Speech_SplitString(\@text, 0, $cutter, 1, ""); } @text = Text2Speech_SplitString(\@text, 100, $TTS_Delemiter, $TTS_ForceSplit, $TTS_AddDelemiter); @@ -389,14 +409,16 @@ sub Text2Speech_PrepareSpeech($$) { @text = Text2Speech_SplitString(\@text, 100, ";", 0, "al"); @text = Text2Speech_SplitString(\@text, 100, "und", 0, "af"); + Log3 $hash, 4, "$me: Auflistung der Textbausteine nach Aufbereitung:"; for(my $i=0; $i<(@text); $i++) { + # entferne führende und abschließende Leerzeichen aus jedem Textbaustein + $text[$i] =~ s/^\s+|\s+$//g; for(my $j=0; $j<(@FileTpl); $j++) { - # entferne führende und abschließende Leerzeichen aus jedem Textbaustein - $text[$i] =~ s/^\s+|\s+$//g; - # ersetze die FileTemplates + # ersetze die FileTemplates mit den echten MP3-Files @FileTplPc = split(/:/, $FileTpl[$j]); - $text[$i] = $TTS_FileTemplateDir ."/". $FileTplPc[1] if($text[$i] eq ":".$FileTplPc[0].":") + $text[$i] = $TTS_FileTemplateDir ."/". $FileTplPc[1] if($text[$i] eq $FileTplPc[0]); } + Log3 $hash, 4, "$me: $i => ".$text[$i]; } @{$hash->{helper}{Text2Speech}} = @text; @@ -412,7 +434,7 @@ sub Text2Speech_PrepareSpeech($$) { # param3: string: Delemiter # param4: int : 1 -> es wird am Delemiter gesplittet # 0 -> es wird nur gesplittet, wenn Stringlänge länger als MaxChar -# param5: string: Add Delemiter to String? [al|af|as|] (AddLast/AddFirst/AddSingle) +# param5: string: Add Delemiter to String? [al|af|] (AddLast/AddFirst) # # Splittet die Texte aus $hash->{helper}->{Text2Speech} anhand des # Delemiters, wenn die Stringlänge MaxChars übersteigt. @@ -437,7 +459,6 @@ sub Text2Speech_SplitString(@$$$$){ for(my $j=0; $j<(@b); $j++) { $b[$j] = $b[$j] . $Delemiter if($AddDelemiter eq "al"); # Am Satzende wieder hinzufügen. $b[$j+1] = $Delemiter . $b[$j+1] if(($AddDelemiter eq "af") && ($b[$j+1])); # Am Satzanfang des nächsten Satzes wieder hinzufügen. - push(@newText, $Delemiter) if($AddDelemiter eq "as" && $j>0); # AddSingle: füge Delemiter als EinzelSatz hinzu. Zb. bei FileTemplates push(@newText, $b[$j]); } } @@ -751,7 +772,9 @@ sub Text2Speech_WriteStats($$$$){ Set
+ + +Beispiele + =end html @@ -909,7 +941,9 @@ sub Text2Speech_WriteStats($$$$){ Set
+ + +Beispiele + + =end html_DE =cut