System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

120
Gdańsk, wrzesień 2011 POLITECHNIKA GDAŃSKA Wydział Elektroniki Telekomunikacji i Informatyki Katedra Systemów Decyzyjnych Imię i nazwisko dyplomanta: Jan Klimczak Nr albumu: 112006 Forma i poziom studiów: niestacjonarne inżynierskie Kierunek studiów: Informatyka Praca dyplomowa inżynierska Temat pracy: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym Intelligent web navigation voice controlled system Kierujący pracą: prof. dr hab. inż. Zdzisław Kowalczuk Recenzent: Zakres pracy: Opracowanie głosowego systemu komunikacji oraz nawigacji po serwisie internetowym. Projekt zakłada wykonanie portalu testowego, systemu rozpoznawania i generowania mowy, mózgu systemu oraz postaci Awatara komunikującego się z użytkownikami oraz kierującego ich po serwisie. System ma być inteligentny w tym znaczeniu, iż Awatar nie będzie nas tylko słuchał, ale także będzie z nami w dialogu wyrażając się poprzez swoje emocje. Wykonanie projektu zakłada komunikację w języku angielskim. Nr raportu:

Transcript of System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

Page 1: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

Gdańsk, wrzesień 2011

POLITECHNIKA GDAŃSKA

Wydział Elektroniki

Telekomunikacji i Informatyki

Katedra Systemów Decyzyjnych

Imię i nazwisko dyplomanta: Jan Klimczak

Nr albumu: 112006

Forma i poziom studiów: niestacjonarne inżynierskie

Kierunek studiów: Informatyka

Praca dyplomowa inżynierska

Temat pracy: System inteligentnej nawigacji sterowanej głosem po serwisie

internetowym

Intelligent web navigation voice controlled system

Kierujący pracą: prof. dr hab. inż. Zdzisław Kowalczuk

Recenzent:

Zakres pracy: Opracowanie głosowego systemu komunikacji oraz nawigacji po serwisie

internetowym. Projekt zakłada wykonanie portalu testowego, systemu rozpoznawania

i generowania mowy, mózgu systemu oraz postaci Awatara komunikującego się

z użytkownikami oraz kierującego ich po serwisie. System ma być inteligentny w tym znaczeniu,

iż Awatar nie będzie nas tylko słuchał, ale także będzie z nami w dialogu wyrażając się poprzez

swoje emocje. Wykonanie projektu zakłada komunikację w języku angielskim.

Nr raportu:

Page 2: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym
Page 3: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

.......................................................

Imię i nazwisko dyplomanta

1.1.1. OŚWIADCZENIE

Oświadczam, że:

1) niniejszą pracę dyplomową wykonałem samodzielnie,

2) wszystkie informacje umieszczone w pracy uzyskane ze źródeł pisanych oraz informacje

ustne pochodzące od innych osób zostały udokumentowane w wykazie literatury

odpowiednimi odnośnikami.

.................................................

podpis dyplomanta

Page 4: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym
Page 5: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

Spis treści

1.1.1. OŚWIADCZENIE ..................................................................................................... 3

2. CEL PRACY ORAZ ROZPOZNANIE TECHNOLOGII .......................................................... 9

2.1. Wprowadzenie .................................................................................................................. 9

2.2. Założenia ogólne ............................................................................................................... 9

2.3. Przegląd istniejących technologii ................................................................................... 10

2.3.1. Systemy mowy ........................................................................................................ 10

2.3.2. Systemy Java Speech .............................................................................................. 10

2.3.3. Systemy Microsoft Speech ...................................................................................... 11

2.3.4. Systemy rozpoznawania mowy ............................................................................... 11

2.3.5. Systemy syntezy mowy ........................................................................................... 11

2.3.6. Przegląd istniejących systemów mowy ................................................................... 12

2.4. Serwery obsługujące protokół czasu rzeczywistego ...................................................... 14

2.5. Specyfikacja techniczna ................................................................................................. 15

2.6. Podsumowanie ................................................................................................................ 17

3. SPRECYZOWANIE WYMAGAŃ FUNKCJONALNYCH .................................................... 18

3.1. Wprowadzenie ................................................................................................................ 18

3.2. Przeznaczenie systemu ................................................................................................... 19

3.3. Funkcja ........................................................................................................................... 20

3.4. Podsumowanie ................................................................................................................ 21

4. ZASADA DZIAŁANIA ORAZ OPIS SYSTEMU .................................................................. 22

4.1. Wprowadzenie ................................................................................................................ 22

4.2. Architektura systemu ...................................................................................................... 22

4.3. Algorytm działania systemu ........................................................................................... 25

4.3.1. Przygotowanie systemu mowy ................................................................................ 25

4.3.2. Podłączenie klienta .................................................................................................. 26

4.3.3. Wygenerowanie mowy i jej odsłuchanie przez użytkownika ................................. 28

4.3.4. Rozpoznanie wydanej komendy głosowej .............................................................. 31

4.3.5. Mózg ........................................................................................................................ 32

4.3.6. Stan (emocje) ........................................................................................................... 32

4.4. Opis wyników ................................................................................................................. 33

4.5. Struktura oprogramowania ............................................................................................. 33

4.6. Podsumowanie ................................................................................................................ 34

5. REALIZACJA PRACY ............................................................................................................ 35

5.1. Wprowadzenie ................................................................................................................ 35

5.2. Testowanie platformy ..................................................................................................... 36

5.3. Omówienie sposobów rozwiązania problemów ............................................................. 36

Page 6: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

5.4. Podsumowanie................................................................................................................ 36

6. MOŻLIWOŚCI ROZWOJU SYSTEMU ................................................................................. 37

6.1. Wprowadzenie ................................................................................................................ 37

6.2. Rozwój klienta ................................................................................................................ 37

6.3. Rozwój systemu generowania mowy ............................................................................. 37

6.4. Rozwój systemu rozpoznawania mowy ......................................................................... 38

6.5. Rozwój postaci Awatara ................................................................................................. 38

6.6. Rozwój Mózgu ............................................................................................................... 38

6.7. Podsumowanie................................................................................................................ 38

7. PODSUMOWANIE ORAZ WNIOSKI Z PRACY .................................................................. 39

7.1. Podsumowanie oraz wnioski z pracy ............................................................................. 39

8. Dodatek 1. Skrótowy opis aplikacji .......................................................................................... 40

Tytuł dyplomu ........................................................................................................................... 40

Cel i przeznaczenie aplikacji ..................................................................................................... 40

Funkcjonalność ......................................................................................................................... 40

Opis realizowanych funkcji ................................................................................................... 40

Lista przykładowych zastosowań .......................................................................................... 41

Szczegółowe opisy działania aplikacji .................................................................................. 41

Architektura sprzętu .................................................................................................................. 42

Architektura oprogramowania .................................................................................................. 42

Opis metody wytwarzania aplikacji .......................................................................................... 44

Założenia i sformułowane zadania ....................................................................................... 45

Specyfikacje ........................................................................................................................... 45

Przygotowanie projektu ........................................................................................................ 45

Prototypowanie i implementacja .......................................................................................... 46

Testowanie ............................................................................................................................ 46

Ocena aplikacji oraz porównanie do innych rozwiązań ....................................................... 46

Wnioski i perspektywy dalszych prac .................................................................................... 46

9. Dodatek 2. Instrukcja dla użytkownika..................................................................................... 47

Przygotowanie do pracy z systemem .................................................................................... 47

Komendy sterujące pracą systemu ........................................................................................ 50

Lokalne ustawienia systemu ................................................................................................. 51

10. Dodatek 3. Instrukcja dla administratora ................................................................................ 52

System znaczników ............................................................................................................... 52

Mapa strony – sitemap .......................................................................................................... 54

Panel administracyjny ........................................................................................................... 54

Edycja generowanych odpowiedzi z systemu – Avatar Speech ........................................... 54

Generator treści systemu ....................................................................................................... 56

Page 7: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

Podgląd zawartości wygenerowanej bazy danych na bazie znaczników .............................. 57

Instrukcja wdrożenia systemu ............................................................................................... 57

11. Dodatek 4. Instrukcja dla programisty .................................................................................... 59

Budowa bazy danych ................................................................................................................ 59

Specyfikacja komunikacji z Mózgiem ...................................................................................... 60

Klient (ActionScript) – diagram klas .................................................................................... 61

Serwer Mowy (JavaEE)– diagram klas ................................................................................. 62

System znaczników. .................................................................................................................. 63

Dodanie postaci Awatara .......................................................................................................... 64

Konfiguracja systemu rozpoznawania i generowania mowy .................................................... 66

12. Dodatek 5. Listing kodów źródłowych głównych modułów .................................................. 67

Serwer mowy - SpeechServer ................................................................................................... 67

Klient - SpeechAvatar ............................................................................................................... 82

Model danych – SpeechModel .................................................................................................. 96

Mózg – BrainService ............................................................................................................... 100

Administrator – Administrator ................................................................................................ 104

Portal demonstarcyjny – PortalPG .......................................................................................... 111

13. Bibliografia ............................................................................................................................ 118

Page 8: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym
Page 9: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

2

2.CEL PRACY ORAZ ROZPOZNANIE TECHNOLOGII

2.1. Wprowadzenie

Niniejszy projekt ma za zadanie przegląd oraz scalenie istniejących rozwiązań,

które umożliwiają sterowanie portalem internetowym za pomocą głosu. Użytkownik otrzymuje

możliwość wydawania komend głosowych, a także zapytań odnośnie zawartości portalu. System

w odpowiedzi na komendy generuje komunikaty głosowe, które udzielą odpowiedzi na zadane

pytania. System także może przenosić użytkownika w inne miejsce portalu, o które prosimy

wydając komendy. Do interakcji użytkownika z portalem została utworzona postać

Inteligentnego Awatara (ang. Intelligent Avatar) [1], która umożliwia interakcję głosową

z systemem. Awatar jest wrażliwy na to co i jak mówimy, posiada swoje emocje,

które są uwidocznione podczas komunikacji.

Największym wyzwaniem stojącym przy realizacji projektu jest jego rozproszona praca,

która umożliwia niezależne sterowanie portalem dla wielu użytkowników jednocześnie poprzez

przeglądarkę internetową pracując w trybie on-line1 bez potrzeby zalogowania się do systemu

oraz zastosowany silnik sztucznej inteligencji2 i emocji

3 postaci Awatara, która pamięta

użytkownika i swój stan podczas przeglądania portalu.

2.2. Założenia ogólne

Ze względu na skomplikowanie języka polskiego, czego wynikiem jest praktyczny brak

implementacji tego języka dla technologii mowy (ang. Speech) (rozpoznawania i syntezy mowy)

[2] przedstawiony projekt został wykonany wyłącznie w języku angielskim, co nie wyklucza

dalszej jego rozbudowy o kolejne języki w przyszłości.

Zakłada się kontynuację pracy oraz dalszy rozwój platformy po ukończeniu projektu,

tak więc została zapewniona jego dalsza rozbudowa w sposób mało inwazyjny oraz praktycznie

niezależny dla każdego z modułów.

1 W trybie połączonym z Internetem.

2 Moduł nazwany „Mózgiem” niniejszej platformy.

3 Emocje identyfikują stan Awatara, który jest indywidualny dla każdego użytkownika portalu internetowego.

Page 10: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

1. Cel pracy oraz rozpoznanie technologii 10

2.3. Przegląd istniejących technologii

Sporządzony przegląd zawiera zestawienie istniejących technologii, które zostały uwzględnione

w fazie analizy wykonania projektu w obszarze rozpoznawania i generowania mowy.

2.3.1. Systemy mowy

Technologie rozpoznawania i syntezy mowy są od wielu lat rozwijane. Jednak semantyka

i struktura języka ludzkiego są na tyle skomplikowane, iż obecnie pomimo wielu lat rozwoju

nie ma żadnego istniejącego rozwiązania, które było by idealne lub bardzo zadowalające w tym

zakresie4. Wiele projektów zostało albo skomercjonalizowanych

5 i obecnie są dostępne

do zakupienia po wygórowanych cenach mimo, iż nie oferują fantastycznych rezultatów6,

albo zostało zaprzestanych w rozwoju z różnych powodów7.

Pod pojęciem systemu mowy (ang. Speech) wyróżniamy rozwiązania, które w mniejszym

lub większym stopniu umożliwiają rozpoznanie mowy (ang. Speech Recognition) [3]

lub/i jej syntezę, czyli wygenerowanie mowy na podstawie tekstu (ang. Speech Synthesis) [4]

za pośrednictwem własnych bibliotek oraz ich interfejsów API.

W tym obszarze możemy wyróżnić dwa czołowe rozwiązania: system mowy firmy

Microsoft (ang. Microsoft Speech) [5] oraz system mowy Java (ang. Java Speech) [6].

Praktycznie wszystkie obecne rozwiązania na nich bazują. Dzięki nim otrzymujemy dostęp

do framework'u, który umożliwia nam ich swobodne zastosowanie. Oczywiście na rynku istnieją

inne rozwiązania, ale zazwyczaj są one przeznaczone do ściśle określonych celów, a sama

ich licencja oraz brak dostępu do ich kodu uniemożliwia szersze ich wykorzystanie.

2.3.2. Systemy Java Speech

Java Speech API (ang. Java Speech Application Programming Interface, JSAPI) [7]

umożliwia wykorzystanie systemu mowy (ang. Speech) w między-platformowych aplikacjach

opierających się na technologii Java [8]. Dzięki zastosowaniu JSAPI otrzymujemy obsługę

komend i kontroli aplikacji poprzez rozpoznawanie mowy, system obsługujący gramatykę

(ang. Dictation System) [9] oraz syntezer mowy (ang. Speech Synthesis) dla rozwiązań

osobistych lub klasy korporacyjnej. Java Speech API obsługuje rozpoznawanie oraz syntezę

mowy.

Podstawową korzyścią korzystania z technologii Java jest to, iż otrzymujemy rozwiązanie

z otwartym dostępem do kodu (ang. Open Source) [10] oraz pełną zgodność między-

platformową (możliwość uruchomienia aplikacji na wielu platformach, w tym.: Microsoft,

Macintosh oraz Linux, ang. Cross-Platform) praktycznie bez wykonywania dodatkowej pracy

w tym zakresie.

Java Speech API zostało utworzone przez SUN Microsystems, obecnie Oracle

Corporation [11] przy współpracy z przodującymi na tamte czasy firmami8, które zajmowały się

systemami rozpoznawania mowy: Apple Computers, Inc. [12] , AT&T [13], Dragon System,

Inc. [14], IBM Corporation [15], Novell, Inc. [16], Philips [17], Texas Instruments [18].

4 W znaczeniu poprawności rozpoznawania i generowania mowy.

5 Rozwijanych przez firmy i odsprzedawanych po wygórowanych cenach.

6 Pomimo wielu lat rozwoju nie ma obecnie takiego systemu, który zastąpił by człowieka.

7 Większość rozwijanych projektów realizowana była przez uczelnie, jednak wiele z nich zostało zakończonych i nie

jest już rozwijana. 8 Dotyczy to lat 80-90 bieżącego stulecia.

Page 11: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

1. Cel pracy oraz rozpoznanie technologii 11

Pierwsza wersja Java Speech API została utworzona i zaakceptowana w 1998 roku. Od tego

też czasu nic się w niej nie zmieniło, nie była także modernizowana. Obecnie tylko różne

jej implementacje są rozwijane.

W 2001 roku rozpoczęto prace nad specyfikacją Java Speech API 2 (ang. JSAPI 2)

dostępną jako zgłoszenie JSR 113 (ang. Java Specification Request: JavaTM Speech API 2.0)

[19]. Pace nad nią trwały przez 8 lat. Jedną z głównych korzyści będzie zgodność

z zaproponowanym frameworkiem mowy dla przeglądarek internetowych przez W3C9

(ang. W3C Speech Interface Framework) [20] poprzez zastosowanie znaczników HTML

bezpośrednio na stronie internetowej oraz kompatybilność z interfejsem programowania systemu

mowy (ang. Speech Application Programming Interface) [21] wywodzącym się z Microsoft’u.

Jednak na JSAPI 2 musimy jeszcze troszkę poczekać ponieważ do dnia dzisiejszego

nie ma praktycznie żadnej działającej implementacji gotowej do wdrożenia i zastosowania.

2.3.3. Systemy Microsoft Speech

Microsoft posiada dobrze rozwinięty system mowy. Na jego stronie „Microsoft Tellme speech

innovation” [22] zostały dobrze opisane technologie przez niego wspierane. Technologie

te pozwalają na rozpoznawanie oraz generowanie mowy (ang. Speech Synthesis

and Recognition) w wielu językach. Dodatkowo za pomocą komend głosowych można sterować

systemem operacyjnym Windows oraz wybranymi aplikacjami. Jednak ograniczenia licencyjne

na wykorzystanie tego systemu mowy wykluczyła wykorzystanie tego rozwiązania

w wykonywanym projekcie.

2.3.4. Systemy rozpoznawania mowy

Od wielu dziesięcioleci ludzie próbują sterować urządzeniami za pomocą głosu. Ze względu

na skomplikowanie ludzkiej mowy pierwsze systemy pozwalały wyłącznie na rozpoznawanie

cyfr. W 1952 roku Bell Laboratories [23] zaprojektował system „Audrey”, który rozpoznawał

cyfry. Dziesięć lat później IBM zaprezentował swoją maszynę „Shoebox” [24],

która rozpoznawała 16 słów w języku angielskim. Następnie w latach 70 bieżącego wieku

powstały pierwsze systemy pozwalające rozpoznać tysiące słów, w latach 80 ta liczba

rozpoznawanych słów została już przekroczona. W latach 90 firma Dragon wprowadziła

do sprzedaży pierwszy produkt rozpoznawania mowy Dragon Dictate w cenie 9000$. Siedem lat

później produkt znacznie udoskonalony o nazwie Dragon NaturallySpeaking umożliwiający

płynne rozpoznawanie mowy o szybkości 100 słów na minutę został udostępniony w cenie

ok. 700$. Od 2000 roku systemy te szczycą się 80 % poprawnością rozpoznawania mowy. Także

od tego czasu możliwości wydawania komend głosowych zostały zaimplementowane

do systemów operacyjnych Microsoft Vista oraz MacOS oraz do wielu telefonów komórkowych

[25].

2.3.5. Systemy syntezy mowy

Synteza mowy polega na zamianie tekstu na mowę (ang. Text To Speech, TTS) [26]. Systemy

te ocenia się na podstawie poprawności i zrozumiałości wygenerowanej mowy, która powinna

być zrozumiała przez człowieka. Z roku na rok systemy te są bardziej dopracowane, jednak

na dzień dzisiejszy daleko jest im do doskonałości.

9 Dokument ten na dzień dzisiejszy znajduje się w wersji roboczej.

Page 12: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

1. Cel pracy oraz rozpoznanie technologii 12

2.3.6. Przegląd istniejących systemów mowy

Na rynku istnieje wiele systemów mowy (ang. Speech). Niektóre z nich lepiej sobie radzą,

a niektóre gorzej z rozpoznawaniem i syntezą mowy (ang. Speech Recognition and Synthesis).

Wiele z nich, szczególnie tych dopracowanych występuje w wersji komercyjnej, za którą trzeba

płacić (patrz tab. 1.1.). Większość z tych systemów przedstawia dość wysoki poziom

generowanej i rozpoznawanej mowy. Jednak ze względu na wysokie koszty nie zostały one

uwzględnione przy realizacji niniejszego projektu.

Tab. 2.1. Wybrane komercyjne systemy mowy.

l.p. nazwa cena rodzaj

1. Dragon Medical od 1200$ synteza i

rozpoznawanie mowy

2. Dragon NaturallySpeaking od 30$ za wersję pod

system operacyjny

synteza i

rozpoznawanie mowy

3. Cloud Garden, Talking Java SDK 500$ za serwer (z

ograniczeniami)

synteza mowy

4. Acapela box (Elan Speech Cube) 300€ za godzinę synteza mowy

5. Lumen Vox od 1500$ rozpoznawanie mowy

6. Ivona od 29€ synteza mowy

Dragon Medical [26] oferuje jedne z najbardziej zaawansowanych możliwości rozpoznawania

i syntezy głosu. Jest on przeznaczony dla lekarzy, którzy mogą za jego pośrednictwem szybko

tworzyć raporty medyczne lub przeszukiwać bazy danych. Jest to możliwe dzięki bardzo

dobremu systemowi rozpoznawania tekstu, pełnego zakresu słownictwa medycznego,

technicznego a także sprawności działania, pozwalającej na pracę niemal w czasie rzeczywistym

z systemem.

Drugim według mnie najlepszym systemem mowy jest Dragon NaturallySpeaking [27].

Jest on już przeznaczony dla przeciętnego użytkownika. Pozwala on m. in. na pisanie

oraz edycję dokumentów tekstowych, e-maili, uruchamianie aplikacji i plików, kontrolowanie

myszki oraz pomaga przy wielu innych czynnościach związanych z codzienną pracą

użytkownika z komputerem.

Cloud Garden, Talking Java SDK [28] jest już implementacją JSAPI, która korzysta

z SAPI Microsoftu, tak więc możliwe wykorzystanie jest wyłącznie pod platformą Windows.

Jak nazwa wskazuje jest to SDK (ang. Software Development Kit), które umożliwia praktycznie

dowolną implementację systemu.

Acapela box (Elan Speech Cube) [29] jest generatorem mowy, który pobiera opłaty

w zależności od czasu generacji mowy. Actapela udostępnia nam swój serwer, do którego się

łączymy, generujemy na nim mowę i odbieramy ją z powrotem. Za poprawność pracy całości

odpowiada firma, jednak tylko też ona może dalej rozwijać swój produkt.

Lumen Vox [30] jest firmą, która specjalizuje się w tworzeniu systemów generowania

mowy wysokiej jakości. Ich produkt Lumen Vox zdobył wiele nagród i wyróżnień w kategorii

rozpoznawania mowy. Jednak sama jego cena wskazuje na jego profesjonalne zastosowanie.

Na koniec pozostawiłem nasz rodowity produkt o bardzo wysokiej jakości Ivona [31],

który generuje mowę o bardzo wysokiej jakości. Ivona może poszczycić się generacją bardzo

wysokiej klasy głosu w języku polskim. Posiada ona wiele sposobów licencjonowania, tak więc

dostosowana jest zarówno pod przeciętnego klienta jak i korporacji.

Page 13: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

1. Cel pracy oraz rozpoznanie technologii 13

Większość rozwiązań typu Open Source10

przedstawia niestety tylko dobry lub zadawalający

poziom wygenerowanej mowy (patrz tab. 1.2). Wiele z nich korzysta z SAPI Microsoftu,

co dyskwalifikuje je do wykorzystania w projekcie. Tutaj praktycznie tylko dwa rozwiązania

wybijają się spośród dostępnych implementacji: Sphinx oraz FreeTTS. Charakteryzują się one

znacznie lepszą jakością generowanej i rozpoznawanej mowy oraz lepszą dokumentacją

i większą funkcjonalnością. Niewątpliwie w tym sektorze są liderami. Jednak w odróżnieniu

od komercyjnych systemów tego typu są to wyłącznie biblioteki, które wymagają utworzenia

własnej implementacji, gdzie często rozwiązania komercyjne oferują nam kompletny produkt.

Tab. 2.2. Wybrane systemy mowy typu Open Source.

l.p. Nazwa rodzaj

1. Sphinx-4 rozpoznawanie mowy

2. e-Speaking rozpoznawanie mowy (wymaga SAPI)

3. FreeTTS synteza mowy

4. Flite synteza mowy

5. Festival synteza mowy

6. FestVox synteza mowy

Sphinx-4 [32] jest najbardziej zaawansowanym systemem rozpoznawania mowy dostępnym jako

Open Source. Został on w całości napisany w języku Java poprzez współpracę Sphinx group

na Uniwersytecie Carnegie Mellon, Sun Microsystems Laboratories (obecnie Oracle), Mitsubishi

Electric Research Labs (MERL) oraz Hewlett Packard (HP) przy współpracy z Uniwersytetem

California w Santa Cruz (UCSC) i Massachusetts Institute of Technology (MIT).

System ten rozwijany jest od wielu lat oraz posiada możliwości rozpoznawania

pojedynczych komand jak i zarówno całych sekwencji zdań. Umożliwia on podpięcie wielu

modeli języka naturalnego11

w wielu różnych formatach. Posiada bogatą dokumentację

oraz wiele możliwości podpinania sygnału audio.

System e-Speaking [33] jest przykładem zastosowania SAPI Microsoftu, którego

wymaga do pracy. Posiada on ok. 100 wbudowanych komand do interakcji z systemem

operacyjnym. Obsługuje zarówno Windows 2000 jak i Windows XP. Integruje się z pakietem

Microsoft Office.

FreeTTS [34] z pośród wszystkich tu obecnych otwartych platform pod względem

generowania mowy bije konkurencję na głowę. Obsługuje wiele głosów, wraz z możliwością

ich dodawania. Częściowo wspiera standard JSAPI 1.0. Posiada dobrą dokumentację oraz wiele

interfejsów, które pozwalają na integrację tego systemu w innych modułach. Został on w całości

napisany w języku Java, jednak opiera się on na Flite [35] małym, szybkim, pracującym niemal

w czasie rzeczywistym generatorze mowy w całości napisanym w języku C na Uniwersytecie

Carnegie Mellon. Flite wywodzi się z systemu rozpoznawania mowy Festival [36] i projektu

FestVox [37], które nie są już tak funkcjonalne i zaawansowane jak FreeTTS, jednak odznaczają

się wyższą sprawnością.

Możemy wyróżnić tutaj trzeci typ systemów mowy. Mianowicie systemy on-line, do których

możemy podłączyć się za pośrednictwem interfejsów programistycznych (ang. Application

Programming Interface, API). Opierają się one najczęściej na systemach, a w zasadzie

bibliotekach opisanych w tab. 1.2. Są to proste rozwiązania, nie pamiętają stanu, nie posiadają

10

Dostępnych bez opłat z dostępem do kodu źródłowego. 11

Model określa listę słów i sentencji do rozpoznania.

Page 14: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

1. Cel pracy oraz rozpoznanie technologii 14

własnej logiki, tylko po prostu generują mowę na bazie podanego tekstu lub rozpoznają

wydawane komendy (patrz tab. 1.3). Najbardziej one pasują do tworzonego tutaj systemu, ale nie

mogą w nim jednak być użyte ze względu na swoje ograniczenia.

Tab. 2.3. Wybrane systemy mowy on-line.

l.p. nazwa rodzaj adres www

1. SpeechAPI rozpoznawanie

mowy

http://speechapi.com/

2. Ivona synteza mowy http://www.ivona.com/en/

3. AT&T Natural Voices® Text-

to-Speech Demo

synteza mowy http://www2.research.att.com/~ttsweb

/tts/demo.php

4. Festvox synteza mowy http://festvox.org/voicedemos.html

5. Festival Text-to-Speech Online

Demo

synteza mowy http://www.cstr.ed.ac.uk/projects/festi

val/onlinedemo.html

6. Demo Cepstral Voices synteza mowy http://cepstral.com/demos/

7. I Online Text to Speech

Synthesizer

synteza mowy http://codewelt.com/proj/speak

8. vozMe synteza mowy http://vozme.com/index.php?lang=en

SpeechAPI jest systemem on-line umożliwiającym użytkownikowi Internetu na wypowiadanie

komend oraz czytanie tekstu, który następnie jest rozpoznawany przez system. Internauta

ma do dyspozycji wyłącznie jedną stronę (właściwie kilka podstron) na której wypowiada

komendy. System ten jest interfejsem programistycznym (ang. API) do którego można podłączyć

się za pomocą różnych technologii, w tym: Java Script, Java12

, PHP, Python, Rubby, Web

Services oraz CLI (ang. Command Line Interface). Tak więc jest to system zamknięty, wysyłajcy

żądanie zawierające nagrany głos do rozpoznania, natomiast w odpowiedzi otrzymujemy

rozpoznaną komendę w formie tekstu. Poprzez obsługę wielu technologii wydaje się być

ciekawym rozwiązaniem na rynku. Niestety w 2011 roku prace nad tym systemem bardzo

zmalały także na chwilę obecną ciężko jest przewidzieć jego przyszłość. Także wykonane testy

podczas rozpoznania, które nierzadko kończyły się niepowodzeniem oraz brak udostępnienia

kodu źródłowego do wykonania potrzebnych poprawek wykluczyły ten system

do wykorzystania w tworzonym projekcie.

Ivona udostępniła raczej demonstracyjny panel zamiany tekstu w głos. Można w nim

podać dość krótki fragment, który zostanie zamieniony w głos. Jednak wyróżnia się ona sporą

listą dostępnych języków oraz bardzo wysoką jakością generowanego dźwięku.

Pozostałe systemy on-line zaprezentowane w tab. 1.3. posiadają bardzo ograniczone,

nazwałbym je podstawowe funkcje generowania mowy, jednak pozwalają one

na jej wygenerowanie w przeglądarce internetowej.

2.4. Serwery obsługujące protokół czasu rzeczywistego

Ponieważ wykonany system ma pracować w Internecie użytkownik nie powinien czekać zbyt

długo na reakcję ze strony systemu. W tym celu do wykonania systemu został wykorzystany

serwer obsługujący protokół czasu rzeczywistego (ang. Real-Time Messaging Protocol, RTMP)

[38] utworzony przez Adobe [39]. W naszym przypadku protokół ten przesyła dane audio w taki

sposób, że użytkownik nie musi czekać na wcześniejszy zapis lub zbuforowanie tych danych,

12

Na chwilę pisania tego rozdziału Java nie była jeszcze dostępna.

Page 15: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

1. Cel pracy oraz rozpoznanie technologii 15

tylko bezpośrednio może z tych danych fragment po fragmencie wykorzystać. Zastosowanie

tego protokołu znacznie przyśpieszyło interakcję użytkownika z systemem. Serwery te potocznie

są zwane albo serwerami strumieniowymi albo serwerami czasu rzeczywistego.

Jako, że protokół ten został utworzony przez firmę Adobe także serwery tej firmy

obecnie są najbardziej zaawansowane, dopracowane i stabilne, ale także i kosztują sporo.

W Adobe możemy wyróżnić serwer Flash Media Server [40] oraz LiveCycle DS. [41].

Oba prezentują najwyższą półkę oraz zapewniają wysoką stabilność i dokumentację.

Na drugim horyzoncie znajduje się serwer Wowza Media Server [42], który jest

praktycznie odpowiednikiem tego z Adobe.

Natomiast z wielu rozwiązań typu Open Source praktycznie tylko jedno się liczy,

mianowicie serwer Red5 [43], który wykonany został w technologii Java. Jest to taki mniejszy

brat Adobe Flash Media Server. Na początku 2011 roku został zaprezentowany kandydat

na wersję 1.0. Jednak od tego czasu serwer ten boryka się z wieloma różnymi problemami, które

uniemożliwiły wydanie jego wersji 1.0. Po dopracowaniu myślę, że będzie to solidny serwer,

jednak na dzień dzisiejszy posiada on bardzo skromną dokumentację i wiele elementów trzeba

samemu się domyślać jak je wykonać. Jednak najważniejszą cechą tego serwera jest fakt,

iż występuje on jako Open Source, jest dostępny bez opłat licencyjnych (natomiast jego

konkurenci są wysoko wyceniani) i co najważniejsze obsługuje protokół RTMP.

Serwery tego typu tworzą gniazda na odpowiednich portach (dla RTMP zwykle jest

to port 1935) poprzez które następuje transmisja danych w czasie rzeczywistym. Takie

połączenie w przypadku stron internetowych następuje właśnie poprzez protokół RTMP.

2.5. Specyfikacja techniczna

Ze względu na dalszy rozwój projektu przez uczelnię Politechniki Gdańskiej, Katedrę Systemów

Decyzyjnych cały system został oparty na standardach Open Source. Wyjątkiem są tutaj

platformy technologiczne, np. baza danych, która do zastosowań niniejszego projektu jest

dostępna i zgodna z warunkami licencyjnymi za darmo ze strony firmy Oracle lub server,

który można łatwo podmienić na inny Open Source gdyż, aplikacja została wykonana w pełni

pod standard Java Enterprise Edition.

Obsługiwane systemy operacyjne13

:

Linux Ubuntu 8.04 (server) x3214

Windows15

Macintosh16

.

Wykorzystane serwery:

Server aplikacji: Oracle Web Logic 11g

Server czasu rzeczywistego + java: Red5 RC 1.0.

Wykorzystane standardy Java [44, 45, 46, 47, 48]:

Java 5 EE

EJB 3.0 (ang. Enterprise JavaBean)

13

W kontekście uruchomienia platformy. Odnośnie końcowego użytkownika to może on działać na dowolnym

systemie operacyjnym obsługującym wtyczkę Adobe Flash 10. 14

Po odpowiednim dostrojeniu aplikacja powinna działać i w innych wersjach systemu. Mi osobiście nie udało się

uruchomić systemu pod Linux Fedora Core 14 x64 (problem był z biblioteką xuggler). 15

Potwierdzone w systemie Windows Vista x32. 16

Brak przeprowadzenia testów, ale po odpowiedniej konfiguracji powinno zadziałać.

Page 16: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

1. Cel pracy oraz rozpoznanie technologii 16

JPA (ang. Java Persistence API)

EAR (ang. Enterprise Archive)

JSF2 (ang. Java Server Faces 2)

Threads

Entity

Facelets.

Baza danych:

Oracle XE 11g.

Technologie RIA (ang. Rich Internet Application):

Adobe Flex 4.5

AS 3 (ang. Action Script 3)

NetStream

SO (ang. Shared Object)

MXML

Adobe Flash 10.

Technologie Internetowe:

xHTML (ang. Extensible HyperText Markup Language)

CSS (ang. Cascading Style Sheets)

JS (ang. JavaScript)

Sitemap (plik tekstowy).

Technologie rozproszone SOA (ang. Service Oriented Architecture):

SOAP 1.1 (ang. Simple Object Access Protocol)

XML (ang. Extensible Markup Language)

WSDL (ang. Web Services Description Language).

Technologie rozpoznawania mowy:

JSGF (ang. Java Speech Grammar Format).

Wykorzystane bibloteki [55]:

rozpoznanie mowy: Sphinx4

synteza mowy: FreeTTS

konwersja formatów audio: Xuggler

spring Source Framework

parser HTML: JSoup

system logowania: Apache Logger.

Metodologia wytwarzania oprogramowania [49, 50, 51, 52, 53, 54]:

UML 2.0 (ang. Unified Modeling Language)

wzorce projektowe

oprogramowanie obiektowe i rozproszone.

Page 17: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

1. Cel pracy oraz rozpoznanie technologii 17

2.6. Podsumowanie

Wykorzystując system mowy w aplikacjach otrzymujemy bardziej naturalny interfejs

użytkownika, który umożliwia łatwiejsze oraz bardziej przyjazne sterowanie aplikacją pomiędzy

użytkownikiem a systemem (w naszym przypadku portalem internetowym).

Możemy wyróżnić dwa główne obszary systemu mowy: rozpoznawanie mowy

(ang. Speech Recognition) oraz synteza mowy (ang. Speech Synthesis). Rozpoznawanie mowy

polega na tym iż komputer słucha co do niego mówimy a następnie konwertuje to na tekst.

Synteza mowy jest odwrotnym procesem, który polega na czytaniu tekstu poprzez

wygenerowany głos ludzki w aplikacji. Często proces ten określany jest jako technologia text-to-

speech (TTS).

Celem pracy jest opracowanie głosowego systemu komunikacji oraz nawigacji

po serwisie internetowym. Projekt zakłada wykonanie portalu testowego, systemu

rozpoznawania i generowania mowy, mózgu systemu oraz postaci Awatara komunikującego się

z użytkownikami oraz kierującego ich po serwisie. System ma być inteligentny w tym znaczeniu,

iż Awatar nie będzie nas tylko słuchał, ale także będzie z nami w dialogu. Ze względu

na skomplikowanie języka i dostępność bibliotek generowania i syntezy mowy wykonanie

projektu zakłada komunikację w języku angielskim.

Page 18: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

2

3.SPRECYZOWANIE WYMAGAŃ FUNKCJONALNYCH

3.1. Wprowadzenie

Wykonany system pozwala na komunikację oraz nawigację po utworzonym portalu

internetowym za pomocą głosu. W dialogu uczestniczy postać Awatara, która wyposażona

jest w stan, który docelowo w przyszłości będzie rozszerzony do postaci Dictobot’a [56]

za pośrednictwem odpowiedniej implementacji „Mózgu” systemu. Widok demonstracyjnego

systemu został zaprezentowany na rys 2.1.

Page 19: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

2. Sprecyzowanie wymagań funkcjonalnych 19

Rys. 2.1. Widok portalu demonstracyjnego.

3.2. Przeznaczenie systemu

Zaprezentowany system przeznaczony jest dla każdego użytkownika z dostępem do Internetu

ze znajomością języka angielskiego, gdyż obustronna komunikacja odbywa się właśnie w tym

języku.

Praca ta jest pracą rozpoznawczą, przygotowuje ona platformę do dalszego rozwoju

poprzez umożliwienie podziału dalszej pracy na kilka zespołów. Pod tym kątem cały system jest

tworzony i dlatego w pewnych warstwach charakteryzuje się pewnym nadmiarem,

który wydzielił moduły funkcjonalne systemu.

System pokazuje możliwości wykorzystania technologii rozpoznawania i generowania

mowy w połączeniu ze stanem Awatara, który pamięta użytkownika przez całą sesję w której

uczestniczymy w interakcji. Sam Awatar w tym wykonaniu jest częściowo autonomiczny,

jednak został on tak zaprojektowany aby w przyszłości stał się on całkowicie autonomiczny

Page 20: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

2. Sprecyzowanie wymagań funkcjonalnych 20

i sam podejmował już niektóre decyzje. Dodatkowo cała zabawa została udostępniona

dla użytkowników bez potrzeby zalogowania się do portalu.

3.3. Funkcja

Wyróżniamy kilka funkcjonalnych stref systemu, które dotyczą zwykłego użytkownika

oraz administratora. Z myślą o wdrożeniu wykonanego systemu do istniejącego portalu

internetowego samodzielnie on generuje i uaktualnia zawartość tego portalu. Ponieważ nie

chcemy także, aby wszystko co na nim się znajduje trafiało do naszego systemu, np. treść

znaczników opisujących tabele lub obrazki na stronie wyposażony on został w moduł filtrowania

zawartości portalu.

Chcemy także, aby cały system szybko działał, tak więc z tego powodu została dodana

baza danych która buforuje zawartość strony. W przeciwnym wypadku użytkownik

był by zmuszony oczekiwać na każdorazowe przeanalizowanie strony portalu i na tej bazie

otrzymywał by odpowiedź, co było by czasochłonne.

Nie chcemy, aby użytkownik musiał logować się do portalu. Powinien po prostu wejść

na stronę i zacząć z niej korzystać bez poświęcania dodatkowego czasu na logowanie się

lub konfigurowanie systemu.

Wymagania względem Awatara:

wyposażony jest w stan (emocje), który jest zapamiętywany i przywracany kiedy

ponownie użytkownik wraca do aplikacji

stan awatara jest normalizowany1 po stronie klienta, niezależnie, nie obciążając

dodatkowo łącza internetowego

wydanie każdej komendy głosowej związane jest z pobraniem stanu Awatara,

gdzie „Mózg” odpowiednio reaguje na ten stan

„Mózg” odpowiada za modyfikację stanu Awatara

stan Awatara został graficznie odzwierciedlony w postaci wykresu słupkowego,

gdzie każdy słupek odzwierciedla inną cechę2

postać Awatara jest animowana w zależności od aktualnego stanu.

Wymagania względem rozpoznawania mowy:

rozpoznawane komendy głosowe:

o „Good Morning” – Awatar wita się

o „Hello” – Awatar wita się

o „How are Yoy ?” - Awatar odpowiada nam jak się czuje i pyta się nas o to samo

o „What is Your Name ?”, „Name” – Awatar odpowiada nam jak się nazywa

o „Read page”, „Read” – Awatar czyta zawartość strony głównej

o „Home”, „People”, „Teachers”, „Specialization”,, „Teaching”, “Research”,

“Laboratories”, “Smart control idea”, – Komendy te przekierowują

do odpowiednich podstron portal demonstracyjnego

o „Next page”, „Next”, i „Previous Page”, „Previous” – Powodują przejście

do następnej i poprzedniej strony w portalu internetowym.

Wymagania względem generowania mowy:

możliwość edycji generowanych komunikatów za pomocą panelu administracyjnego

głos powinien być odpowiednio modulowany w zależności od aktualnego stanu Awatara

1 Wyposażony w mechanizm „zapominania”.

2 W niniejszej implementacji Awatar posiada 4 cechy, a każda z nich przyjmuje wartości od 0 do 200.

Page 21: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

2. Sprecyzowanie wymagań funkcjonalnych 21

Wymagania względem mózgu systemu:

autonomiczność, poprzez wykorzystanie technologii SOA umożliwiająca łatwą

jego podmianę nawet w czasie pracy systemu

generowanie odpowiedzi na bazie aktywnego kontekstu (stanu Awatara, adresu strony

żądania i komendy) zawierającej komunikat głosowy, zmianę stanu oraz ew. polecenie

przekierowania w inną część portalu demonstracyjnego.

Wymagania względem portalu demonstracyjnego:

zawiera angielską część informacji z Katedry Systemów Decyzyjnych

zawartość odzwierciedla fragment strony Katedry Systemów Decyzyjnych

zawiera minimum 5 podstron z różną zawartością.

Wymagania względem części administracyjnej:

wygenerowanie zawartości portalu na bazie odpowiednich znaczników

podgląd zawartości bazy danych

edycja komunikatów głosowych wydawanych przez Awatara.

3.4. Podsumowanie

Jest to wzorcowy projekt, który umożliwia sterowanie portalem internetowym za pomocą głosu.

Jego główną funkcją jest możliwość interakcji użytkownika za pomocą głosu poprzez

wydawanie komend głosowych oraz słuchanie i dialog z Awatarem.

Docelowo, jeżeli system ten odniesie sukces będzie on zaimplementowany na portalu

Uczelni, dlatego został on wyposażony we własny system znaczników i parser3,

który na podstawie znaczników przygotowuje odpowiednio bazę danych, która wykorzystywana

jest już przez „Mózg” systemu. W ten sposób została zagwarantowana możliwość

jego implementacji na portalu uczelni w przyszłości.

3 Parser analizuje zawartość stron portalu na postawie specjalnych znaczników. Szczytuje tylko wybraną zawartość

portalu w sposób odpowiednio przygotowany.

Page 22: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

3

4.ZASADA DZIAŁANIA ORAZ OPIS SYSTEMU

4.1. Wprowadzenie

Na cały system składa się wiele różnych technologii, które współpracują ze sobą. Ich połączenie

wymusiło utworzenie wielu warstw z wieloma współzależnościami. W celu obsłużenia wielu

użytkowników jednocześnie cały system w kluczowych elementach został podzielony na osobne

wątki, tak aby jeden użytkownik nie musiał czekać na zakończenie operacji związanej z obsługą

innych użytkowników. Całe rozwiązanie zostanie przedstawione w kolejnych podrozdziałach.

4.2. Architektura systemu

Ogólna architektura systemu została przedstawiona na rys. 3.1. Na rysunku możemy zauważyć,

iż cały system jest mocno rozproszony i dzieli się na poszczególne moduły,

które są odpowiedzialne za swoją część. W ten sposób cały projekt został podzielony na

mniejsze części, które mogą być niezależnie zarządzane.

Page 23: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

3. Zasada działania oraz opis systemu 23

Rys. 3.1. Ogólna architektura systemu.

Wydzielamy tu część kliencką oznaczoną kolorem błękitnym która jest środowiskiem pracy,

które w danym momencie posiada użytkownik systemu. Część kliencka odpowiada

za komunikację z serwerem, przydzieleniem uprawnień do mikrofonu i głośników,

wygenerowaniem unikalnego identyfikatora dla klienta, który następnie jest wykorzystywany

przez serwer do jego identyfikacji. Także w tej części użytkownik ma kontakt z systemem,

obserwuje wizualnie Awatara, wydaje komendy oraz słucha systemu. Tutaj także znajduje się

aktualna wizualizacja stanu Awatara w postaci wykresu słupkowego oraz konsola logów

z całego systemu, w której użytkownik monitoruje stan platformy w danym momencie.

Po stronie klienta przechowywany jest aktualny stan Awatara unikalny dla każdego

użytkownika, jednak jest on przypisany na stałe do danego komputera, a czasem przeglądarki.

Tak więc po powrocie do systemu w późniejszym czasie na danym komputerze następuje

odczytanie stanu Awatara, który na stałe zachowany jest na dysku użytkownika w postaci

obiektu współdzielonego (ang. Shared Object). Także tutaj użytkownik ma dostęp do ustawień,

które są przechowywane w obiekcie współdzielonym (ang. Shared Object). Ustawienia

te pozwalają na włączenie lub wyłączenie odświeżania stanu Awatara oraz włączenie/wyłączenie

wyświetlania konsoli logowania w portalu internetowym. Ustawienia te powalają zwiększyć

wydajność pracy aplikacji klienta. W ustawieniach można także zdefiniować adres serwera

mowy, który odpowiada za całą dalszą pracę systemu1.

Część serwerowa została oznaczona kolorem zielonym. Fizycznie część ta podzielona

jest na dwa serwery: serwer mowy jest serwerem czasu rzeczywistego, jest to serwer Red5 RC

1.0, który opiera się na platformie Apache Tomcat 6 działający na porcie 8080 dla protokołu

HTML oraz na porcie 1935 dla protokołu RTMP, drugim serwerem jest Oracle WebLogic 11g

1 W końcowej fazie pracy nad systemem opcja ta została domyślnie wyłączona.

Page 24: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

3. Zasada działania oraz opis systemu 24

na którym działa „Mózg” systemu, część administracyjna oraz portal demonstracyjny. Sewer

standardowo działa na porcie 7001 dla protokołu HTML.

Serwer mowy jest kluczowym elementem całego systemu, zwyczajowo nazywany

„serwerem” niniejszego systemu. To bezpośrednio z nim komunikuje się klient (w zasadzie

użytkownik systemu). Serwer ten wydziela dalszą interakcję z użytkownikiem. Na serwerze

tym zostały utworzone moduły generowania i syntezy mowy, klienta mózgu, obsługi i konwersji

danych audio przesyłanych w czasie rzeczywistym. Także w tym miejscu znajduje się lista słów

i komend rozpoznawalnych przez system w formacie JSGF (ang. Java Speech Grammar

Format). W tym miejscu mamy konfiguracje systemów rozpoznawania i syntezy mowy

w formatach zdefiniowanych przez specyfikacje bibliotek FreeTTS oraz Sphinx4.

Wykonany serwer mowy posiada architekturę wielo-wątkową2 (ang. Multithreading),

tak więc każde żądanie nowego klienta obsługiwane jest w nowym wątku. Konwersje formatów

danych audio są także wykonywane wielo wątkowo. Rozpoznanie komendy głosowej

z wygenerowaniem odpowiedzi również zachodzi w osobnym wątku.

Wiele operacji w serwerze zachodzi w oparciu o zdarzenia (ang. Events). Dotyczy

to obsługi komunikacji serwera z klientem podczas wymienianych komunikatów, konwersji

plików audio oraz obsługi wymiany danych audio w czasie rzeczywistym.

Serwer mowy wykorzystuje bibliotekę Xuggler do konwersji formatów audio. Biblioteka

ta jest zainstalowana na serwerze w systemie operacyjnym, natomiast sam system korzysta z niej

poprzez referencję. Standardowo serwer Red5 nagrywa dane audio w formacie .flv (ang. Flash

Video) które są następnie konwertowane do formatu .wav (ang. Wave form audio format)

poprzez napisany konwerter wykorzystujący bibliotekę Xuggler, który jest już zrozumiały

dla systemu rozpoznawania mowy. Natomiast generator mowy generuje mowę w formacie .wav,

który jest zbyt duży do przesłania do użytkownika, a także nie jest standardowo obsługiwany

przez serwer Red5 tak więc jest on konwertowany do formatu .mp3 (ang. MPEG-1/MPEG-2

Audio Layer 3), który jest już kilka do kilkunastu razy mniejszy oraz możliwy do odtworzenia

w czasie rzeczywistym przez klienta.

Mózg jest drugim serwerem, który odpowiada za logikę aplikacji. Komunikuje się

on bezpośrednio i wyłącznie z systemem mowy, od którego dostaje komendę użytkownika

w postaci tekstowej, identyfikator klienta oraz stan Awatara oraz zwraca akcję do wykonania

przez klienta wraz z komendą zmiany stanu Awatara lub wykonania przekierowania do innej

strony w portalu internetowym. Komunikacja systemu mowy następuje poprzez klienta Mózgu,

który komunikuje serwer mowy z „Mózgiem” poprzez protokół SOAP przy wykorzystaniu

dokumentu WSDL w technologii rozproszonej SOA. To rozwiązanie umożliwia łatwe

dodawanie nowych implementacji Mózgu oraz przełączanie ich w czasie działania aplikacji.

Mózg na podstawie otrzymanych danych i przetworzeniu posiadanych decyduje o wykonanej

interakcji w portalu internetowym za pośrednictwem serwera mowy, który dodatkowo może

wygenerować komunikaty głosowe dla użytkownika oraz przesłać komunikaty zmiany stanu

Awatara lub zadecydować o wykonaniu przekierowania użytkownika do innej strony na portalu

internetowym.

Oba serwery działają w technologii Java. Wyłącznie Mózg komunikuje się z bazą danych

poprzez fasadę, obiekt typu EJB Stateless Bean wykorzystując Framework JPA i zdefiniowane

źródło danych (ang. Data Source) po stronie serwera oraz mapowanie ORM (ang. Object-

relational maping) dzięki wykorzystaniu encji (ang. Entities). Zastosowaną bazą danych jest

2 Architektura wielo-wątkowa pozwala na równoległą realizację żądań wielu użytkowników równocześnie.

Najczęściej żądania są rozdzielane równomiernie na dostępne procesory i rdzenie dzięki czemu wykonywane

operacje powinny odbywać się szybciej (choć nie zawsze, jeżeli liczba wątków jest zbyt duża) i powinny pozwolić

na wykonanie danej operacji przez nowego użytkownika bez potrzeby oczekiwania na zakończenie wykonywanych

operacji przez innych użytkowników (jednak w praktyce nie zawsze tak jest, jest to zależne od wykonanej

implementacji).

Page 25: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

3. Zasada działania oraz opis systemu 25

baza danych Oracle XE 11g, która przechowuje wcześniej przygotowaną zawartość portalu

internetowego oraz treść komunikatów generowanych dla użytkownika.

Nad zapełnieniem bazy danych oraz przygotowaniem w niej danych odpowiada część

Administratora, która szczytuje zawartość portalu na podstawie jego mapy strony (ang. Sitemap)

oraz wcześniej przygotowanym znacznikom mowy (ang. Tags). Moduł ten jest całkowicie

niezależny od pozostałej części systemu, zapewnia on możliwość do podglądu wygenerowanych

danych, wygenerowaniu nowych danych oraz możliwość edycji generowanych komunikatów

dla użytkownika.

Klient łączy się z częścią serwerową za pośrednictwem protokołów RTMP i AMF (ang. Action

Message Format). Za pomocą protokołu RTMP przesyłany jest wyłącznie sygnał audio w czasie

rzeczywistym bez potrzeby przesyłania całego materiału w całości3. Natomiast protokół AMF

służy wyłącznie do wymiany komunikatów pomiędzy serwerem a klientem. Komunikaty

te zawierają informacje typu: stan Awatara, komendy tekstowe przesyłane do serwera w postaci

czytelnego tekstu, informacje zwrotne dla klienta kiedy czeka na niego wiadomość

do odsłuchania, komunikaty logów4 ze strony serwera itp. Klient-serwer komunikują się ze sobą

wyłącznie za pośrednictwem tych dwóch protokołów.

Serwer mowy komunikuje się z Mózgiem za pośrednictwem protokołu SOAP

w technologii rozproszonej SOA. Wyłącznie Mózg komunikuje się z bazą danych. W ten sposób

zostały jasno wyznaczone warstwy systemu.

4.3. Algorytm działania systemu

System posiada budowę modułową, tak więc możemy wyróżnić wiele algorytmów działania

systemu. W poniższym opisie została pominięta obsługa sytuacji awaryjnych, która została

zaimplementowana przez system. Jednak niniejszy rozdział skupia się na poprawnym

i przewidzianym funkcjonowaniu systemu. Opis ten nie obejmuje także opisu sytuacji logowania

wykonywanych operacji, ponieważ są one wykonywane we wszystkich istotnych częściach

systemu5.

4.3.1. Przygotowanie systemu mowy

Do poprawnego działania systemu wymagane jest przygotowanie i inicjalizacja serwera mowy.

Podczas startu serwera inicjalizowany jest system mowy i sam serwer czasu rzeczywistego.

Inicjalizacja serwera mowy polega na załadowaniu i wybraniu głosu (w naszym przypadku jest

to głos męski o nazwie „kevin16”, gdzie 16 oznacza 16kHz próbkowanie, czyli głos

o najwyższej jakości dostępny jako Open Soure), rezerwacji zasobów sprzętowych

wykorzystywanych podczas generowania mowy oraz samo przypisanie generatora do systemu

mowy. Kolejnym kluczowym elementem, który inicjalizowany jest podczas startu serwera jest

to inicjalizacja systemu rozpoznawania mowy. W pierwszej kolejności następuje

skonfigurowanie systemu poprzez załadowanie pliku konfiguracyjnego „config,xml”.

Plik ten przede wszystkim wczytuje listę słów w formacie JSGF (znajdująca się w pliku

„hello.gram”) i komend do rozpoznania przy uwzględnieniu danej rozdzielczości sygnału audio

(w naszym przypadku system został skonfigurowany do wykorzystania najwyższej dostpnej

3 Protokół RTMP w odróżnieniu od innych protokołów naprawdę przesyła dane w czasie rzeczywistym. Inne

protokoły najczęściej „udają”, że przesyłają materiał czasie rzeczywistym, lecz np. przesyłają go w partiach,

a nie bit po bicie jak dzieje się to w przypadku wykorzystania protokołu RTMP. 4 Komunikaty te informują klienta co dzieje się po stronie serwera. W przypadku jakichkolwiek problemów

po stronie serwera klient jest informowany o tym fakcie. 5 Obsługę błędów jak i system logów można prześledzić w załączonym kodzie źródłowym.

Page 26: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

3. Zasada działania oraz opis systemu 26

jakości sygnału audio), model akustyczny oraz inne ustawienia wykorzystywane podczas

rozpoznawania mowy. Następnie alokowane są zasoby systemowe niezbędne

do przeprowadzenia procesu rozpoznania mowy. W ten sposób system mowy zostaje

uruchomiony. Bez poprawnego wykonania inicjalizacji powyższych elementów system

nie zadziała w ogóle. Powyższe działania zostają wykonane jednorazowo.

4.3.2. Podłączenie klienta

Interakcja po stronie użytkownika następuje już w momencie otworzenia strony portalu

internetowego. W pierwszym momencie po stronie portalu zostaje wygenerowany unikalny

identyfikator użytkownika, który wykorzystywany jest w połączeniach klienta z serwerem.

Następnie zostaje załadowany klient w technologii Flex poprzez wtyczkę przeglądarki

internetowej Adobe Flash. Klient w momencie startu dokonuje załadowania postaci graficznej

Awatara wykonanej w technologii Adobe Flash oraz odczytuje identyfikator klienta

wygenerowany przez portal internetowy. Potem następuje inicjalizacja klienta, która uwzględnia

utworzenie specjalnej wersji systemu logowania aplikacji klienta, która wysyła logi aplikacji

dla użytkownika za pośrednictwem interfejsu zewnętrznego (ang. ExternalInterface)

za pośrednictwem języka Java Script oraz dzieli logi na podstawowe kategorie. Kolejno

utworzony jest lub wczytany współdzielony obiekt (ang. Shared Object) ustawień danego klienta

oraz otwierany lub nie w zależności od ustawień panel logów po stronie portalu internetowego

(dzięki tej operacji użytkownik ma możliwość na bieżąco śledzenia kolejnych zdarzeń, które

zachodzą w całym systemie oraz w przypadku wystąpienia błędu jest o tym informowany

na bieżąco). W następnej kolejności zostaje zarezerwowany mikrofon do wykorzystania

w systemie (tutaj następuje weryfikacja, czy użytkownik zezwolił aplikacji na wykorzystanie

mikrofonu przez aplikację). W tym momencie następuje wczytanie pozostałych ustawień klienta

zapisanych w obiekcie współdzielonym6. Po wczytaniu ustawień zostaje albo utworzony

standardowy stan Awatara lub zostaje on odtworzony z obiektu współdzielonego. Następnym

krokiem jest przygotowanie klienta do wymiany komunikatów z serwerem, w tym tych

wysyłanych i odbieranych. Po wykonaniu tych wszystkich czynności Awatar zostaje ożywiony,

tzn. zostaje on poddany normalizacji czyli powrotu do stanu normalnego7.

Po przygotowaniu klienta8 następuje połączenie klienta z serwerem. Obsługa połączenia

po stronie klienta następuję w trybie zdarzeniowym (ang. Events). Po wysłaniu żądania

połączenia z serwerem, serwer podejmuje próbę połączenia z klientem w osobnym wątku. Klient

wysyła swój identyfikator do serwera, który jest zapisany w atrybucie klienta po stronie serwera

do jego dalszej identyfikacji. W pierwszym momencie po stronie serwera następuje weryfikacja,

czy łączący się klient czasem nie jest już połączony z serwerem w innym żądaniu9 (np. w innej

zakładce przeglądarki lub w wyniku po prostu przejścia na inną stronę portalu internetowego).

Jeżeli klient jest już połączony to następuje jego scalenie „sesji” z obecnie zapisaną w liście

6 W ten sposób została zapewniona możliwość np. przesłania dodatkowych parametrów do systemu, np. naszego

imienia. Jednak ta wersja systemu nie korzysta z takiego rozwiązania. 7 Normalizacja czyli funkcja zapominania stanu Awatara ze względu na optymalizację wydajności całego systemu

została wykonana wyłącznie po stronie klienta. Zamiast obciążać klienta częstym przesyłaniem informacji o stanie

Awatara np. raz na sekundę, to czynność ta została całkowicie wykonana po stronie klienta. Jeżeli weźmiemy pod

uwagę pracę z wieloma klientami jest to znaczne odciążenie zarówno klienta jak i serwera odnośnie dodatkowej

obsługi każdego takiego żądania kosztem większego skomplikowania systemu. 8 Przedstawione przygotowanie klienta występuje po każdorazowym odwiedzeniu strony w portalu internetowym.

9 Tutaj sytuacja trochę się komplikuje ponieważ połączenie klient-serwer w prezentowanym systemie nie jest

połączeniem sesyjnym. O zapewnieniu trwałości połączenia system musi sam zdecydować, nie dzieje się

to automatycznie ze względu na to iż aplikacje Flex są bezstanowe w momencie przejścia do innej strony

internatowej lub jej przeładowania.

Page 27: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

3. Zasada działania oraz opis systemu 27

klientów aktualnie połączonych10

, w przeciwnym razie zostaje klient dodany do listy nowych

klientów aktualnie połączonych z systemem. W przypadku sukcesu połączenia i w zależności

od typu połączenia (nowe lub wznowione) w osobnym wątku zostaje wygenerowana wiadomość

powitalna dla klienta11

. Na koniec zostaje wysłana wiadomość powitalna dla klienta, która jest

wiadomością kontrolną czy funkcjonuje komunikacja dwustronna w obszarze klient-serwer.

Dopiero w tym momencie klient odbiera potwierdzenie połączenia z serwerem i ustawia

swój status połączenia na połączony12

. Jeszcze pozostało zestawienie połączenia gniazda (ang.

Socket), właściwie strumienia danych po protokole RTMP.

W ten sposób klient został połączony i przygotowany do dalszego użycia.

Przebieg algorytmu podłączenia klienta:

1. otworzenie strony internetowej

2. wygenerowanie unikalnego identyfikatora użytkownika

3. załadowanie klienta poprzez wtyczkę flash

4. wczytanie postaci graficznej awatara poprzez klienta

5. odczytanie wygenerowanego identyfikatora poprzez klienta

6. utworzenie systemu logowania po stronie klienta

7. wczytanie lub utworzenie obiektu SO z ustawieniami klienta

8. inicjalizacja mikrofonu jeżeli zezwolono

9. wczytanie ustawień z obiektu SO

10. wczytanie lub utworzenie stanu Awatara

11. przygotowanie komunikacji klient-serwer

12. ożywienie Awatara w proces normalizacji

13. połączenie klienta z serwerem wraz z wysłaniem identyfikatora klienta w nowym wątku

14. zapisanie identyfikatora klienta po stronie serwera

15. weryfikacja czy klient nie jest już połączony z serwerem

16. dodanie lub przekierowanie klienta do listy połączonych z serwerem

17. wygenerowanie wiadomości powitalnej dla klienta w nowym wątku

18. wysłanie wiadomości powitalnej do klienta z informacją, iż został on już połączony

19. serwer wysyła wiadomość do klienta, iż czeka na niego wiadomość do odsłuchania

20. zestawienie połączenia RTMP pomiędzy klientem i serwerem.

10

Połączenie klienta determinowane jest po długości czasu życia sesji po stronie portalu internetowego według

wygenerowanego identyfikatora klienta. 11

Algorytm generowania mowy został opisany w osobnym podrozdziale. 12

W rzeczywistości status connectionStatus otrzymuje wartość true.

Page 28: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

3. Zasada działania oraz opis systemu 28

Rys. 3.2. Wykorzystanie wątków podczas inicjalizacji klienta.

Rysunek 3.2 przedstawia sposób wykorzystania wątków podczas inicjalizacji klienta. P0 oznacza

klienta, T0 reprezentuje podłączenie klienta do serwera, każdy klient zostaje obsłużony

w osobnym wątku, następnie T1 oraz T2 przedstawiają wygenerowanie wiadomości powitalnej,

która generowana jest także w osobnych wątkach, aż w końcu wszystkie te komunikaty wracają

z powrotem do klientów.

4.3.3. Wygenerowanie mowy i jej odsłuchanie przez użytkownika

System umożliwia proste wygenerowanie mowy na podstawie przekazanego tekstu lub bardziej

zaawansowane przy wykorzystaniu obiektu złożonego zawierającego stan Awatara.

W zależności od implementacji Mózgu przy wykorzystaniu obiektu złożonego możemy

otrzymać inny wynik wygenerowanej mowy w zależności od aktualnego stanu Awatara a także

system może przekierować nas w inne miejsce w portalu internetowym. Przy wykorzystaniu

prostego tekstu zawsze otrzymamy wygenerowaną mowę do odsłuchania. Ze względu na to

iż obiekt złożony rozszerza wykorzystanie prostego tekstu podczas wygenerowania mowy,

w tym rozdziale tylko ten algorytm zostanie opisany. Schemat wygenerowania komendy

głosowej został przedstawiony na rys. 3.3.

Page 29: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

3. Zasada działania oraz opis systemu 29

Rys 3.3. Wygenerowanie odpowiedzi na podstawie komendy głosowej.

Na początku zostaje utworzony obiekt zapytania, który zawiera komendę tekstową

oraz stan Awatara13

. Komenda tekstowa jest tekstem, który ma posłużyć do wygenerowania

mowy. Poprzez klienta obiekt zapytania jest przekazany do Mózgu za pośrednictwem protokołu

SOAP. W samym mózgu zapytanie jest przetwarzane14

. W naszym systemie następuje

porównanie nadesłanej komendy głosowej czy jest ona rozpoznawana przez Mózg. W zależności

od rozpoznanej lub nie komendy następuje przygotowanie odpowiedzi zwrotnej, która zawiera

tekst odpowiedzi pobrany z bazy danych oraz wartości zmiany stanu Awatara w zależności

od kontekstu15

w wartościach względnych16

a także opcjonalnie informację o wymaganym

przekierowania użytkownika na inną stronę portalu internetowego.

Odpowiedź ta jest zwracana z Mózgu do serwera mowy, który na jej podstawie

przygotowuje obiekt odpowiedzi dla klienta, następnie odpowiedź ta przesyłana jest do klienta

i modyfikuje na tej podstawie stan Awatara lub przekierowuje użytkownika na inną stronę

w zależności czy to przekierowanie miało nastąpić, czy też nie.

Równolegle na podstawie wcześniej zapisanego identyfikatora klienta, który zgłosił

żądanie na wygenerowanie mowy rozpoczyna się proces generowania mowy. W tym miejscu

od razu na wstępie zostaje wygenerowany unikalny numer pliku globalny dla całego serwera

mowy, który będzie wykorzystany do zapisania wygenerowanej mowy poprzez wykorzystanie

13

Zwyczajowo stan Awatara jest bezpośrednio pobierany od klienta przed samym wysłaniem zapytania do Mózgu.

W celu pobrania odpowiedniego stanu Awatara klient jest wcześniej odpowiednio identyfikowany, zaś samo

pobranie stanu zostaje wykonane za pośrednictwem protokołu AMF. 14

W zależności od implementacji Mózgu wynik może być zupełnie odmienny. 15

Kontekst jest definiowany i pobierany przez Mózg systemu. 16

Są to wartości, które są dodawane do stanu Awatara (mogą być także wartościami ujemnymi).

Page 30: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

3. Zasada działania oraz opis systemu 30

własnej implementacji modułu zapisu wygenerowanej mowy do pliku. Z syntezatora mowy

zostaje pobrany odtwarzacz, który zostaje przekierowany do pliku. Zostaje wygenerowana

mowa, która zostaje zapisana do pliku .wav, który jeszcze nie nadaje się do przesłania do klienta.

W tym miejscu nowo wygenerowany plik zostaje przekonwertowany na podstawie

implementacji konwertera biblioteki Xlugger z formatu .wav do formatu .mp3. Konwersja

ta zawsze przebiega w nowym wątku. Konwerter sprawdza czy na podstawie

przekonwertowanego pliku ma nastąpić rozpoznanie komendy i wykonanie akcji17

. W przypadku

zwykłej konwersji do tej czynności nie dochodzi wcale. Jest ona zarezerwowana dla obsłużenia

komend głosowych wydanych bezpośrednio po stronie klienta.

Po wygenerowaniu pliku mowy i przekonwertowaniu go do formatu umożliwiającego

jego odtworzenie w czasie rzeczywistym zostaje wysłana komenda odtwórz wiadomość w raz

z nazwą pliku do odtworzenia dla klienta zgłaszającego prośbę o wygenerowanie mowy.

W tym momencie klient otrzymawszy taką wiadomość, sprawdza czy połączenie

z serwerem i gniazdem jest już gotowe. Jeżeli jest już gotowe to następuje odtworzenie

wygenerowanej mowy w czasie rzeczywistym. W przeciwnym wypadku zgłoszenie zostaje

zapisane po stronie klienta, który ponawia 5-cio krotnie próbę otworzenia oczekującej

wiadomości co 0,5s. Po tym czasie próba odtworzenia wiadomości zostaje zaniechana,

a klientowi zostaje przekazany komunikat o błędzie w konsoli logowania.

Przebieg algorytmu generowania mowy:

1. utworzenie obiektu zapytania zawierającego tekst mowy do wygenerowania oraz stan

awatara (stan pobierany jest od klienta tuż przed samym wysłaniem żądania do Mózgu)

2. przesłanie zapytania do Mózgu za pośrednictwem protokołu SOAP

3. rozpoznanie nadesłanej komendy

4. pobranie tekstu odpowiedzi z bazy danych

5. obliczenie wymaganej zmiany stanu Awatara

6. przygotowanie strony przekierowania o ile zajdzie taka potrzeba

7. wygenerowanie odpowiedzi zwrotnej

8. przekazanie odpowiedzi z Mózgu do serwera mowy

9. utworzenie komunikatu zwrotnego dla klienta

10. przesłanie komunikatu zwrotnego do klienta

11. zmiana stanu Awatara po stronie klienta

12. przekierowanie użytkownika na inną stronę o ile zajdzie taka potrzeba

13. wygenerowanie unikalnego w skali serwera mowy identyfikatora pliku

14. utworzenie pliku .wav zawierającego odpowiedź audio dla klienta

15. w nowym wątku następuje konwersja pliku .wav na plik .mp3

16. opcjonalnie następuje tu wykrycie komendy oraz wykonanie akcji na tej podstawie

17. wysłanie komendy odtwórz oczekującą wiadomość do klienta

18. klient weryfikuje czy podłączenie RTMP z serwerem jest już gotowe

19. następuje 5-cio krotna próba odtworzenia oczekującej wiadomości w czasie

rzeczywistym.

17

Jest to uniwersalne rozwiązanie pozwalające usprwanić proces dalszej analizy i obróbki uzyskanego materiału

audio. Rozpoznanie komendy i wykonanie akcji występuje wyłącznie w momencie, gdy komenda ta została

zgłoszona bezpośrednio ze strony klienta poprzez protokół czasu rzeczywistego RTMP. W innym wypadku nie jest

ona w ogóle wykorzystywana.

Page 31: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

3. Zasada działania oraz opis systemu 31

Rys. 3.4. Wykorzystanie wątków podczas generowania mowy.

Rysunek 3.4 przedstawia sposób wykorzystania wątków podczas generowania mowy.

P0 oznacza zgłoszenie pliku oczekującego na konwersję, T0 reprezentuje konwersję pliku .wav

na .mp3. Każdy plik zostaje obsłużony w osobnym wątku, następnie następuję przesłanie

odpowiedzi iż pliki zostały przekonwertowane dla swoich „zleceniodawców”.

4.3.4. Rozpoznanie wydanej komendy głosowej

Rozpoznanie komendy głosowej rozpoczyna się w momencie wciśnięcia i przytrzymania

przycisku „Speak” w kliencie przy postaci Awatara. W tym momencie następuje nagranie

materiału jeszcze audio/video na serwerze18

w czasie rzeczywistym pod wysłaną nazwą klienta.

Podczas tej operacji serwer przechwytuje materiał audio/video i zapisuje go na dysku komputera.

W momencie odpuszczenia przycisku przez użytkownika jest wysyłany komunikat o ukończeniu

nagrywania do serwera. Teraz w nowym wątku po stronie serwera następuje konwersja pliku .flv

do pliku .wav za pośrednictwem implementacji bibloteki Xuggler19

a następnie rozpoznanie

komendy i wykonanie akcji opisanej w poprzednim podrozdziale.

Przebieg algorytmu rozpoznania mowy:

1. rozpoczęcie procesu rozpoznania mowy następuje z chwilą wciśnięcia przycisku „Speak”

po stronie klienta

2. następuje nagrywanie materiału audio/video po stronie serwera w czasie rzeczywistym

3. odpuszczenie przycisku „Speak” po stronie klienta powoduje wysłanie komunikatu

do serwera o zakończeniu procesu nagrywania

18

Serwer Red5 umożliwia wyłącznie nagrywanie materiału audio/video w czasie rzeczywistym. 19

Operacja ta została opisana w rozdziale „Wygenerowanie mowy i jej odsłuchanie przez użytkownika”.

Page 32: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

3. Zasada działania oraz opis systemu 32

4. w nowym wątku rozpoczyna się konwersja formatu .flv do pliku .wav

5. teraz następuje rozpoznanie komendy z otrzymanego pliku .wav

6. na tej podstawie wysyłana jest wiadomość do Mózgu a następnie występują czynności

opisane w poprzednim podrozdziale.

Wykorzystanie wątków w tym procesie jest analogiczne jak przy procesie generowania mowy.

4.3.5. Mózg

System ten został wyposażony w bardzo prostą implementację Mózgu, która porównuje

otrzymane komendy do tych zapisanych we własnej pamięci i na tej podstawie wykonuje

przypisane operacje. Mózg otrzymuj kontekst danego użytkownika składający się z chwilowego

stanu (emocji) Awatara, aktualnej strony WWW, z której przyszło dane żądanie oraz

z komunikatu tekstowego. Na bazie kontekstu i rozpoznanej komendy z komunikatu tekstowego

generowana jest na sztywno odpowiedź, która zawiera pobraną z bazy danych komendę

głosową, polecenie i adres przekierowania użytkownika do innej strony internetowej oraz

zmianę stanu (emocji) Awatara. Zmiana stanu Awatara w tej implementacji Mózgu polega

na jego zmianie w losowej wartości zmiany w określonym zakresie20

.

4.3.6. Stan (emocje)

Awatar wyposażony jest w samoistną świadomość wyposażoną w mechanizm „zapominania”,

który działa wyłącznie po stronie klienta i doprowadza stan (emocje) do stanu

znormalizowanego. Stan Awatara przechowywany jest na komputerze klienta i zapamiętywany

jest nie tylko poprzez daną sesję użytkownika (które de facto nie wymaga chociażby

zalogowania się do systemu), ale pamiętany jest od czasu ostatnich odwiedzin portalu

internetowego. Pamięć ta opiera się na mechanizmie Shared Object platformy Adobe Flash,

który w uproszczeniu21

jest odpowiednikiem pliku ciasteczka (ang. cookie).

Na bazie aktualnego stanu Mózg jest w stanie wygenerować inną odpowiedź,

która spowoduje odmienne zachowanie się Awatara oraz zmieni modulację jego głosu22

.

Graficzna postać Awatara jest animowana23

na bazie stanu w sposób ciągły (patrz rys. 3.5),

natomiast komenda głosowa w całości uwzględnia stan z momentu jej wygenerowania.

Rys. 3.5. Animacja postaci Awatara w zależności od stanu (emocji).

20

Dzięki aktualnej implementacji możemy określić zachowania Awatara jako nieobliczalne. Jednak jest to tylko

i wyłącznie kwestią implementacji Mózgu. 21

Tak naprawdę Shared Object jest obiektem o wiele bardziej zaawansowanym niż ciasteczko. 22

Modulacja zawiera zmianę szybkości mówienia, częstotliwości oraz wysokości głosu. 23

Animacja uwzględnia powiększenie oraz pomniejszenie źrenic, zmianę kolorystyki twarzy oraz zmianę tępa

animacji mowy w momencie, gdy Awatar nam odpowiada.

Page 33: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

3. Zasada działania oraz opis systemu 33

4.4. Opis wyników

Pierwsze testy integralne całego systemu wykazały jego stabilną pracę. Jednak wykorzystane

biblioteki rozpoznawania i syntezy mowy, pomimo iż zostały wykorzystane ich najbardziej

dopracowane biblioteki w wersji Open Source pozostawiają jeszcze wiele do życzenia. Jakość

wygenerowanej mowy nie jest wysokiej jakości, a sam system rozpoznawania mowy

charakteryzuje się wysokim progiem błędów, przez co wydawane komendy są źle

interpretowane. Biblioteki te są stale rozwijane, jednak tempo ich rozwoju nie jest zbyt wielkie,

lecz gdy pojawią się ich lepsze odpowiedniki będzie można je podmienić w systemie.

4.5. Struktura oprogramowania

Tak jak zostało to już wcześniej wielokrotnie napisane cały system został wykonany jako zbiór

wielu modułów wymienionych w tab. 3.1. Każdy moduł jest niezależnym projektem. Wszystkie

kluczowe moduły posiadają oddzielne aplikacje testujące.

Tab. 3.1. Moduły systemu.

l.p. moduł technologia opis

1. Administrator Java, JSF, EJB, JSoup,

HTML, JAAS

część administracyjna

2. AdministratorTest Java, Junit testy jednostkowe

3. Avatar Flash, AS postać Awatara

4. BrainService Java, EJB, WSDL,

WSDL, Web-Service,

SOA

Mózg

5. BrainServiceClient Java, Web-Service,

SOA

klient Mózgu

6. BrainServiceClientTest Java, Junit testy jednostkowe

7. PortalPG Java, JSF, HTML, JS,

CSS

portal demonstracyjny

8. SpeechAvatar Flex, AS, MXML,

RTMP, AMF

klient

9. SpeechModel Java, JPA, EJB, Entity,

ORM

odwzorowanie bazy danych,

model danych oraz fasada

10. SpeechModelTest Java, Junit testy jednostkowe

11. SpeechServer Java, Spring, Injection,

RTMP, AMF

serwer mowy

12. SpeechServerTest Java, Junit testy jednostkowe

13. Baza danych Oracle, SQL baza danych

Następujące moduły składają się na systsem:

Administrator

BrainService

PortalPG

SpeechModel

Page 34: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

3. Zasada działania oraz opis systemu 34

4.6. Podsumowanie

Jak zostało to przedstawione w tym rozdziale architektura systemu jest mocno rozproszona.

Praktycznie każdy moduł może istnieć niezależnie, jednak wszystkie moduły razem wzięte

tworzą pełną platformę. Taka budowa zapewnia dobrą rozbudowę systemu.

Page 35: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

4

5.REALIZACJA PRACY

5.1. Wprowadzenie

W momencie realizacji niniejszego projektu posiadałem już wieloletnie doświadczenie

w programowaniu głównie systemów internetowych w różnych technologiach, w tym systemów

rozproszonych oraz korporacyjnych. Dzięki temu swobodnie mogłem skupić się na sposobie

implementacji technologii Speech (rozpoznawania i syntezy mowy) dla celów komunikacji

użytkownika z systemem za jej pośrednictwem w portalu internetowym. Technologia ta jest

dla mnie pewnym nowym wyzwaniem, które zamierzam zrealizować. Na chwilę obecną nie ma

żadnych gotowych samouczków czy pomocy naukowych które opisały by sposób wykonania

takiego systemu. Do dyspozycji mamy odrębne elementy opisane osobno, które należy zmusić

do współpracy ze sobą w pewnych określonych warunkach (w naszym przypadku chodzi

o zastosowanie klient-serwer, z wykorzystaniem dodatkowych zasobów po stronie klienta co jest

dodatkowym utrudnieniem).

Realizacja całego projektu przebiegała przy ciągłej współpracy i pod nadzorem Pana

prof. dr hab. inż. Zdzisław Kowalczuk, który wyznaczył kierunek wykonanej pracy oraz czuwał

nad tym aby nie był to projekt zamknięty, ale mógł być kontynuowany przez kolejne lata

na uczelni.

Wykonanie pracy zostało podzielone na kilka kluczowych etapów opisanych poniżej.

Wyszczególnione etapy zostały wyodrębnione na bazie poszczególnych funkcji bądź założeń,

które nie koniecznie zostały wykonane w opisanej kolejności, a często były tworzone

równorzędnie.

Etapy realizacji projektu:

1. zapoznanie się z technologią Speech oraz AI

2. wykonanie systemu analizy serwisu

3. system generowania oraz rozpoznawania mowy

4. silnik AI wraz z inicjacją "świadomości" bota oraz z implementacją 4 stanów emocji

5. stworzenie prostej graficznej postaci Awatara komunikującej się z silnikiem AI

Page 36: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

4. Realizacja pracy 36

6. utworzenie demonstracyjnego serwisu z implementacją postaci Awatara

7. przygotowanie odpowiedniej dokumentacji.

5.2. Testowanie platformy

Podstawową techniką testowania systemu jest wykorzystanie jednostek testowych, które

weryfikują cząstkowe działanie systemu. System powstawał krok po kroku, z małego rozwinął

się w duży wykonując testy użytkownika podczas jego działania. Skala złożoności i zależności

systemu jest tak duża, że do pomocy został wykonany specjalny system logowania, który

informuje użytkownika o pracy całego systemu umożliwiając wykrycie różnego rodzaju

dolegliwości i problemów w systemie, którego przetestowanie jest o tyle skomplikowane,

iż opiera się na mowie, stanie Awatara, który nie bazuje na sesji a dodatkowo rozproszony jest

na wiele pod stron, niezależnych żądań przekierowań, ale jednak tworzących pewną całość,

która była testowana poprzez użytkownika systemu.

5.3. Omówienie sposobów rozwiązania problemów

Głównym problemem, który pojawił się na początku było spasowanie i dobór istniejących

technologii do wykonanego projektu. Nadrzędnym celem jest uzyskanie wysokiej jakości

produktu przy wykorzystaniu technologii Open Source, tak aby projekt mógł być dalej rozwijany

przez uczelnie. Tak więc po wybraniu kluczowych technologii rozpoznawania i syntezy mowy

nastąpiło pasowanie do nich technologii pomocniczych. Tutaj pojawiły się już pierwsze

ograniczenia, które wskazały jakie formaty danych są obsługiwane przez powyższe technologie.

W tym momencie nastąpiło poszukiwanie technologii wspierających

Możliwość pracy rozproszonej dodatkowo komplikuje sam fakt dostępu do zasobów

komputera użytkownika (mikrofonu i głośników), który domyślnie jest zablokowany. W tym

celu została wykorzystała wykorzystana technologia Adobe Flex, która daje dostęp

do wymaganych zasobów.

5.4. Podsumowanie

W informatyce mówi się, że po wykonaniu 80% projektu do jego ukończenia pozostało

pozostałe 90%, co miało miejsce także i w tym projekcie. Projekt był nowatorski, wiele się

z niego nauczyłem, bardzo mnie rozwinął, pokonałem w nim wiele przeszkód i rozwiązałem

wiele problemów.

Page 37: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

5

6.MOŻLIWOŚCI ROZWOJU SYSTEMU

6.1. Wprowadzenie

We wczesnym etapie planowania projektu jednym z jego głównych elementów było wymaganie,

które mówiło iż projekt powinien być dalej rozwijany po jego ukończeniu. Zostało jasno

powiedziane, iż należy go tak przygotować, aby potem można było go w prosty sposób rozwijać

i podzielić jego dalszą pracę nad nim nad poszczególnymi modułami. I tak też się stało.

6.2. Rozwój klienta

System można wzbogacić o dodatkowe możliwości konfiguracyjne dla użytkownika.

Użytkownik mógłby podać swoje imię lub inne dane, które były by uwzględniane podczas

dalszej interakcji z systemem. Można by dać możliwość wyboru postaci Awatara, głosu przez

niego używanego oraz np. możliwości zmiany Mózgu, która charakteryzowała by się całkowicie

odmienną pracą systemu.

6.3. Rozwój systemu generowania mowy

System generowania mowy można wyposażyć w dodatkowe głosy, które mogą być przełączane

po stronie klienta. Istnieje także możliwość, aby utworzyć własne głosy, jest to jednak zadanie

bardzo pracochłonne i obarczone dużym ryzykiem niepowodzenia.

Ogólnie jest możliwość dodania głosów w innych wersjach językowych, jednak w tym

miejscu problemem może okazać się brak możliwości dostosowania systemu rozpoznawania

mowy w tych językach1.

Istnieje możliwość doposażenia systemu w nowe dodatkowe możliwości sterujące

generacją głosu w rodzaju możliwości sterowania prędkością, wysokością i częstotliwością

1 Problem ten dotyczy sytuacji dnia dzisiejszego.

Page 38: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

5. Możliwości rozwoju systemu 38

głosu. Także w tym miejscu można przygotować obsługę poprawnej wymowy znaków

specjalnych, skrótów i innych zapisów specjalnych.

6.4. Rozwój systemu rozpoznawania mowy

System rozpoznawania mowy można wyposażyć w kolejne komendy jeszcze bardziej

zaawansowane oraz o większą ich ilość. Teoretycznie istnieje możliwość nauczenia systemu

do rozpoznawania nowych nazw jeszcze nie zdefiniowanych w istniejących słownikach, co jest

bardzo czasochłonne i obarczone jest dużym ryzykiem niepowadzenia.

Można tutaj pomyśleć o implementacji mechanizmów rozpoznawania ciągłej mowy.

6.5. Rozwój postaci Awatara

Postać Awatara można dopracować graficznie, dopieścić jego animację i reakcję na zmianę

stanu. Można by stworzyć pakiet postaci Awatarów, z których użytkownik mógłby wybrać ten

z którym chciał by się utożsamić.

6.6. Rozwój Mózgu

Rozwój Mózgu daje najwięcej możliwości ponieważ może całkowicie zmienić zachowanie

systemu w danej sytuacji. Można by dodać do Mózgu informacje o danych poczynaniach danego

klienta, np. w celu usunięcia głupich odpowiedzi w nieskończoność typu „Jak się nazywasz?”,

gdzie po kilku takich pytaniach Awatar mógłby zwrócić uwagę klientowi, iż pytał się już

o to wielokrotnie.

Co najważniejsze można by pomyśleć o implementacji autonomicznego umysłu Awatara,

który w określonych warunkach mógłby samodzielnie podejmować decyzję, jak ma to miejsce

np. w Dictobot’cie oraz wiernie zaimplementować jego stan.

6.7. Podsumowanie

Na rynku obecnie nie ma zbyt wiele (o ile istnieją) takich lub podobnych systemów. Warto

podjąć kontynuację niniejszego projektu oraz zbadać i przetestować nowe możliwości, które on

ze sobą niesie.

Page 39: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

6

7.PODSUMOWANIE ORAZ WNIOSKI Z PRACY

7.1. Podsumowanie oraz wnioski z pracy

Praca nad systemem była wymagająca, rozwojowa, ale i wciągająca. System który powstał jest

niekonwencjonalny, przełamał wiele barier technologicznych oraz pokazał praktyczne

zastosowanie wielu różnych technologii.

W chwili obecnej nie udało mi się znaleźć żadnego odpowiednika niniejszego systemu1

lub systemu, który w dużej części odpowiadał by obecnej realizacji. Do jego realizacji

poświęciłem naprawdę wiele czasu, wiele nocy nie przespałem, kilka tygodni wolnego z pracy

także zostało spożytkowane w tym celu. Sporą część realizacji zawdzięczam Panu prof. dr hab.

inż. Zdzisław Kowalczuk, który nadał kierunek i pokierował pracą w tę stronę, w której praca

obecnie się znajduje a także poświęcił wiele czasu nad jej realizacją, za co jestem bardzo

wdzięczny.

Wykonanie systemu było dla mnie niezwykle rozwijające, nauczyłem się wiele z samych

technologii informatycznych, ale także poznałem elementy, które nadają „życia” temu

komputerowemu projektowi. Był to czas, którego nie żałuję iż wykorzystałem go w taki a nie

w inny sposób.

Projekt obecnie znajduje się na wstępnej rozwojowej drodze, tak więc nadaje się

on do podjęcia jego rozbudowy i dopracowania, tak aby był w stanie godnym przedstawienia

go szerszemu gronu odbiorców.

1 Mogę z wielką pewnością stwierdzić, iż taki odpowiednik nie istnieje wcale.

Page 40: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

40

8.Dodatek 1. Skrótowy opis aplikacji

Tytuł dyplomu

System inteligentnej nawigacji sterowanej głosem po serwisie internetowym.

Cel i przeznaczenie aplikacji

Opracowanie głosowego systemu komunikacji oraz nawigacji po serwisie internetowym. Projekt

zakłada wykonanie portalu testowego, systemu rozpoznawania i generowania mowy, mózgu

systemu oraz postaci Awatara komunikującego się z użytkownikami oraz kierującego ich

po serwisie. System ma być inteligentny w tym znaczeniu, iż Awatar nie będzie nas tylko

słuchał, ale także będzie z nami w dialogu wyrażając się poprzez swoje emocje. Wykonanie

projektu zakłada komunikację w języku angielskim.

Funkcjonalność

Opis realizowanych funkcji

Praca w Internecie bez potrzeby zalogowania się

Równoczesna obsługa wielu użytkowników w osobnych wątkach

Stan Awatara wyposażony w 4 niezależne wartości

Pamięć stanu Awatara

Rozpoznawanie wybranych komend głosowych

Generowanie mowy z uwzględnieniem aktualnego stanu Awatara

Odtwarzanie oraz nagrywanie mowy w czasie rzeczywistym

Konwersja formatów: FLV -> WAV -> MP3 w osobnych wątkach

Funkcjonalny portal demonstracyjny

Panel administratora

Niezależny Mózg systemu generujący mowę, odpowiedź i przekierowanie w zależności

od kontekstu jako Web-Service

Wizualizacja postaci Awatara, który graficznie przedstawia swój stan

Animacja ruchu ust Awatara podczas jego mowy

Prosta implementacja modulacji głosu Awatara w zależności od jego stanu

Możliwość edycji generowanych komunikatów głosowych

Podgląd stanu bazy danych poprzez Panel Administracyjny

Pamięć użytkownika poprzez całą komunikację po portalu (wielo-stronnicowa)

Rozpoznanie czy użytkownik przyszedł po raz pierwszy na Portal

czy powrócił tu ponownie, np. zmieniając wyświetlaną stronę

Przekierowanie na nową stronę portalu na podstawie wydanej komendy głosowej

Głosowa wiadomość powitalna dla każdej pod-strony

Zaawansowany system zdarzeń informacji o pracy całego systemu po stronie

użytkownika, który daje wgląd w pracę całego systemu we wszystkich modułach

Kompresja wygenerowanej mowy w celu przyśpieszenia odtworzenia wiadomości

Zaimplementowana najwyższa jakość generowanego i rozpoznanego głosu, jaki daje

zastosowana biblioteka (zastosowane ustawienia na 16kHz)

Mechanizm kilkukrotnego ponowienia odtworzenia oczekującej wiadomości głosowej

o ile system nie został jeszcze w pełni zainicjalizowany

Osobne przechowywanie plików audio dla wejścia i wyjścia sygnału

Page 41: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

41

Funkcja zapominania stanu Awatara po stronie klienta

Opcja nagrywania mowy za pomocą jednego wciśnięcia i przytrzymania przycisku

Zastosowany system znaczników mowy pozwalający na implementację tego systemu

na dowolny Portal Internetowy.

Lista przykładowych zastosowań

Odsłuchiwanie zawartości strony Portalu Internetowego

Umilenie pracy użytkownika

Nawigacja po portalu za pomocą wykorzystania własnego głosu

Zabawa z Awatarem w celu rozpoznania jego emocji poprzez odsłuchiwanie jego mowy

Dialog z Awatarem, po odpowiednim dopracowaniu Mózgu można zrobić z niego tzw.

Zwierzątko, które będzie żyło własnym życiem

Po odpowiednim dopracowaniu inteligentne wyszukiwanie i filtrowanie zawartości

portalu.

Szczegółowe opisy działania aplikacji

Aplikacja jest typu klient-server. Klient jest to część, która znajduje się po stronie użytkownika,

zapewnia ona komunikację z serwerem, jest ona interfejsem użytkownika, który wydaje

komendy głosowe, odsłuchuje komunikaty oraz przedstawia graficzną postać Awatara

zmieniającą się w zależności od swojego stanu. Serwer zajmuje się rozpoznawaniem oraz

generowaniem mowy, obsługą połączeń klientów oraz komunikacją z Mózgiem systemu.

Wykonany system jest platformą, portal demonstracyjny jest jedynie pokazem jego

zastosowania. Z tego względu działanie aplikacji możemy wydzielić na dwie części. Pierwszą

z nich jest wygenerowanie na podstawie wcześniej przygotowanych znaczników mowy

zawartości portalu, która posłuży Mózgowi do odsłuchania (wygenerowania mowy), wyszukania

informacji oraz przekierowania w odpowiednie miejsce portalu. Za tę część odpowiedzialny jest

system znaczników oraz część administracyjna, która generuje treść portalu bazując

na dostarczonym sitemap strony. Generator przechodząc kolejno przez strony zapisane

w sitemap, parsuje je, wyciąga przygotowane informacje oraz w odpowiedni sposób indeksuje

i buforuje dane w bazie danych.

Działanie samego systemu opiera się na samoistnej świadomości Awatara, który

wyposażony jest w mechanizm „zapominania”, który działa wyłącznie po stronie klienta.

Stan Awatara przechowywany jest na komputerze klienta i zapamiętywany jest nie tylko poprzez

daną sesję użytkownika (które de facto nie wymaga chociażby zalogowania się do systemu),

ale pamiętany jest od czasu ostatnich odwiedzin portalu internetowego. Pamięć ta opiera się

na mechanizmie Shared Object platformy Adobe Flash, który w uproszczeniu1 jest

odpowiednikiem pliku ciasteczka (ang. cookie). Użytkownik wchodząc na portal w pierwszej

kolejności zostaje przywitany odpowiednim komunikatem oraz zostaje zapamiętany w systemie,

tak że podczas kolejnej wizyty w trakcie danej sesji zostanie on już w inny sposób obsłużony,

tzn. otrzyma inny komunikat powitalny. Obsługa rozpoznania klienta znajduje się po stronie

Serwera Mowy, który posiada zapisaną listę aktualnie podłączonych klientów.

Podczas każdego załadowania strony następuje inicjalizacja połączenia, każde połączenie

jest weryfikowane czy może zostać obsłużone w kanale RTMP zapewniającym nagrywanie

i odsłuchiwanie komunikatów głosowych w czasie rzeczywistym. Także w tym momencie

następuje rezerwacja mikrofonu oraz zapytanie o zgodę na jego wykorzystanie. Gdy proces

ten przebiegnie pomyślnie Serwer Mowy przesyła dla klienta potwierdzenie, iż połączenie

1 Tak naprawdę Shared Object jest obiektem o wiele bardziej zaawansowanym niż ciasteczko.

Page 42: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

42

zostało nawiązane, wówczas klient w odpowiedzi przesyła prośbę o wygenerowanie komunikatu

powitalnego oraz przesyła swój stan (emocje, które w danym momencie mogą być inne niż

domyślne). Na podstawie prośby i stanu Serwer Mowy za pośrednictwem Mózgu generuje

wiadomość powitalną, która na bazie zaktualizowanego stanu Awatara zostaje odpowiednio

zmodulowana2. Informacja o wygenerowanej i oczekującej wiadomości do odsłuchania zostaje

przesłana dla klienta, który automatycznie odtwarza ją3. Równocześnie klient otrzymuje

od Mózgu za pośrednictwem serwera mowy bodziec zmieniający stan Awatara (jego emocje),

który zostaje już stopniowo zaktualizowany po stronie klienta4.

Podobnie ma się sprawa z wysłaniem komendy głosowej, która nagrywana jest podczas

przyciśnięcia i przytrzymania przycisku „Speak”. W tym czasie mowa zostaje bezpośrednio

nagrywana na serwerze mowy. Po zakończeniu nagrywania komendy głosowej, zostaje pobrany

stan Awatara od klienta, z nagranej mowy zostaje rozpoznana komenda głosowa, która

przesyłana zostaje do Mózgu systemu. Mózg posiadając informacje o aktualnym stanie Awatara

generuje odpowiedź, która przekazywana jest do klienta. Odpowiedź zawiera wygenerowany

komunikat głosowy, zmianę stanu Awatara (emocji) oraz ewentualnie adres nowej strony,

na którą klient powinien zostać automatycznie przekierowany.

Architektura sprzętu

Elementy rozpoznawania i generowania mowy wymagają silnego serwera, aby były w stanie

obsłużyć wielu użytkowników równocześnie oraz aby zapewnić krótkie czasy reakcji

na wypowiadane i generowane komendy głosowe. Do pracy z systemem wymaga się komputera

wyposażonego w głośniki i mikrofon, które nie są wymagane po stronie serwera.

Do wykonania systemu korzystałem z dwóch środowisk:

deweloperskie – wyposażone w komputer o procesorze Pentium 4x2.66 GHz oraz 4 GB

RAM, 300 GB HDD

produkcyjne – wyposażone w komputer o procesorze Pentium 4x2.66 GHz oraz 16 GB

RAM, o przepustowości Internetu 100Mbps oraz 2TB HDD

System wymaga silnego serwera oraz dużej przestrzeni dyskowej, ponieważ dla jednego

użytkownika podczas kilku godzin pracy generowanych jest kilkaset megabajtów danych audio

w przeciągu kilku dni5.

Architektura oprogramowania

Architektura systemu została przedstawiona na rys. 7.1. Cały system został wytworzony

w technologii Java/Flex. Technologia Adobe Flex została wykorzystana do utworzenia klienta,

natomiast część serwerowa została wykonana w technologii Java. Budowa platformy

jest modułowa, umożliwiająca niezależny rozwój i wymianę każdego z modułów.

2 Modulacja polega na zmianie parametrów audio generowanej mowy.

3 Odtworzenie nagranego komunikatu głosowego następuje w czasie rzeczywistym przy wykorzystaniu protokołu

RTMP. 4 Zmiany stanu (emocji) Awatara dokonywane są po stronie klienta na bazie otrzymanych informacji o ile dany stan

(emocja) powinien zostać zmieniony. 5 Do klienta zostaje przesłany materiał w wersji skompresowanej o kilku, a czasem kilkunasto krotnie mniejszej

objętości. Tylko po stronie serwera zostają wygenerowane dane o dostępnej najwyższej jakości danych, które

następnie zostają skompresowane i przekazane dla klienta.

Page 43: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

43

Rys. 7.1. Ogólna architektura systemu.

Część kliencka odpowiada za komunikację z serwerem, przydzieleniem uprawnień do mikrofonu

i głośników, wygenerowaniem unikalnego identyfikatora dla klienta, który następnie jest

wykorzystywany przez serwer do jego identyfikacji. Także w tej części użytkownik ma kontakt

z systemem, obserwuje wizualnie postać Awatara, wydaje komendy oraz słucha systemu, tutaj

także znajduje się aktualna wizualizacja stanu Awatara w postaci wykresu słupkowego oraz

konsola logów z całego systemu, w której użytkownik monitoruje stan systemu w danym

momencie. Po stronie klienta przechowywany jest aktualny stan Awatara unikalny dla każdego

użytkownika. jednak jest on przypisany na stałe do danego komputera, a czasem przeglądarki.

Część serwerowa została oznaczona kolorem zielonym. Fizycznie część ta podzielona

jest na dwa serwery: serwer mowy jest serwerem czasu rzeczywistego, jest to serwer Red5 RC

1.0, który opiera się na platformie Apache Tomcat 6 działający na porcie 8080 dla protokołu

HTML oraz na porcie 1935 dla protokołu RTMP, drugim serwerem jest Oracle WebLogic 11g

na którym działa „Mózg” systemu, część administracyjna oraz portal demonstracyjny. Sewer

standardowo działa na porcie 7001 dla protokołu HTML.

Serwer mowy jest kluczowym elementem całego systemu, zwyczajowo nazywany

„serwerem” niniejszego systemu. To bezpośrednio z nim komunikuje się klienta (a w zasadzie

użytkownik systemu). Serwer ten wydziela dalszą interakcję z użytkownikiem. Na serwerze tym

zostały utworzone moduły generowania i syntezy mowy, klienta mózgu, obsługi i konwersji

danych audio przesyłanych w czasie rzeczywistym. Także w tym miejscu znajduje się lista słów

i komend rozpoznawalnych przez system w formacie JSGF (ang. Java Speech Grammar

Format). W tym miejscu mamy konfiguracje systemów rozpoznawania i syntezy mowy

w formatach zdefiniowanych przez specyfikacje bibliotek FreeTTS oraz Sphinx4.

Page 44: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

44

Wykonany serwer mowy posiada architekturę wielo-wątkową6 (ang. Multithreading),

tak więc każde żądanie nowego klienta obsługiwane jest w nowym wątku. Konwersje formatów

danych audio są także wykonywane wielo wątkowo. Rozpoznanie komendy głosowej

z wygenerowaniem odpowiedzi również zachodzi w osobnym wątku. Wymienione elementy

posiadają wykonaną własną implementację nie zależną od standardu Javy, która samodzielnie

próbuje dzielić zadania na wiele wątków.

Mózg jest drugim serwerem, który odpowiada za logikę aplikacji. Komunikuje się

on bezpośrednio i wyłącznie z systemem mowy, od którego dostaje komendę użytkownika już

w postaci tekstowej, identyfikator klienta oraz stan Awatara oraz zwraca akcję do wykonania

przez klienta wraz z komendą zmiany stanu Awatara lub wykonania przekierowania do innej

strony w portalu internetowym. Komunikacja systemu mowy następuje poprzez klienta Mózgu,

który komunikuje serwer mowy z „Mózgiem” poprzez protokół SOAP przy wykorzystaniu

dokumentu WSDL w technologii rozproszonej SOA. To rozwiązanie umożliwia łatwe

dodawanie nowych implementacji Mózgu oraz przełączanie ich w czasie działania aplikacji.

Mózg na podstawie otrzymanych danych i przetworzeniu posiadanych decyduje o wykonanej

interakcji w portalu internetowym za pośrednictwem serwera mowy, który dodatkowo może

wygenerować komunikaty głosowe dla użytkownika oraz przesłać komunikaty zmiany stanu

Awatara lub zadecydować o wykonaniu przekierowania użytkownika do innej strony na portalu

internetowym.

Klient łączy się z częścią serwerową za pośrednictwem protokołów RTMP i AMF (ang. Action

Message Format). Za pomocą protokołu RTMP przesyłany jest wyłącznie sygnał audio w czasie

rzeczywistym bez potrzeby przesyłania całego materiału w całości7. Natomiast protokół AMF

służy wyłącznie do wymiany komunikatów pomiędzy serwerem a klientem. Komunikaty

te zawierają informacje typu: stan Awatara, komendy tekstowe przesyłane do serwera w postaci

czytelnego tekstu, informacje zwrotne dla klienta kiedy czeka na niego wiadomość

do odsłuchania, komunikaty logów8 ze strony serwera itp. Klient-serwer komunikuje się ze sobą

wyłącznie za pośrednictwem tych dwóch protokołów.

Serwer mowy komunikuje się z Mózgiem za pośrednictwem protokołu SOAP

w technologii rozproszonej SOA. Wyłącznie Mózg komunikuje się z bazą danych. W ten sposób

zostały jasno wyznaczone warstwy systemu.

Opis metody wytwarzania aplikacji

Cykl wytworzenia niniejszej aplikacji przedstawia się następująco:

1. zapoznanie się z technologią Speech oraz AI

2. wykonanie systemu analizy serwisu

3. system generowania oraz rozpoznawania mowy

4. silnik AI wraz z inicjacją "świadomości" bota oraz z implementacją 4 stanów emocji

5. stworzenie prostej graficznej postaci Awatara komunikującej się z silnikiem AI

6 Architektura wielo-wątkowa pozwala na równoległą realizację żądań wielu użytkowników równocześnie.

Najczęściej żądania są rozdzielane równomiernie na dostępne procesory i rdzenie dzięki czemu wykonywane

operacje powinny odbywać się szybciej (choć nie zawsze, jeżeli liczba wątków jest zbyt duża) i powinny pozwolić

na wykonanie danej operacji przez nowego użytkownika bez potrzeby oczekiwania na zakończenie wykonywanych

operacji przez innych użytkowników (jednak w praktyce nie zawsze tak jest, jest to zależne od danej

implementacji). 7 Protokół RTMP w odróżnieniu od innych protokołów naprawdę przesyła dane w czasie rzeczywistym. Inne

protokoły najczęściej „udają”, że przesyłają materiał czasie rzeczywistym, lecz np. przesyłają go w partiach, a nie

bit po bicie jak dzieje się to w przypadku wykorzystania protokołu RTMP. 8 Komunikaty te informują klienta co dzieje się po stronie serwera. W przypadku jakichkolwiek problemów

po stronie serwera klient jest informowany o tym fakcie.

Page 45: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

45

6. stworzenie demonstracyjnego serwisu

7. przygotowanie odpowiedniej dokumentacji.

Założenia i sformułowane zadania

Celem niniejszego projektu jest wytworzenie systemu, który docelowo będzie można wdrożyć

w istniejący portal PG. Z tego powodu zostało założone wykonanie mechanizmu

dostosowującego się do istniejącego portalu internetowego, który powinien działać

po wykonaniu minimalnego nakładu pracy.

Kolejne założenia dotyczą samego systemu, który powinien działać w Internecie oraz nie

powinien wymagać zalogowania się. Do komunikacji z użytkownikiem powinna zostać

wykorzystana postać Awatara wyposażona w swój stan (emocje), dzięki którym będzie się

inaczej zachowywała9 oraz będzie generowała mowę w inny sposób

10.

System ma składać się z niezależnych modułów umożliwiających łatwą jego rozbudowę.

Mózg systemu podejmujący decyzję i generujący odpowiedź11

powinien być niezależny

od implementacji poprzez wykorzystanie technologie usług internetowych (ang. Web Service),

który umożliwi jego nieograniczony rozwój bez wymuszenia zastosowania konieczności

zastosowania konkretnego języka programowania.

Specyfikacje

System operacyjny:

Linux

Windows

Macintosh.

Serwer aplikacji:

Oracle WebLogic

Red5.

Języki programowania:

JavaEE

ActionScript.

Baza danych:

Oracle.

Główne bibloteki:

Rozpoznawanie mowy: Sphinx-4

Generowanie mowy: FreeTTS.

Przygotowanie projektu

Projekt został udostępniony i zainstalowany na serwerze dedykowanym, który dzierżawię.

W pełni funkcjonalny jest on dostępny pod adresem internetowym:

9 Zachowanie postaci Awatara zostało odwzorowane w animacji.

10 Poprzez wykorzystanie modulacji wygenerowanego głosu.

11 Podjęcie decyzji ma za zadanie wygenerowanie odpowiedniej odpowiedzi w zależności od kontekstu, w którym

w danej chwili znajduje się postać Awatara.

Page 46: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

46

http://94.23.252.15:7001/portal/index.xhtml

Prototypowanie i implementacja

Ze względu na charakter niniejszego projektu, który jest pewnym novum na rynku można

powiedzieć, że większość prac z projektem była pewnym etapem prototypowania. Z każdym

miesiącem projekt ewoluował, rozwijał się w miarę dokonanych badań, testów i uzyskanych

wyników, tak aby docelowo uzyskał on najlepszy możliwy wynik. Implementacja była

już wynikiem wcześniej wykonanych prac.

Testowanie

Podstawową techniką testowania systemu jest wykorzystanie jednostek testowych, które

weryfikują cząstkowe działanie systemu. System powstawał krok po kroku, z małego rozwinął

się w duży wykonując testy użytkownika podczas jego działania. Skala złożoności i zależności

systemu jest tak duża, że do pomocy został wykonany specjalny system logowania, który

informuje użytkownika12

o pracy całego systemu umożliwiając wykrycie różnego rodzaju

dolegliwości i problemów w systemie, którego przetestowanie jest o tyle skomplikowane,

iż opiera się na mowie, stanie Awatara, który nie bazuje na sesji a dodatkowo rozproszony jest

na wiele pod stron, niezależnych żądań przekierowań, ale jednak tworzących pewną całość,

która była testowana poprzez użytkownika systemu.

Ocena aplikacji oraz porównanie do innych rozwiązań

W chwili obecnej nie udało mi się znaleźć żadnego odpowiednika niniejszego systemu13

lub systemu, który w dużej części odpowiadał by obecnej realizacji. Do jego realizacji

poświęciłem naprawdę wiele czasu, wiele nocy nie przespałem, kilka tygodni wolnego z pracy

także zostało spożytkowane w tym celu. Sporą część realizacji zawdzięczam Panu prof. dr hab.

inż. Zdzisław Kowalczuk, który nadał kierunek i pokierował pracą w tę stronę, w której praca

obecnie się znajduje a także poświęcił wiele czasu nad jej realizacją, za co jestem bardzo

wdzięczny. Te wszystkie elementy potwierdzają wyłącznie iż praca została wykonana żetelnie,

z największą starannością, ale także zawiera wiele unikalnych i nowatorskich rozwiązań, która

zapracowała i zasługuje na najwyższą ocenę.

Wnioski i perspektywy dalszych prac

Wykonanie systemu było dla mnie niezwykle rozwijające, nauczyłem się wiele z samych

technologii informatycznych, ale także poznałem elementy, które nadają „życia” temu

komputerowemu projektowi. Był to czas, którego nie żałuję iż wykorzystałem go w taki a nie

w inny czas.

Projekt obecnie znajduje się na wstępnej rozwojowej drodze, tak więc nadaje się

on do podjęcia jego rozbudowy i dopracowania, tak aby był w stanie godnym przedstawienia

go szerszemu gronu odbiorców.

12

Operator systemu. 13

Mogę z wielką pewnością stwierdzić, iż taki odpowiednik nie istnieje wcale.

Page 47: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

47

9.Dodatek 2. Instrukcja dla użytkownika

Instrukcja opisuje sposób sterowania Portalem Internetowym za pomocą głosu.

Adres internetowy portalu demonstracyjnego:

http://94.23.252.15:7001/portal/index.xhtml

Przygotowanie do pracy z systemem

Wymagania do rozpoczęcia pracy z systemem:

połączenie do Internetu

przeglądarka internetowa z wtyczką Adobe Flash Player 10 lub nowszym

głośniki i mikrofon.

Zaleca się skorzystanie ze słuchawek z mikrofonem w celu większego odseparowania

użytkownika od otoczenia.

Do pełnej wygody podczas pracy z aplikacją zaleca się skonfigurowanie zabezpieczeń

systemu Adobe, aby za każdym razem system nie pytał się nas o wyrażenie zgody

na wykorzystanie mikrofonu.

Wydanie zgody dla aplikacji na korzystanie z mikrofonu

Polityka bezpieczeństwa Adobe wymusza na nas każdorazowo o wydanie zgody

na wykorzystanie mikrofonu. Ma to na celu np. uniemożliwienie podsłuchiwania użytkowników

poprzez Internet, dlatego więc użytkownik zmuszony został do świadomego wyrażenia zgody

na podłączenie mikrofonu do aplikacji jak pokazano na poniższym rysunku:

Rys. 8.1. Prośba o wyrażenie zgody na użycie mikrofonu.

Istnieje jednak możliwość, aby globalnie taką zgodę (wówczas aplikacja nie będzie

już wyświetlała okienka jak powyżej i domyślnie pozwoli na wykorzystanie mikrofonu). Zostało

to opisane poniżej. Opis dotyczy najnowszej wersji wtyczki Adobe Flash 11 w wersji polskiej.

Klikamy prawym przyciskiem myszki na postać Awatara i wybieramy opcję „Ustawienia

globalne…”:

Page 48: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

48

Rys. 8.2. Wybranie opcji „Ustawienia globalne…”.

W „Menedżer ustawień programu Flash Player” przechodzimy do zakładki „Kamera

i mikrofon” oraz wciskamy przycisk „Ustawienia kamery i mikrofonu wg witryn…”:

Rys. 8.3. Przejście do ustawień kamery i mikrofonu.

W oknie „Ustawienia kamery i mikrofonu wg witryn” zaznaczamy w głównym oknie

witrynę internetową o nazwie „94.23.252.15” poprzez kliknięcie jej (wówczas zostanie

ona podświetlona na niebiesko):

Page 49: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

49

Rys. 8.4. Wybranie adresu portalu demonstracyjnego.

Następnie w części „Gdy zaznaczona witryna spróbuje użyć kamery lub mikrofonu:”

wybieramy opcję „Zezwól” (domyślnie klikamy na listę o nazwie „Pytaj mnie

o pozwolenie” i zmieniamy ją na „Zezwól”):

Page 50: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

50

Rys. 8.5. Zezwolenie na wykorzystanie mikrofonu dla portalu demonstracyjnego.

Końcowe ustawienia powinny wyglądać jak na rysunku poniżej. Na zakończenie klikamy

„Zamknij”. Od tego momentu aplikacja nie powinna się już nas pytać o możliwość

skorzystania z mikrofonu.

Rys. 8.6. Widok ostatecznej konfiguracji reguł systemu zabezpieczeń Adobe.

Komendy sterujące pracą systemu

Sterowanie portalem odbywa się poprzez wydawanie komend głosowych oraz poprzez

udzielanie odpowiedzi na wydane zapytania ze strony systemu. Wszystkie komendy należy

wydawać głośno i wyraźnie. Zaleca się użycie słuchawek z mikrofonem. Należy mieć

na uwadze, aby w pomieszczeniu, w którym odbywa się komunikacja z portalem panowała

cisza. Wszelkie hałasy, dźwięki w tle mogą utrudnić lub uniemożliwić poprawne rozpoznawanie

komend głosowych poprzez system, co w konsekwencji może uniemożliwić poprawne

rozpoznawanie komend głosowych poprzez system.

W celu wydania komendy głosowej należy wcisnąć przycisk „Speech”, wydać komendę

głosową do mikrofonu oraz puścić przycisk.

Podstawowe komendy użytkownika zostały przedstawione w tab. 8.1.

Tab. 8.1. Komendy użytkownika.

l.p. komenda działanie

1. „Good Morning” awatar powinien przywitać się z nami

2. „Hello” awatar wita się

3. „How are You ?” awatar odpowiada nam jak się czuje i pyta się nas

o to samo

4. „What is Your Name ?” awatar odpowiada nam jak się nazywa

Page 51: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

51

5. „Read page” awatar czyta zawartość głównej strony

6. „Home”, itp. następuje przeniesienie do odpowiedniej strony

7. „Next page” powodują przejście do następnej strony

8. „Previous page” powodują przejście do poprzedniej strony

Lokalne ustawienia systemu

Użytkownik może zdecydować czy chce wyświetlać emocje awatara lub logi z systemu.

Dokonuje tego poprzez diwie opcje:

Show info – decyduje czy system ma wyświetlać emocje Awatara,

Show log – określa czy wyświetlać logi z systemu.

Opcje te po przełączeniu są od razu zapisywane i nie trzeba wciskać przycisku „Save”1. Panel

ustawień został zaprezentowany na rys. 8.7. Część opcji została domyślnie wyłączona przed

modyfikacją użytkownika2.

Adres: http://94.23.252.15:7001/portal/avatar/settings.xhtml

Rys. 8.7. Ustawienia aplikacji klienta.

1 Co więcej opcje te są zapisywane i pamiętane nawet po zamknięciu danej przeglądarki internetowej.

2 Jest to celowe uproszczenie systemu. Opcje te można odkomentować w kodzie źródłowym dołączonej aplikacji.

Page 52: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

52

10.Dodatek 3. Instrukcja dla administratora

Administrator systemu odpowiada za przygotowanie portalu internetowego do pracy

z systemem, wygenerowanie treści portalu oraz zdefiniowanie komunikatów głosowych

wypowiadanych przez Awatara. Do tego celu został przygotowany system znaczników oraz

Panel Administracyjny. W celu wybrania poszczególnych stron portalu do obsługi w systemie

wykorzystuje się mapę strony (ang. sitemap).

System znaczników

W celu oznaczenia treści portalu, które mają zostać wykorzystane w systemie został

zdefiniowany specjalny system znaczników, którymi obejmuje się fragmenty strony

internetowej1.

Podstawowa budowa znacznika z wymaganymi elementami:

<speech value=" " weight"”>TREŚĆ</speech>

TREŚĆ – treść, która może być uwzględniona podczas generowania mowy.

Tab. 9.1. Atrybut „value”.

l.p. wartość opis

1. MENU element menu

2. TITLE tytuł strony lub głównego elementu na stronie

3. INTRO skrócona zawartość strony. Opis zawartości strony

4. TEXT główna treść strony

5. LINK link w części strony

6. PEOPLE wykładowca

7. SUBJECT przedmiot dydaktyczny

8. SUBJECT_DATA dodatkowe informacje na temat przedmiotu

Atrybut „value” oznacza typ zaindeksowanej zawartości. Atrybut ten został opisany w tab. 9.1.

Tab. 9.2. Atrybut weight.

l.p. wartość opis

1. 0 element najważniejszy

2. 1 element średnio ważny

3. 2 element najmniej ważny

Atrybut „weight” oznacza ważność danego elementu. Za jego pomocą można określić

np. iż menu główne jest bardziej istotne z punktu widzenia systemu niż menu poboczne2.

Atrybut ten został opisany w tab. 9.2.

1 Znacznikami mowy można objąć zarówno statyczne jaki i dynamiczne fragmenty stlony internetowej.

2 Takie rozumowanie wydaje się logiczne, jednak system sam nie myśli, dlatego taka logika została jawnie

zdefiniowana.

Page 53: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

53

W systemie istnieją także inne znaczniki, które zawierają więcej atrybutów. Należą do nich

znaczniki typu3:

PEOPLE,

SUBJECT,

SUBJECT_DATA.

Znacznik typu PEOPLE:

<speech value="PEOPLE" weight="" degree="" function="" moreUrl="">IMIĘ

I NAZWISKO</speech>

Tab. 9.3. Dodatkowe atrybuty znacznika typu PEOPLE.

l.p. atrybut wartość

1. degree stopień naukowy.

2. function zajmowane stanowisko,

3. moreUrl adres strony internetowej z informacją na temat

wykładowcy.

Znacznik typu SUBJECT:

<speech value="SUBJECT" type="">NAZWA PRZEDMIOTU</speech>

Tab. 9.3. Dodatkowe atrybuty znacznika typu SUBJECT.

l.p. atrybut wartość

1. type rodzaj przedmiotu.

Znacznik typu SUBJECT_DATA:

<speech value="SUBJECT_DATA" name="" subjectForm="" noOfHours="" teachers=""

taughtIn="" studyLevel="" semester=”" department=""/>

Tab. 9.4. Dodatkowe atrybuty znacznika typu SUBJECT_DATA.

l.p. atrybut wartość

1. name nazwa przedmiotu. Powinna być taka jak podana w

znaczniku typu SUBJECT.

2. subjectForm rodzaj zajęć.

3. noOfHours liczba godzin w semestrze.

4. taughtIn kierunek.

5. studyLevel poziom studiów.

6. semester semestr.

7. department wydział.

3 Typ znacznika został zdefiniowany poprzez atrybut „value”.

Page 54: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

54

Mapa strony – sitemap

Na potrzeby systemu została wykorzystana standardowa mapa strony (ang. sitemap).

Za jej pomocą definiuje się listę stron do zaindeksowania dla systemu.

Przykładowa mapa strony:

http://94.23.252.15:7001/portal/index.xhtml

http://94.23.252.15:7001/portal/people.xhtml

http://94.23.252.15:7001/portal/people/zdzislaw_kowalczuk.xhtml

http://94.23.252.15:7001/portal/specialization.xhtml

http://94.23.252.15:7001/portal/didactics/process_diagnostics.xhtml

http://94.23.252.15:7001/portal/teaching.xhtml

http://94.23.252.15:7001/portal/research.xhtml

http://94.23.252.15:7001/portal/laboratories.xhtml

http://94.23.252.15:7001/portal/smart_control_idea.xhtml

Panel administracyjny

System został wyposażony w panel administracyjny ułatwiający pracę wygenerowania oraz

zweryfikowania zawartości platformy a także zmiany generowanych komunikatów głosowych.

Adres panelu administracyjnego:

http://94.23.252.15:7001/portal/admin/index.xhtml

Dane logowania:

Login: admin

Hasło: etiavatar1

Edycja generowanych odpowiedzi z systemu – Avatar Speech

Adres: http://94.23.252.15:7001/portal/admin/index.xhtml

W celu zmiany generowanych odpowiedzi przez system należy skorzystać z tego panelu.

Wybieramy komunikat głosowy, klikamy po prawej stronie przycisk „edit”, zmieniamy jego

treść oraz klikamy przycisk „save”4 w celu zapisania zmian. Panel ten został przedstawiony

na rys. 9.1. Tabela 9.4 przedstawia domyślne treści komunikatów głosowych.

Tab. 9.4. Dodatkowe atrybuty znacznika typu SUBJECT_DATA.

l.p. Typ komunikatu Domyślny komunikat

1. WELCOME_BACK Welcome back my dear

2. DONT_UNDERSTAND I don't understand You. Please repeat.

3. PLEASE_REPEAT Please repeat.

4. YOU_SAID I thing that I don't understand you well. Have you said

5. HELLO Hello. It's nice to meet you.

6. MY_NAME_IS My name is Avatar. What is your name ?

7. GOTO_PAGE I'am moving you to the page

4 W trybie edycji przycisk „save” pojawia się w miejscu przycisku „edit”.

Page 55: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

55

8. PAGE_ABOUT About Department! The Department of Decision Systems

was created in 2006 by professor Zdzislaw Kowalczuk

and, of interests of the Department concern modeling and

identification, diagnostics, control and decision systems.

Scientific research involve planning and control both

industrial and economical processes as well as developing

modern design methods using computer techniques and

tools. The methods derived result both from classical

analysis and artificial/computational intelligence.

Industrial process diagnosis, methods of system and

signal analysis and filtering, estimation of dynamical

plants state, production and path planning and other

problems, which enhance the characterization of the

Department, are utilized in automatic control systems,

mobile and flying robots, automotive vehicles and other

industrial objects. In the field of teaching the

Department’s staff together with the staff of the

Automatic Control Department play the role of a

principal leader in the BSc/MSc course of Automatic

Control and Robotics in the Faculty of Electronics

Telecommunication and Informatics of the Gdansk

University of Technology.

9. WELCOME_ON_PORTAL Welcome on avatar speech portal. This is an engineer

thesis work.

10. WELCOME Good morning my dear. What's a beautyfull day. How are

you?

Page 56: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

56

Rys. 9.1. Edycja generowanych odpowiedzi z systemu.

Generator treści systemu

Generator tworzy bazę danych na bazie uprzednio przygotowanych znaczników mowy

na podstawie listy stron zapisanych w mapie strony (ang. sitemap).

Adres: http://94.23.252.15:7001/portal/admin/sitemap.xhtml

Rysunek 9.2 przedstawia panel. Zawiera on wyłącznie dwie opcje:

Show – która wyświetli zawartość sitemap,

Generate – generuje zawartość portalu5.

W polu „Sitemap” należy podać lokalizację pliku sitemap.

5 Uwaga: opcja ta wyczyści aktualnie przechowywane informacje na portalu, jednak nie zmodyfikuje treści

generowanych komunikatów mowy przez system. Niepoprawne skonfigurowanie uniemożliwi dalszą pracę

z systemem do czasu przygotowania poprawnych danych.

Page 57: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

57

Rys. 9.2. Generator treści systemu.

Podgląd zawartości wygenerowanej bazy danych na bazie znaczników

W każdym momencie możemy podejrzeć zawartość wygenerowanej bazy danych na bazie

zastosowanych znaczników mowy.

Adres:

http://94.23.252.15:7001/portal/admin/pages.xhtml

http://94.23.252.15:7001/portal/admin/speech.xhtml

http://94.23.252.15:7001/portal/admin/peoples.xhtml

http://94.23.252.15:7001/portal/admin/subjects.xhtml

Instrukcja wdrożenia systemu

Na dołączonej płycie DVD znajduje się przygotowana paczka systemu w wersji do wdrożenia

na serwer. Paczka ta kompatybilna jest ze standardem JavaEE6 EAR. Zawiera ona przykładową

konfigurację pod serwer Oracle WebLogic. Instalacja odbywa się w sposób standardowy

dla tego typu serwerów tak więc można ją wykonać według instrukcji dołączonej do serwera.

Dodatkowo poza paczką EAR na płycie znajduje się aplikacja SpeechServer, którą należy

wdrożyć na serwer RTMP Red5. Paczka ta jest już skonfigurowana do pracy pod tym serwerem,

wdraża się ją jak na serwer Apache Tomcat. Schemat wdrożeniowy został przedstawiony

na rys. 9.3. Przed instalacją systemu na serwery należy wpierw utworzyć bazę danych ze

skryptów dołączonych na płycie oraz dodać DataSource na serwerze JavaEE o nazwie

SPEECHDS z połączeniem do nowo utworzonej bazy danych. Serwer mowy wymaga

zainstalowanej biblioteki Xuggler.

6 Dodatkowo znajduje się w niej plik wdrożeniowy na serwer Oracle WebLogic. Istnieje jednak możliwość,

aby tak przygotowaną paczkę wdrożyć na inny serwer JavaEE po odpowiednim przygotowaniu.

Page 58: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

58

Główne pliki konfiguracyjne:

SpeechServer\src\com\janklimczak\speech\server\Settings.java – zawiera adres folderu

na serwerze do przechowywania plików audio

SpeechAvatar\src\com\janklimczak\speech\communication\ResponseToServer.as – adres

serwera RTMP wraz z nazwą aplikacji SpeechServer7

Pozostałe pliki konfiguracyjne wynikają ze specyfikacji JavaEE, tak więc na ich temat można

znaleźć więcej w dokumentacji Java.

Rys. 9.3. Diagram wdrożenia systemu.

7 System zawiera implementację tego adresu jako opcja konfiguracyjna z panelu administracyjnego. Opcja

ta ze względu na uproszczenie została zakomentowana i wpisana w tym miejscu na sztywno.

Page 59: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

59

11.Dodatek 4. Instrukcja dla programisty

Instrukcja zawiera wskazówki dla webmasterów i programistów rozwijających system. System

posiada udokumentowany kod źródłowy aplikacji w postaci komentarzy wykonanych w języku

angielskim. Dodatkowo do systemu została dołączona dokumentacja techniczna zawierająca opis

funkcji (do każdego modułu), która znajduje się na dołączonej płycie DVD (rys. 10.1).

Rys. 10.1. Dołączona dokumentacja projektu javadoc.

Budowa bazy danych

Rys. 10.2. Budowa bazy danych.

Page 60: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

60

Specyfikacja komunikacji z Mózgiem

Rys. 10.3. Komunikacja z Mózgiem poprzez WSDL.

Page 61: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

61

Klient (ActionScript) – diagram klas

Rys. 10.4. Diagram klas modułu klienta.

Page 62: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

62

Serwer Mowy (JavaEE)– diagram klas

Rys. 10.5. Diagram klas Serwera Mowy.

Page 63: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

63

System znaczników.

Aby system mógł poprawnie funkcjonować należy oznaczyć treści portalu, które mają

być uwzględnione w systemie mowy. Realizacja polega na dodaniu znaczników Speech do treści

dokumentów webowych1. Do tego celu zostały przygotowane znaczniki w postaci:

<speech value="SpeechType" weight="SpeechWeight"> treść </speech>

Wartości SpeechType oraz SpeechWeight należy zastąpić tymi z rys. 10.6. opisanymi

w tab. 10.1. i 10.2.

Rys. 10.6. Wartości atrybutów znacznika speech.

Tab. 10.1. Wartości atrybutu SpeechType.

l.p. atrybut opis

1. MENU pozycja z menu

2. TITLE tytuł strony

3. INTRO streszczenie zawartości strony

4. TEXT zawartość strony

5. LINK link do innej strony

6. PEOPLE wykładowca

7. SUBJECT przedmiot/specjalizacja

8. SUBJECT_DATA opis przedmiotu/specjalizacji

Tab. 10.2. Wartości atrybutu SpeechWeight.

l.p. atrybut opis

1. FIRST = 0 element najbardziej istotny

2. SECOND = 1 element umiarkowany

3. THIRD = 2 element najmniej istotny

Dla znaczników typu PEOPLE wymagane są dodatkowe atrybuty zdefiniowane w tab. 10.3.

1 Znaczniki te w czytelnej postaci powinny znaleźć się w wygenerowanych plikach HTML.

Page 64: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

64

Tab. 10.3. Wartości dodatkowych wymaganych atrybutów dla znacznika typu PEOPLE.

l.p. atrybut opis

1. NAME imię i nazwisko

2. DEGREE stopień naukowy

3. FUNCTION obejmowana funkcja

4. URL adres strony WWW zawierającej informacje o

osobie

Dla znaczników typu SUBJECT wymagane są dodatkowe atrybuty zdefiniowane w tab. 10.4.

Tab. 10.4. Wartości dodatkowych wymaganych atrybutów dla znacznika typu SUBJECT.

l.p. atrybut opis

1. NAME nazwa przedmiotu/specjalizacji

2. TYPE przeznaczenie dla specjalizacji

Dla znaczników typu SUBJECT_DATA wymagane są dodatkowe atrybuty zdefiniowane

w tab. 10.5.

Tab. 10.5. Wartości dodatkowych wymaganych atrybutów dla znacznika typu

SUBJECT_DATA.

l.p. atrybut opis

1. NAME nazwa przedmiotu/specjalizacji

2. SUBJECTFORM rodzaj zajęć, np. laboratorium

3. NOOFHOURS liczba godzin w semestrze

4. TEACHERS lista nauczycieli oddzielona znakiem #

5. TAUGHTIN specjalizacja

6. STUDYLEVEL poziom studiów

7. SEMESTER semestr

8. DEPARTMENT wydział

Przykładowy znacznik dla elementu menu pierwszego poziomu:

<speech value="MENU" weight="O">Home Page </speech>

Dodanie postaci Awatara

W celu umożliwienia wydawania i odsłuchiwania komend dla systemu należy dodać postać

Awatara i klienta do portalu internetowego, aby była ona widoczna na wszystkich stronach

w których będziemy korzystali z systemu sterowania głosem. Postać Awatara została wykonana

w technologii Flash, aby ją dodać do strony należy wkleić poniższy fragment kodu na stronę

portalu: <script language="JavaScript" type="text/javascript"> <!-- // Version check for the Flash Player that has the ability to start Player Product Install (6.0r65) var hasProductInstall = DetectFlashVer(6, 0, 65);

Page 65: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

65

// Version check based upon the values defined in globals var hasRequestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision); if ( hasProductInstall && !hasRequestedVersion ) { // DO NOT MODIFY THE FOLLOWING FOUR LINES // Location visited after installation is complete if installation is required var MMPlayerType = (isIE == true) ? "ActiveX" : "PlugIn"; var MMredirectURL = window.location; //document.title = document.title.slice(0, 47) + " - Flash Player Installation"; var MMdoctitle = document.title; AC_FL_RunContent( "src", "playerProductInstall", "FlashVars", "MMredirectURL="+MMredirectURL+'&MMplayerType='+MMPlayerType+'&MMdoctitle='+MMdoctitle+"", "width", "100%", "height", "100%", "align", "middle", "id", "SpeechAvatar", "quality", "high", "bgcolor", "#ffffff", "name", "SpeechAvatar", "allowScriptAccess","sameDomain", "type", "application/x-shockwave-flash", "pluginspage", "http://www.adobe.com/go/getflashplayer" ); } else if (hasRequestedVersion) { // if we've detected an acceptable version // embed the Flash Content SWF when all tests are passed /*AC_FL_RunContent( "src", "#{request.contextPath}/avatar/SpeechAvatar.swf", "flashVars", "client_id=#{session.id}", "width", "215", "height", "138", "align", "middle", "id", "SpeechAvatar", "quality", "high", "bgcolor", "#ffffff", "name", "SpeechAvatar", "allowScriptAccess","sameDomain", "type", "application/x-shockwave-flash", "pluginspage", "http://www.adobe.com/go/getflashplayer" );*/ } else { // flash is too old or we can't detect the plugin var alternateContent = '' + 'This content requires the Adobe Flash Player. ' + '<a href=http://www.adobe.com/go/getflash/>Get Flash</a>'; document.write(alternateContent); // insert non-flash content } // --> </script> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="SpeechAvatar" width="215" height="138" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"> <param name="movie" value="#{request.contextPath}/avatar/SpeechAvatar.swf" /> <param name='flashVars' value='client_id=#{session.id}'/> <param name="quality" value="high" /> <param name="bgcolor" value="#ffffff" />

Page 66: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

66

<param name="allowScriptAccess" value="sameDomain" /> <embed src="#{request.contextPath}/avatar/SpeechAvatar.swf" quality="high" bgcolor="#ffffff" width="215" height="138" name="SpeechAvatar.swf" align="middle" flashVars="client_id=#{session.id}" play="true" loop="false" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"> </embed> </object>

Należy w kodzie zamienić fragment „#{session.id}” na inny generator unikalnego identyfikatora

udostępnionego przez portal.

Konfiguracja systemu rozpoznawania i generowania mowy

Moduły odpowiedzialne za konfigurację rozpoznawania i generowania mowy znajdują się

na Serwerze Mowy. Dokumentacja ich konfiguracji znajduje się na stronach ich producentów

(FreeTTS i Sphinx-4).

Pliki konfiguracyjne:

SpeechServer\src\speech.properties

SpeechServer\src\com\janklimczak\speech\server\recognize\config.xml

SpeechServer\src\com\janklimczak\speech\server\recognize\hello.gram

SpeechServer\src\com\janklimczak\speech\server\recognize\SpeechRecognize.java

SpeechServer\src\com\janklimczak\speech\server\syntetize\SpeechSyntetizer.java

Page 67: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

67

12.Dodatek 5. Listing kodów źródłowych głównych modułów

Dodatek ten zawiera listing głównych kodów źródłowych. Opis działania znajduje się

bezpośrednio przy kodzie w postaci komentarzy w języku angielskim w formacie Javadoc i

ASDoc w zależności odwykorzystanej technologi (Java lub ActionScript). Dodatkowo na płycie

została dołączona pełna wygenerowana dokumentacja w tych powyższych formatach.

Serwer mowy - SpeechServer

SpeechServer\src\com\janklimczak\speech\server\Engine.java:

package com.janklimczak.speech.server;

import com.janklimczak.speech.brain.client.model.Question;

import java.util.Map;

import java.util.concurrent.ConcurrentHashMap;

import org.red5.server.api.IClient;

import org.red5.server.api.IConnection;

import org.red5.server.api.IScope;

import org.red5.server.api.Red5;

import org.red5.server.api.service.IServiceCapableConnection;

import org.red5.server.api.stream.IBroadcastStream;

import org.red5.server.api.stream.IStreamAwareScopeHandler;

import org.red5.server.api.stream.ISubscriberStream;

import org.red5.server.adapter.MultiThreadedApplicationAdapter;

import com.janklimczak.speech.server.audio.ConvertAudio;

import com.janklimczak.speech.server.client.ClientAttribute;

import com.janklimczak.speech.server.client.ClientContainer;

import com.janklimczak.speech.server.speech.ResponseToFlex;

import com.janklimczak.speech.server.speech.Speech;

import com.janklimczak.speech.server.utils.SpeechLogger;

import com.xuggle.mediatool.IMediaReader;

import com.xuggle.mediatool.ToolFactory;

/**

* Speech Server.

*

* @author Jan Klimczak

*/

public class Engine extends MultiThreadedApplicationAdapter implements IStreamAwareScopeHandler {

/** Container for connected clients */

final private Map<String, ClientContainer> connections = new ConcurrentHashMap<String,

ClientContainer>();

/** Logger */

private static SpeechLogger logger = new SpeechLogger(Engine.class);

/** Straem counter */

private int streamCounter = 0;

/** Speech system */

private Speech speech = new Speech();

Page 68: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

68

/**

* Start and initialize Speech Server.

*

* @param app Scope

* @return true if succes

*/

@Override

public boolean appStart(IScope app) {

logger.info("SERVER RTMP ZOSTAL URUCHOMIONY");

this.speech = new Speech();

return super.appStart(app);

}

/**

* Connect client into server.

*

* {@inheritDoc}

* @param conn IConnection

* @param scope IScope

* @param params Client params with client id

* @return true if succes

*/

@Override

public boolean connect(IConnection conn, IScope scope, Object[] params) {

String clientId = params[0].toString();

IClient client = conn.getClient();

client.setAttribute(ClientAttribute.CONNECTION_ID.toString(), clientId);

ClientContainer cContainer;

if (connections.containsKey(clientId)) {

cContainer = connections.get(clientId);

IConnection realConnection = cContainer.getConnection();

if (realConnection.isConnected()) {

// Client is already connected

IClient realClient = realConnection.getClient();

String realClientId = realClient.getId();

client.setId(realClientId);

logger.info("Connect to exsisting client (on-line): " + client.getId(), clientId);

} else {

// Get Client id from his container

client.setId(cContainer.getClientId());

logger.info("Connect to exsisting client (off-line): " + client.getId(), clientId);

}

logger.info("Client is already connected: " + clientId, clientId);

cContainer.setWelcomeMessage(false);

Page 69: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

69

} else {

logger.info("Connected new client: " + clientId, clientId);

cContainer = new ClientContainer();

cContainer.setWelcomeMessage(true);

}

// Actualize client connections for using it with response

cContainer.setClientId(client.getId());

cContainer.setConnection(conn);

connections.put(clientId, cContainer);

// Send greathings message for client

IServiceCapableConnection sc =

(IServiceCapableConnection)connections.get(clientId).getConnection();

if (sc != null) {

sc.invoke("connectionFromServer");

}

return true;

}

/**

* Disconnect client.

*

* {@inheritDoc}

* @param conn IConnection

* @param scope IScope

*/

@Override

public void disconnect(IConnection conn, IScope scope) {

String clientId =

conn.getClient().getAttribute(ClientAttribute.CONNECTION_ID.toString()).toString();

logger.info("Disconnecting client: " + clientId);

super.disconnect(conn, scope);

}

/**

* Gets the client id.

*

* @return the client id

*/

public String getClientId(String connectionId) {

for (IClient client : getClients()) {

if (client.getAttribute(ClientAttribute.CONNECTION_ID.toString()).equals(connectionId)) {

return (String)client.getAttribute(ClientAttribute.CONNECTION_ID.toString());

}

}

logger.debug("Client id: " + Red5.getConnectionLocal().getClient().getId());

return Red5.getConnectionLocal().getClient().getId();

}

/**

* Generate new unique stream name.

*

Page 70: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

70

* @return Stream name

*/

public String getStreamName() {

logger.info("getting a stream name " + streamCounter);

return String.valueOf(streamCounter++);

}

/**

* Execute command into Brain.

*

* @param emotions Avatar emotions

*/

public synchronized void executeCommand(ResponseToFlex emotions) {

if (emotions == null) {

return;

}

Question question = new Question();

question.setE1(emotions.getE1());

question.setE2(emotions.getE2());

question.setE3(emotions.getE3());

question.setE4(emotions.getE4());

IClient client = Red5.getConnectionLocal().getClient();

String clientId = (String)client.getAttribute(ClientAttribute.CONNECTION_ID.toString());

if (connections.containsKey(clientId)) {

ClientContainer cContainer = connections.get(clientId);

if (cContainer.isWelcomeMessage()) {

question.setMessage("welcome");

cContainer.setWelcomeMessage(false);

} else {

question.setMessage("welcome back");

}

} else {

question.setMessage("welcome");

}

this.speech.askBrain(question);

}

/**

* Start live stream recording.

*

* @param stream IBroadcastStream

*/

@Override

public void streamRecordStart(IBroadcastStream stream) {

logger.debug("START Recording stream (RT)");

try {

stream.saveAs(stream.getPublishedName(), false);

} catch (Exception e) {

e.printStackTrace();

}

super.streamRecordStart(stream);

Page 71: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

71

}

/**

* Stop live stream recording.

* Convert recorded audio from flv to wav.

* Recognize command from speech, ask Brain

* and send Answer into client.

*

* @param stream IBroadcastStream

*/

@Override

public void streamBroadcastClose(IBroadcastStream stream) {

logger.debug("STOP Recording stream (RT)");

String file = Settings.STREAM_FOLDER_PATH + stream.getPublishedName();

IMediaReader reader = ToolFactory.makeReader(file + ".flv");

ConvertAudio ca = new ConvertAudio(reader, file + "_in.wav");

ca.setSpeech(speech);

ca.run();

super.streamBroadcastClose(stream);

}

/**

* Start play live stream.

*

* @param stream ISubscriberStream

*/

@Override

public void streamSubscriberStart(ISubscriberStream stream) {

IConnection conn = stream.getConnection();

IClient client = conn.getClient();

logger.debug("START Playing stream (RT)",

client.getAttribute(ClientAttribute.CONNECTION_ID.toString()).toString());

super.streamSubscriberStart(stream);

}

/**

* Stop playing live stream.

*

* @param stream ISubscriberStream

*/

@Override

public void streamSubscriberClose(ISubscriberStream stream) {

IConnection conn = stream.getConnection();

IClient client = conn.getClient();

logger.debug("STOP Playing stream (RT)", client.getId());

super.streamSubscriberClose(stream);

}

}

Page 72: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

72

SpeechServer\src\com\janklimczak\speech\server\recognize\SpeechRecognize.java:

package com.janklimczak.speech.server.recognize;

import com.janklimczak.speech.server.utils.SpeechLogger;

import java.io.File;

import java.net.URL;

import java.util.LinkedList;

import edu.cmu.sphinx.frontend.util.AudioFileDataSource;

import edu.cmu.sphinx.recognizer.Recognizer;

import edu.cmu.sphinx.result.Result;

import edu.cmu.sphinx.util.props.ConfigurationManager;

/**

* Speech recognizer.

*/

public class SpeechRecognize {

/** Logger */

private SpeechLogger logger = new SpeechLogger(SpeechRecognize.class);

/** URL of file to recognize from */

private URL urlAudio;

/** Recognize configuration */

private ConfigurationManager cm;

/** Recognizer */

private Recognizer recognizer;

/** Audio data source */

private AudioFileDataSource audioDataSource;

/** Recognition result */

private Result result;

/**

* Initialize and allocate speech recognizer.

*

*/

public void initialize() {

logger.info("Initialize Recognizer");

URL urlConfig = SpeechRecognize.class.getResource("config.xml");

this.cm = new ConfigurationManager(urlConfig);

this.recognizer = (Recognizer)cm.lookup("recognizer");

this.recognizer.allocate();

this.audioDataSource = (AudioFileDataSource)cm.lookup("audioFileDataSource");

logger.info("Recognizer initialized");

}

/**

Page 73: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

73

* Recognize speech into one sentence.

*

* @param file File to recognize.

* @return Recognized text

*/

public String recognizeFull(String file) {

LinkedList<String> recognized = recognize(file);

if (recognized == null) {

return null;

} else {

String result = "";

for (String s : recognized) {

result += " " + s.trim() + " ";

}

return result.trim();

}

}

/**

* Recognize text from file.

*

* @param file File to recognize

* @return Recognized word list

*/

public LinkedList<String> recognize(String file) {

LinkedList<String> resultSpeeak = new LinkedList<String>();

logger.info("Start recognition");

File myfile = new File(file);

System.out.println("Open: " + file);

if (!myfile.exists()) {

logger.error("file not exsists");

}

if (!myfile.canRead()) {

logger.error("cant read recorded file");

}

audioDataSource.setAudioFile(myfile, null);

boolean none = false;

while ((result = recognizer.recognize()) != null) {

String resultText = result.getBestResultNoFiller();

if (resultText != null && !resultText.isEmpty()) {

logger.info("You said: " + resultText);

resultSpeeak.add(resultText);

} else {

logger.info("I don't understand You.");

none = true;

}

}

logger.info("Finish recognition");

Page 74: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

74

if (none) {

return null;

} else {

return resultSpeeak;

}

}

/**

* Deinitialize speech recognizer.

*/

public void deinitialize() {

this.recognizer.deallocate();

}

/**

* Get speech recognizing result.

*

* @return Speech recognizing result

*/

public Result getResult() {

return result;

}

}

}

SpeechServer\src\com\janklimczak\speech\server\speech\Speech.java:

package com.janklimczak.speech.server.speech;

import com.janklimczak.speech.brain.client.BrainServicePortClient;

import com.janklimczak.speech.brain.client.model.Answer;

import com.janklimczak.speech.brain.client.model.Question;

import com.janklimczak.speech.server.client.ClientAttribute;

import com.janklimczak.speech.server.recognize.SpeechRecognize;

import com.janklimczak.speech.server.syntetize.SpeechSyntetizer;

import com.janklimczak.speech.server.utils.SpeechLogger;

import java.util.LinkedList;

import org.red5.io.utils.ObjectMap;

import org.red5.server.api.IConnection;

import org.red5.server.api.Red5;

import org.red5.server.api.service.IPendingServiceCall;

import org.red5.server.api.service.IPendingServiceCallback;

import org.red5.server.api.service.IServiceCapableConnection;

import org.red5.server.api.service.ServiceUtils;

/**

* Speech service.

*

* @author Jan Klimczak

*/

public class Speech implements IPendingServiceCallback {

/** Logger */

private static SpeechLogger logger = new SpeechLogger(Speech.class);

/** Brain service client */

private static BrainServicePortClient brainService = new BrainServicePortClient();

Page 75: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

75

/** Speech recognizer */

private SpeechRecognize recognizer = new SpeechRecognize();

/** Speech syntetizer */

private SpeechSyntetizer syntetizer = new SpeechSyntetizer();

/** Stream counter */

private int streamCounter = 0;

/** Result */

private String result;

/** Client id */

private String clientId;

/**

* Initialize speech service.

*/

public Speech() {

super();

this.initialize();

}

/**

* Initialize speech syntetizer and recognizer.

*/

public void initialize() {

this.syntetizer.initialize();

this.recognizer.initialize();

}

/**

* Get Avatar emotions from client response.

* Ask Brain.

*

* @param call IPendingServiceCall

*/

@Override

public void resultReceived(IPendingServiceCall call) {

call.unregisterCallback(this);

Question question = new Question();

question.setMessage(result);

if (call.isSuccess()) {

ObjectMap emotions = (ObjectMap)call.getResult();

question.setE1((Integer)emotions.get("e1"));

question.setE2((Integer)emotions.get("e2"));

question.setE3((Integer)emotions.get("e3"));

question.setE4((Integer)emotions.get("e4"));

logger.debug("Load Avatar state into Server for Brain.");

askBrain(question);

} else {

logger.error("Cannot get Awatar state from client.");

Page 76: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

76

askBrain(question);

}

}

/**

* Ask Brain by web-servcie.

* Get Avatar emotions from client.

*

* @param question Question to ask.

*/

public void askBrain(Question question) {

IConnection conn = Red5.getConnectionLocal();

Object requestUrl = conn.getConnectParams().get("pageUrl");

if (requestUrl != null) {

question.setUrl(requestUrl.toString());

}

Answer answer = brainService.askQuestion(question);

ResponseToFlex response = new ResponseToFlex();

response.readBrainAnswer(answer);

ServiceUtils.invokeOnConnection("responseFromServer", new Object[] { response });

syntetizer.speechNow(clientId, answer, getStreamName());

}

/**

* Generate speech.

*

* @param clientId Client id

* @param text Text to generate speech

* @param streamName Stream name to save file

*/

public void speechNow(String clientId, String text, String streamName) {

this.syntetizer.speechNow(clientId, text, streamName);

}

/**

* Generate speech.

*

* @param clientId Client id

* @param answer Answer

* @param streamName Stream name to save file

*/

public void speechNow(String clientId, Answer answer, String streamName) {

this.syntetizer.speechNow(clientId, answer, streamName);

}

/**

* Recognize text from audio file.

*

* @param file File to recognize

* @return Recognize word list

*/

public LinkedList<String> recognize(String file) {

return this.recognizer.recognize(file);

}

/**

Page 77: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

77

* Recognize text from audio file and ask Brain.

*

* @param file File to recognize

*/

public void recognizeAndExecute(String file) {

result = this.recognizer.recognizeFull(file);

clientId =

(String)Red5.getConnectionLocal().getClient().getAttribute(ClientAttribute.CONNECTION_ID.toString());

IServiceCapableConnection sc = (IServiceCapableConnection)Red5.getConnectionLocal();

if (sc != null) {

sc.invoke("getAwatarState", this);

} else {

Question question = new Question();

question.setMessage(result);

askBrain(question);

}

}

/**

* Generate unique stream name.

*

* @return Stream name.

*/

private String getStreamName() {

logger.info("getting a stream name " + streamCounter);

return String.valueOf(streamCounter++ + "_out");

}

}

SpeechServer\src\com\janklimczak\speech\server\syntetize\SpeechSyntetizer.java:

package com.janklimczak.speech.server.syntetize;

import com.janklimczak.speech.brain.client.model.Answer;

import com.janklimczak.speech.server.Settings;

import com.janklimczak.speech.server.audio.ConvertAudio;

import com.janklimczak.speech.server.audio.SaveToFile;

import com.janklimczak.speech.server.utils.SpeechLogger;

import org.red5.server.api.service.ServiceUtils;

import com.sun.speech.freetts.FreeTTS;

import com.sun.speech.freetts.Voice;

import com.sun.speech.freetts.VoiceManager;

import com.xuggle.mediatool.IMediaReader;

import com.xuggle.mediatool.ToolFactory;

/**

* Speech syntetizer.

*

* @author Jan Klimczak

*/

public class SpeechSyntetizer {

/** Voice */

Page 78: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

78

private Voice voice;

/** FreeTTS engine */

private FreeTTS freetts;

/** Voice manager */

private VoiceManager vm;

/** Logger */

private SpeechLogger logger = new SpeechLogger(SpeechSyntetizer.class);

/**

* Initialize speech synthetizer.

*/

public void initialize() {

logger.info("Initialize Syntetizer");

System.setProperty("com.sun.speech.freetts.voice.defaultAudioPlayer",

"com.janklimczak.speech.server.audio.SaveToFile");

this.vm = VoiceManager.getInstance();

this.voice = vm.getVoice("kevin16");

this.logger.debug("Initialize Voice");

if (voice == null) {

this.logger.error("Voice is null");

throw new RuntimeException("Voice is null");

}

if (voice != null) {

this.voice.allocate();

}

this.freetts = new FreeTTS(voice);

logger.info("Syntetizer initialized");

}

/**

* Denitialize speech synthetizer.

*/

public void deinitialize() {

logger.info("De-Initialize Syntetizer");

this.freetts.shutdown();

}

/**

* Speech.

*

* @param clientId Client id.

* @param text Text to speech.

* @param streamName Stream name to save file.

*/

public void speech(String clientId, String text, String streamName) {

Answer answer = new Answer();

answer.setMessage(text);

this.speech(clientId, answer, streamName);

Page 79: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

79

}

/**

* Speech with emotions.

* Convert wav to mp3 in new thread.

* Send request to speak for client.

*

* @param clientId Client id.

* @param answer Text to speech from Answer.

* @param streamName Stream name to save file.

*/

public void speech(String clientId, Answer answer, String streamName) {

String text = answer.getMessage();

SaveToFile sfap;

byte b[] = text.getBytes();

if (b == null) {

logger.error("No byte array", clientId);

return;

}

String file = Settings.STREAM_FOLDER_PATH + streamName;

IMediaReader reader = null;

ConvertAudio ca;

try {

sfap = (SaveToFile)voice.getDefaultAudioPlayer();

sfap.reset();

sfap.setSpeechLength(b.length);

sfap.setFileName(file + ".wav");

sfap.write(b);

this.logger.debug("Generate message", clientId);

float volume = (float)0.85;

float pitch = 100;

float duration = 1;

float pitchShift = 1;

float pitchRange = 1;

float rate = 120;

// Generate emotions 1

if (answer.getStateE1() != null) {

Integer e1 = answer.getStateE1();

// ------- Volume

float newVolume;

if (e1 > 100) {

newVolume = (float)((e1 - 100) + 1) / 100;

volume -= newVolume;

} else {

newVolume = (float)(e1 + 1) / 100;

volume += newVolume;

}

// ------- Pitch

Page 80: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

80

float newPitch;

if (e1 > 100) {

newPitch = (float)((e1 - 100) + 1) / 3;

pitch -= newPitch;

} else {

pitch = e1;

}

}

// Generate emotions 2

if (answer.getStateE2() != null) {

Integer e2 = answer.getStateE2();

// ------- Duration

float newDuration;

if (e2 > 100) {

newDuration = (float)((e2 - 100) + 1) / 100;

duration += newDuration;

} else {

newDuration = (float)((e2 - 100) + 1) / 200;

duration -= newDuration;

}

}

// Generate emotions 3

if (answer.getStateE3() != null) {

Integer e3 = answer.getStateE3();

// ------- Pitch Shift

float newPitchShift;

if (e3 > 100) {

newPitchShift = (float)((e3 - 100) + 1) / 75;

pitchShift += newPitchShift;

} else {

newPitchShift = (float)((e3 - 100) + 1) / 250;

pitchShift -= newPitchShift;

}

}

// Generate emotions 4

if (answer.getStateE4() != null) {

Integer e4 = answer.getStateE4();

// ------- Pitch Range

//pitchRange = 101 - e4;

pitchRange = 1;

// ------- Rate

float newRate;

if (e4 > 100) {

newRate = (float)((e4 - 100) + 1) / 2;

rate -= newRate;

} else {

newRate = (float)((e4 - 100) + 1) * 2;

rate += newRate;

}

Page 81: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

81

}

this.voice.setVolume(volume);

this.voice.setPitch(pitch);

this.voice.setDurationStretch(duration);

this.voice.setPitchShift(pitchShift);

this.voice.setPitchRange(pitchRange);

this.voice.setRate(rate);

this.voice.speak(text);

sfap.close();

this.logger.debug("Save generated message to server", clientId);

this.logger.debug("Start converting message to stream", clientId);

reader = ToolFactory.makeReader(file + ".wav");

reader.open();

ca = new ConvertAudio(reader, file + ".mp3");

ca.run();

} catch (Exception e) {

reader.close();

e.printStackTrace();

this.logger.error("Error generating message", clientId);

}

}

/**

* Speech now and request it into client.

*

* @param clientId Client id

* @param answer Answer

* @param streamName File to save

*/

public void speechNow(String clientId, Answer answer, String streamName) {

this.speech(clientId, answer, streamName);

Object[] param = new Object[1];

param[0] = streamName;

ServiceUtils.invokeOnConnection("speak", param);

}

/**

* Speech now and request it into client.

*

* @param clientId Client id

* @param text Text to speech

* @param streamName File to save

*/

public void speechNow(String clientId, String text, String streamName) {

Answer answer = new Answer();

answer.setMessage(text);

this.speechNow(clientId, answer, streamName);

Page 82: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

82

}

}

Klient - SpeechAvatar

SpeechAvatar\src\com\janklimczak\speech\SpeechEngine.as:

package com.janklimczak.speech

{

import com.janklimczak.speech.avatar.Avatar

import com.janklimczak.speech.Settings;

import com.janklimczak.speech.communication.CommunicateWithServer;

import com.janklimczak.speech.communication.ServiceConnector;

import com.janklimczak.speech.device.SpeechMicrophone;

import com.janklimczak.speech.state.AwatarState;

import com.janklimczak.speech.stream.Stream;

import com.janklimczak.speech.utils.Logger;

import flash.events.NetStatusEvent;

import flash.net.Responder;

import mx.controls.Alert;

import mx.core.FlexGlobals;

import mx.events.FlexEvent;

import mx.utils.OnDemandEventDispatcher;

/**

* Main Avatar Client Engine.

*

* @author Jan Klimczak

*

*/

public class SpeechEngine

{

/** Avatar state - store and manage Avatar emotions */

[Bindable]

public var awatarState:AwatarState;

/** Graphic Avatar instance */

[Bindable]

public var avatar:Avatar;

/** Manage communication with Speech Server */

public var communicateWithServer:CommunicateWithServer;

/** Logger */

public var logger:Logger;

/** Application settings */

private var settings:Settings;

/** Manage live streams with Speech Server */

private var stream:Stream;

Page 83: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

83

/** Client microphone instance */

private var microphone:SpeechMicrophone;

// INITIALIZE ------------------------------------------------------------------

/**

* Initialize whole Client Avatar engine.

*

*/

public function SpeechEngine() {

this.initializeEngine();

this.awatarState.makeLive();

this.communicateWithServer.connId = this.settings.getClientId();

this.communicateWithServer.connectToService(onConnectionNetStatus);

this.initializeDevices();

}

/**

* Initialize engine.

*

* Make Avatar alive (forgetting function).

* Connect with Speech Server.

*

*/

private function initializeEngine():void {

this.logger = new Logger();

this.logger.openMessageLog();

this.microphone = new SpeechMicrophone();

this.settings = new Settings();

this.awatarState = new AwatarState();

this.communicateWithServer = new

CommunicateWithServer(this.settings.data.rtmpService, this.awatarState);

}

/**

* Initialize microphone.

*/

private function initializeDevices():void {

this.microphone.initialize();

}

/**

* Initialize live stream and connect with Speech Server.

*/

private function initializeStream():void {

this.stream = new Stream(this.communicateWithServer.connection);

this.stream.initialize(this.microphone.mic, onStreamStatus);

this.communicateWithServer.setStream(this.stream);

}

Page 84: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

84

// GLOBAL LISTNERS ------------------------------------------------------------

/**

* Awaiting connection with Speech Server.

* When connected initialize stream.

*

* @param event NetStatusEvent

*

*/

private function onConnectionNetStatus(event:NetStatusEvent) : void {

if(event.info.code == "NetConnection.Connect.Success") {

logger.info('Successfull connected to RTMP server');

this.communicateWithServer.connectionStatus = true;

this.initializeStream();

} else {

logger.error('Error: connect to RTMP server (' + event.info.code + ')');

}

}

/**

* Awaiting stream status and log that into logger.

*

* @param e NetStatusEvent

*

*/

private function onStreamStatus(e:NetStatusEvent) : void {

if ( e.info.code == "NetStream.Publish.Start" ) {

logger.info('Started recording to server (' + e.info.code + ')');

} else if (e.info.code == "NetStream.Record.NoAccess") {

logger.error('You don\'t have access to microphone');

}

this.logger.debug( e.info.code );

}

// ENGINE ---------------------------------------------------------------------

/**

* Start recording speeak into Speech Server.

*

*/

public function recordStart_clickHandler():void

{

logger.info("Initialize START Recording");

// if a stream is already playing, close it

if ( this.stream.getNetStream() != null ) this.stream.getNetStream().close();

this.stream.getNetStream().publish(communicateWithServer.connId, "record");

}

/**

* Stop recording speeak into Speech Server.

*

*/

Page 85: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

85

public function recordStop_clickHandler():void

{

logger.info("Initialize STOP Recording");

if ( this.stream.getNetStream() != null ) this.stream.getNetStream().close( );

}

}

}

SpeechAvatar\src\com\janklimczak\speech\avatar\AvatarEmotions.as:

package com.janklimczak.speech.avatar

{

import com.janklimczak.speech.avatar.Avatar;

import com.janklimczak.speech.state.AwatarState;

import flash.display.MovieClip;

import flash.events.Event;

import flash.events.TimerEvent;

import flash.geom.ColorTransform;

import flash.utils.Timer;

/**

* Animate avatar emotions into Graphic Avatar instance.

*

* @author Jan Klimczak

*

*/

public class AvatarEmotions {

/** Graphic Avatar instance */

[Bindable]

public var avatar:Avatar;

/** Avatar state,emotions */

[Bindable]

public var state:AwatarState;

/** Counter */

public var counter:int = 0;

/** Timer used for animating changes */

private var myTimer:Timer = new Timer(25);

/** Is Avatar curently speaking */

private var speaking:Boolean = false;

/** Factor of speed animation */

private var speed:int = 10;

/**

* Initialize and start timers for animating.

*

* @param avatar Graphic Avatar instance.

*

*/

public function AvatarEmotions(avatar:Avatar) {

this.avatar = avatar;

Page 86: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

86

this.myTimer.start();

this.myTimer.addEventListener(TimerEvent.TIMER, timerHandler);

}

/**

* Animate mouth every frame.

* Use speed factor to make it slower or faster.

*

* @param e TimerEvent

*

*/

private function timerHandler(e:TimerEvent):void {

if (this.avatar.isLoaded) {

if (this.speaking) {

if (this.counter > (speed/4) ) {

this.avatar.mouth.nextFrame();

this.counter = 0;

} else {

this.counter++;

}

} else {

if (this.avatar.mouth.currentFrame > 50) {

this.avatar.mouth.gotoAndStop(1);

} else if (this.avatar.mouth.currentFrame != 1) {

this.avatar.mouth.nextFrame();

}

}

}

}

/**

* Connect Avatar state with emotions into this module.

*

* @param state Awatar state

*

*/

public function connectState(state:AwatarState):void {

this.state = state;

}

/**

* Update Graphic Avatar to display changes for client.

*

*/

public function updateGraphicAvatar():void {

if (this.avatar.isLoaded) {

this.updateSatisfaction();

this.updateExcitement();

this.updateJoy();

}

}

Page 87: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

87

/**

* Calculate satisfaction changes based on Avatar state.

*

*/

private function updateSatisfaction():void {

var factor:int = this.state.e2;

var newColor:ColorTransform = new ColorTransform();

newColor.redMultiplier = 0;

newColor.redOffset = factor + 155;

newColor.greenMultiplier = 0;

newColor.greenOffset = factor + 100;

newColor.blueMultiplier = 0;

newColor.blueOffset = factor + 70;

this.avatar.face.transform.colorTransform = newColor;

}

/**

* Calculate excitement changes based on Avatar state.

*

*/

private function updateExcitement():void {

var factor:Number = (this.state.e3 + 1) / 100 ;

factor = Math.abs(factor - 2);

this.avatar.eyeLeft.scaleY = factor;

this.avatar.eyeRight.scaleY = factor;

}

/**

* Calculate joy changes based on Avatar state.

*

*/

private function updateJoy():void {

this.speed = ((this.state.e3 + 1) / 10) + 1;

}

/**

* Start speak.

*

*/

public function startSpeak():void {

this.speaking = true;

}

/**

* Stop speak.

*

*/

public function stopSpeak():void {

this.speaking = false;

}

}

}

SpeechAvatar\src\com\janklimczak\speech\communication\CommunicateWithServer.as:

Page 88: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

88

package com.janklimczak.speech.communication

{

import com.janklimczak.speech.state.AwatarState;

/**

* Module responsible for bi-directional communication with Speech Server.

*

* @author Jan Klimczak

*

*/

public class CommunicateWithServer extends ResponseToServer {

/**

* Constructor.

*

* @param serviceAddress Address of RTMP service of Speech Server.

* @param awatarState Avatar state.

*

*/

public function CommunicateWithServer(serviceAddress:String, awatarState:AwatarState) {

super(serviceAddress, awatarState);

}

}

}

SpeechAvatar\src\com\janklimczak\speech\communication\ResponseFromServer.as:

package com.janklimczak.speech.communication

{

import com.janklimczak.speech.model.ResponseToFlex;

import com.janklimczak.speech.state.AwatarState;

import com.janklimczak.speech.state.Emotions;

import com.janklimczak.speech.utils.Logger;

import flash.events.AsyncErrorEvent;

import flash.events.NetStatusEvent;

import flash.events.TimerEvent;

import flash.net.NetStreamPlayOptions;

import flash.net.Responder;

import flash.utils.Timer;

import mx.collections.ArrayCollection;

/**

* Manage responses from Speech Server.

* Reacting for response from server.

*

* @author Jan Klimczak

*

*/

public class ResponseFromServer extends ServiceConnector {

/** Timer for re-playing audio from Speech Server */

private var myTimer:Timer = new Timer(500, 5);

/** Streeam name to play from Speech Server */

private var sreamName:String = "0";

/**

Page 89: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

89

* Constructor.

*

* @param serviceAddress Address of RTMP service of Speech Server.

* @param awatarState Avatar state.

*

*/

public function ResponseFromServer(serviceAddress:String, awatarState:AwatarState) {

super(serviceAddress, awatarState);

}

/**

* Request from Sppech Server sent after connect client.

* Send request to Speech Server to generate welcome message.

*

*/

public function connectionFromServer():void {

this.logger.info('Greathings from RTMP server', true);

var emotions:ResponseToFlex = new ResponseToFlex();

emotions.e1 = awatarState.e1;

emotions.e2 = awatarState.e2;

emotions.e3 = awatarState.e3;

emotions.e4 = awatarState.e4;

var responseFromServerResponder:Responder = new Responder(null);

this.connection.call("executeCommand", responseFromServerResponder, emotions);

}

/**

* Request spaek audio from Speech Server.

* 5 time re-try playing in time if engine is no ready.

*

* @param streamName Audio file to play

*/

public function speak(streamName:String):void {

this.sreamName = streamName;

this.logger.info("Request speak message from server");

if ( this.stream != null ) {

// fs a stream is already playing, close it

this.play();

} else {

this.logger.info("Net stream is not initialised yet, will try again soon");

myTimer.start();

myTimer.addEventListener(TimerEvent.TIMER, timerHandler);

myTimer.addEventListener(TimerEvent.TIMER_COMPLETE,

completeHandler);

}

}

/**

* Stop play audio.

*

*/

public function stop():void {

this.stream.getNetStream().close();

}

Page 90: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

90

/**

* Get current Avatar State (emotions).

*

* @return Avatar Emotions

*

*/

public function getAwatarState():Emotions {

this.logger.info('Sending Awatar State into Server', true);

var emotions:Emotions = new Emotions();

emotions.e1 = awatarState.e1;

emotions.e2 = awatarState.e2;

emotions.e3 = awatarState.e3;

emotions.e4 = awatarState.e4;

return emotions;

}

/**

* Take response form Speech Server.

* This response is mainlz generated in the Brain.

*

* Change Avatar state and redirect to other page based on response.

*

* @param obj Message from Speech Server.

*

*/

public function responseFromServer(obj:*):void {

logger.debug("Get request message from the Brain", true);

var response:ResponseToFlex = new ResponseToFlex();

response.convertToResponseObject(obj);

if (response.isRedirect) {

redirectToPage(response.redirectPage);

logger.info('Redirect to page: ' + response.redirectPage);

}

awatarState.actualizeState(response);

}

/**

* Log message from Speech Server.

*

* @param message Message to log

* @param type Mesage tzpe

*

*/

public function messageFromServer(message:String, type:String = "info"):void {

switch (type) {

case "debug" : logger.debug(message, true); break;

case "info" : logger.info(message, true); break;

case "warning" : logger.warning(message, true); break;

case "error" : logger.error(message, true); break;

default: logger.info(message, true);

}

}

Page 91: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

91

/**

* Feedback about playing audio file.

*

* @param message Audio file info

*

*/

public function onMetaData ( message:Object ):void {

logger.info("Fetched meta data about audio", true);

for ( var key:* in message ) {

switch (key) {

case "duration" : logger.debug( "Audio file duration : " + message[key]

, true); break;

}

}

}

/**

* Feedback about playing audio file.

*

* @param message Audio file info

*

*/

public function onPlayStatus ( message:Object ):void {

logger.info("Fetched audio status", true);

for ( var key:* in message ) {

switch (key) {

case "bytes" : logger.debug("Audio file size : " + message[key] , true);

break;

}

}

}

/**

* Other audio file info.

* Not implemented.

*

* @param message Audio file info

*

*/

public function onBWCheck ( message:Object ):void { }

/**

* Other audio file info.

* Not implemented.

*

* @param message Audio file info

*

*/

public function onBWDone ( message:Object ):void { }

/**

* Stop playing listener. Send command to Avatar

* to stop speaking (animation).

*

* @param event NetStatusEvent

*

*/

private function stopPlayingListener(event:NetStatusEvent):void {

Page 92: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

92

if(event.info.code == "NetStream.Play.Complete"

|| event.info.code == "NetStream.Play.Stop"

|| event.info.code == "NetConnection.Connect.Closed") {

this.awatarState.avatarEmotions.stopSpeak();

}

}

/**

* Play audio from Speech Server in Real Time.

* Start and stop animate Avatar to speaking.

*

*/

private function play():void {

this.stream.getNetStream().close( );

this.stream.getNetStream().play('mp3:' + this.sreamName, -2, -1 );

this.stream.getNetStream().inBufferSeek = false;

this.stream.getNetStream().bufferTime = 0;

this.stream.getNetStream().addEventListener(NetStatusEvent.NET_STATUS,

stopPlayingListener);

this.awatarState.avatarEmotions.startSpeak();

}

/**

* Try to speak again.

*

* @param e TimerEvent

*

*/

private function timerHandler(e:TimerEvent):void{

this.logger.info("Try to speak again");

if ( this.stream != null ) {

myTimer.stop();

myTimer.reset();

this.play();

}

}

/**

* Stop timer if is not possible to start play audio in specified time.

*

* @param e TimerEvent

*

*/

private function completeHandler(e:TimerEvent):void {

this.logger.error("Net stream is not initialised.");

myTimer.stop();

myTimer.reset();

}

}

}

Page 93: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

93

SpeechAvatar\src\com\janklimczak\speech\state\AwatarState.as:

package com.janklimczak.speech.state

{

import com.janklimczak.speech.avatar.Avatar;

import com.janklimczak.speech.Settings;

import com.janklimczak.speech.avatar.AvatarEmotions;

import com.janklimczak.speech.model.ResponseToFlex;

import com.janklimczak.speech.utils.Logger;

import flash.events.TimerEvent;

import flash.external.ExternalInterface;

import flash.net.SharedObject;

import flash.utils.Timer;

/**

* Awatar state, emotions.

*

* @author Jan Klimczak

*

*/

public class AwatarState {

/**Happines */

[Bindable]

public var e1:int;

/** Satisfaction */

[Bindable]

public var e2:int;

/** Excitement */

[Bindable]

public var e3:int;

/** Joy */

[Bindable]

public var e4:int;

/** Avatar state, emotions instance */

public var avatarEmotions:AvatarEmotions;

/** Emotions limit */

private const E_LIMIT:int = 200;

/** Logger */

private var logger:Logger = new Logger();

/** Application settings */

private var settings:Settings;

/** Current timestamp */

private var timestamp:Date;

/** Container to store Avatar state, emotions */

private var so:SharedObject;

/**

* Initialize Avatar state, emotions.

Page 94: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

94

* Create new emotions or load it if already exists.

*

*/

public function AwatarState():void {

this.so = SharedObject.getLocal("mind");

if (so.data.e == null) {

this.e1 = 100;

this.e2 = 100;

this.e3 = 100;

this.e4 = 100;

this.timestamp = new Date();

so.data.e = this;

so.flush();

} else {

this.e1 = this.so.data.e.e1;

this.e2 = this.so.data.e.e2;

this.e3 = this.so.data.e.e3;

this.e4 = this.so.data.e.e4;

this.timestamp = this.so.data.e.timestamp;

}

this.settings = new Settings();

if (this.settings.data.infoShowWindow) {

ExternalInterface.call('openWindowInfo');

}

}

/**

* Connect Avatar instance.

*

* @param avatar Avatar instance.

*

*/

public function connectAvatar(avatar:Avatar):void {

this.avatarEmotions = new AvatarEmotions(avatar);

this.avatarEmotions.connectState(this);

logger.info("Connected emotions to Graphic Awatar");

}

/**

* Update Avatar state, emotions.

*

* @param state Avatar state

*

*/

public function actualizeState(state:ResponseToFlex):void {

this.so = SharedObject.getLocal("mind");

if ((this.e1 += state.e1) <= E_LIMIT)

this.e1 = this.so.data.e.e1 += state.e1;

if ((this.e2 += state.e2) <= E_LIMIT)

this.e2 = this.so.data.e.e2 += state.e2;

if ((this.e3 += state.e3) <= E_LIMIT)

this.e3 = this.so.data.e.e3 += state.e3;

Page 95: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

95

if ((this.e4 += state.e4) <= E_LIMIT)

this.e4 = this.so.data.e.e4 += state.e4;

this.timestamp = this.so.data.e.timestamp = new Date();

so.flush();

logger.debug("Emotion/State 1 update : " + state.e1, true);

logger.debug("Emotion/State 2 update : " + state.e2, true);

logger.debug("Emotion/State 3 update : " + state.e3, true);

logger.debug("Emotion/State 4 update : " + state.e4, true);

}

/**

* Make live for Avatar.

* Forgetting function.

*

*/

public function makeLive():void {

var myTimer:Timer = new Timer(500);

myTimer.addEventListener("timer", timerHandler);

myTimer.start();

}

/**

* Check if client is in Normal State.

*

* @return true if is in normal state othervise return false

*/

private function isNormalized():Boolean {

if (this.e1 == 100 && this.e2 == 100 && this.e3 == 100 && this.e4 == 100) {

return true;

} else {

return false;

}

}

/**

* Calculate next normalized factor.

*

* @return calculated normalize factor based on current e.

*/

private function normalizeMind(e:int):int {

if (e >= 150) {

return -2;

} else if (e >= 100) {

return -1;

} else if (e >= 50) {

return 1;

} else {

return 2;

}

}

/**

* Update Avatar state.

*

*/

private function changeClientState():void {

/**

Page 96: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

96

* Based on current Client state make changes to client.

* If Client have bigger state then make bigger changes.

*

* Do it indentpendent for each mind state.

*/

this.e1 = this.so.data.e.e1 += normalizeMind(this.e1);

this.e2 = this.so.data.e.e2 += normalizeMind(this.e2);

this.e3 = this.so.data.e.e3 += normalizeMind(this.e3);

this.e4 = this.so.data.e.e4 += normalizeMind(this.e4);

this.timestamp = this.so.data.e.timestamp = new Date();

so.flush();

if (this.settings.data.infoShowWindow) {

ExternalInterface.call('updateE',this.e1,this.e2,this.e3,this.e4);

}

}

/**

* When active Client will back to normal state durng time process.

* Also Graphic Avatar is updated.

*

*/

public function timerHandler(event:TimerEvent):void {

this.changeClientState();

if (this.avatarEmotions != null) {

this.avatarEmotions.updateGraphicAvatar();

}

}

}

}

Model danych – SpeechModel

SpeechModel\src\com\janklimczak\speech\model\Pages.java:

package com.janklimczak.speech.model;

import java.io.Serializable;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.Id;

import javax.persistence.NamedQueries;

import javax.persistence.NamedQuery;

/**

* Page entity.

*

* @author Jan Klimczak

*/

@Entity

@NamedQueries( { @NamedQuery(name = "Pages.findAll", query = "select o from Pages o") })

public class Pages implements Serializable {

Page 97: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

97

/** Id */

@Id

@Column(nullable = false, length = 256)

private String url;

/** Page number */

@Column(name = "PAGE_NUMBER", nullable = false)

private Integer pageNumber;

public Pages() {}

public Pages(String url, Integer pageNumber) {

this.pageNumber = pageNumber;

this.url = url;

}

public Integer getPageNumber() {

return pageNumber;

}

public void setPageNumber(Integer pageNumber) {

this.pageNumber = pageNumber;

}

public String getUrl() {

return url;

}

public void setUrl(String url) {

this.url = url;

}

}

SpeechModel\src\com\janklimczak\speech\model\Speech.java:

package com.janklimczak.speech.model;

import java.io.Serializable;

import java.math.BigDecimal;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

import javax.persistence.JoinColumn;

import javax.persistence.ManyToOne;

import javax.persistence.NamedQueries;

import javax.persistence.NamedQuery;

import javax.persistence.SequenceGenerator;

import javax.persistence.Table;

/**

* Speech entity.

*

* @author Jan Klimczak

*/

@Entity

Page 98: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

98

@NamedQueries( { @NamedQuery(name = "Speech.findAll", query = "select o from Speech o") })

@Table(name = "SPEECH")

public class Speech implements Serializable {

/** Id */

@Id

@SequenceGenerator(name = "SPEECH_ID", sequenceName = "SPEECH_ID", allocationSize = 1)

@GeneratedValue(generator = "SPEECH_ID", strategy = GenerationType.SEQUENCE )

@Column(nullable = false)

private BigDecimal id;

/** Message/text */

@Column(nullable = false)

private String text;

/** Speech type */

@Column(nullable = false)

private SpeechType type;

/** Speech weight/importance */

@Column(nullable = false)

private SpeechWeight weight;

/** Corresponded pages */

@ManyToOne

@JoinColumn(name = "URL")

private Pages pages;

public Speech() {}

public Speech(Pages page, SpeechType type, SpeechWeight weight, String text) {

this.text = text;

this.type = type;

this.pages = page;

this.weight = weight;

}

public BigDecimal getId() {

return id;

}

public void setId(BigDecimal id) {

this.id = id;

}

public String getText() {

return text;

}

public void setText(String text) {

this.text = text;

}

public SpeechType getType() {

return type;

}

public void setType(SpeechType type) {

this.type = type;

}

Page 99: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

99

public SpeechWeight getWeight() {

return weight;

}

public void setWeight(SpeechWeight weight) {

this.weight = weight;

}

public Pages getPages() {

return pages;

}

public void setPages(Pages pages) {

this.pages = pages;

}

}

SpeechModel\src\com\janklimczak\speech\model\SpeechType.java:

package com.janklimczak.speech.model;

/**

* Speech type.

*

* @author Jan Klimczak

*/

public enum SpeechType {

MENU,

TITLE,

INTRO,

TEXT,

LINK,

PEOPLE,

SUBJECT,

SUBJECT_DATA

}

SpeechModel\src\com\janklimczak\speech\facade\Utils.java:

package com.janklimczak.speech.facade;

import java.util.Hashtable;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

public class Utils {

public static SpeechFacade getSpeechFacade() throws NamingException {

final Context context = getInitialContext();

return (SpeechFacade)context.lookup("Brain-SpeechModel-

SpeechFacade#com.janklimczak.speech.facade.SpeechFacade");

}

public static Context getInitialContext() throws NamingException {

Hashtable env = new Hashtable();

// WebLogic Server 10.x connection details

env.put( Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory" );

env.put(Context.PROVIDER_URL, "t3://127.0.0.1:7001");

return new InitialContext( env );

Page 100: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

100

}

}

Mózg – BrainService

BrainService\src\com\janklimczak\speech\brain\BrainService.java:

package com.janklimczak.speech.brain;

import com.janklimczak.speech.facade.SpeechFacade;

import com.janklimczak.speech.facade.Utils;

import com.janklimczak.speech.model.Message;

import com.janklimczak.speech.model.MessageType;

import java.util.Random;

import javax.jws.WebService;

import javax.naming.NamingException;

import javax.xml.bind.annotation.XmlSeeAlso;

import javax.xml.ws.BindingType;

import javax.xml.ws.soap.SOAPBinding;

/**

* Brain service.

*

* @author Jan Klimczak

*/

@WebService(serviceName = "BrainService", targetNamespace =

"http://com.janklimczak.speech.brainservice/",

portName = "BrainServicePort")

@BindingType(SOAPBinding.SOAP12HTTP_BINDING)

@XmlSeeAlso( { Answer.class, Question.class })

public class BrainService {

/** Speech facade */

private SpeechFacade speechFacade;

/**

* Constructor.

*

* @throws NamingException Throw when is not posible to get object from JDNI address

*/

public BrainService() throws NamingException {

this.speechFacade = Utils.getSpeechFacade();

}

/**

* Ask question.

* Generate answer based on url, message and emotions.

*

* @param question Question

* @return Answer

*/

public Answer askQuestion(Question question) {

Page 101: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

101

Answer answer = new Answer();

String message = question.getMessage();

if (message == null) {

generateAnswer(answer, MessageType.DONT_UNDERSTAND, 20, 10, 16, 22);

} else {

if (message.equals("good morning")) {

generateAnswer(answer, MessageType.WELCOME, 6, 9, 2, 8, false, false, false, true);

} else if (message.equals("welcome")) {

generateAnswer(answer, MessageType.WELCOME_ON_PORTAL, 36, 8, 6, 26, false, true, false,

true);

} else if (message.equals("welcome back")) {

generateAnswer(answer, MessageType.WELCOME_BACK, 40, 40, 40, 40, true, true, true, true);

} else if (message.equals("hello") || message.equals("how are you")) {

generateAnswer(answer, MessageType.HELLO, 9, 22, 4, 10, false, false, false, true);

} else if (message.equals("what is your name") || message.equals("name")) {

generateAnswer(answer, MessageType.MY_NAME_IS, 36, 36, 36, 36, true, true, true, true);

} else if (message.equals("read page") || message.equals("read") || message.equals("page")) {

generateAnswer(answer, MessageType.PAGE_ABOUT, 36, 36, 36, 36, true, true, true, true);

} else if (message.equals("next page") || message.equals("next")) {

generateAnswer(answer, MessageType.GOTO_PAGE, 36, 36, 36, 36, true, true, true, true);

String nextPage = speechFacade.getPreviousPage(question.getUrl());

this.gotoPage(answer, "Next", nextPage);

} else if (message.equals("previous page") || message.equals("previous")) {

generateAnswer(answer, MessageType.GOTO_PAGE, 36, 36, 36, 36, true, true, true, true);

String previousPage = speechFacade.getPreviousPage(question.getUrl());

this.gotoPage(answer, "Previous", previousPage);

} else if (message.equals("go home") || message.equals("home")) {

generateAnswer(answer, MessageType.GOTO_PAGE, 36, 36, 36, 36, true, true, true, true);

this.gotoPage(answer, "Home", "http://94.23.252.15:7001/portal/index.xhtml");

} else if (message.equals("go people") || message.equals("people") || message.equals("teachers")) {

generateAnswer(answer, MessageType.GOTO_PAGE, 36, 36, 36, 36, true, true, true, true);

this.gotoPage(answer, "People", "http://94.23.252.15:7001/portal/people.xhtml");

} else if (message.equals("go specialization") || message.equals("specialization")) {

generateAnswer(answer, MessageType.GOTO_PAGE, 36, 36, 36, 36, true, true, true, true);

this.gotoPage(answer, "Specialization", "http://94.23.252.15:7001/portal/specialization.xhtml");

} else if (message.equals("go teaching") || message.equals("teaching")) {

generateAnswer(answer, MessageType.GOTO_PAGE, 36, 36, 36, 36, true, true, true, true);

this.gotoPage(answer, "Teaching", "http://94.23.252.15:7001/portal/teaching.xhtml");

} else if (message.equals("go research") || message.equals("research")) {

generateAnswer(answer, MessageType.GOTO_PAGE, 36, 36, 36, 36, true, true, true, true);

this.gotoPage(answer, "Research", "http://94.23.252.15:7001/portal/research.xhtml");

} else if (message.equals("go laboratories") || message.equals("laboratories")) {

generateAnswer(answer, MessageType.GOTO_PAGE, 36, 36, 36, 36, true, true, true, true);

this.gotoPage(answer, "Laboratories", "http://94.23.252.15:7001/portal/laboratories.xhtml");

} else if (message.equals("smart control idea") || message.equals("smart control")) {

generateAnswer(answer, MessageType.GOTO_PAGE, 36, 36, 36, 36, true, true, true, true);

this.gotoPage(answer, "Smart Control Idea",

"http://94.23.252.15:7001/portal/smart_control_idea.xhtml");

} else {

generateAnswer(answer, MessageType.YOU_SAID, 36, 36, 36, 36, true, true, true, true);

answer.setMessage(answer.getMessage() + " " + message);

}

}

setEmotionStates(question, answer);

return answer;

}

Page 102: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

102

/**

* Generate answer.

* Always generated emotions are positive.

*

* @param answer Answer

* @param message Speech message

* @param e1 Emotion 1

* @param e2 Emotion 2

* @param e3 Emotion 3

* @param e4 Emotion 4

*/

private void generateAnswer(Answer answer, MessageType message, Integer e1, Integer e2, Integer e3,

Integer e4) {

generateAnswer(answer, message, e1, e2, e3, e4, false, false, false, false);

}

/**

* Generate answer.

* You can set which emotions may be negative.

*

* @param answer Answer

* @param message Speech message

* @param e1 Emotion 1

* @param e2 Emotion 2

* @param e3 Emotion 3

* @param e4 Emotion 4

* @param isNegE1 Emotion 1 may be negative

* @param isNegE2 Emotion 2 may be negative

* @param isNegE3 Emotion 3 may be negative

* @param isNegE4 Emotion 4 may be negative

*/

private void generateAnswer(Answer answer, MessageType message, Integer e1, Integer e2, Integer e3,

Integer e4,

boolean isNegE1, boolean isNegE2, boolean isNegE3, boolean isNegE4) {

Random generator = new Random();

Integer newE1 = generator.nextInt(e1);

Integer newE2 = generator.nextInt(e2);

Integer newE3 = generator.nextInt(e3);

Integer newE4 = generator.nextInt(e4);

if (isNegE1) {

newE1 -= e1 / 2;

}

if (isNegE2) {

newE2 -= e1 / 2;

}

if (isNegE3) {

newE3 -= e1 / 2;

}

if (isNegE4) {

newE4 -= e1 / 2;

}

answer.setE1(newE1);

answer.setE2(newE2);

answer.setE3(newE3);

answer.setE4(newE4);

answer.setMessage(getMessage(message));

Page 103: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

103

answer.setIsRedirect(false);

}

/**

* Set emotions.

*

* @param question Question

* @param answer Answer

*/

private void setEmotionStates(Question question, Answer answer) {

if (question == null && answer == null) {

return;

}

if (question.getE1() == null || question.getE2() == null || question.getE3() == null ||

question.getE4() == null) {

answer.setStateE1(answer.getE1());

answer.setStateE2(answer.getE2());

answer.setStateE3(answer.getE3());

answer.setStateE4(answer.getE4());

return;

}

if (answer.getE1() == null || answer.getE2() == null || answer.getE3() == null || answer.getE4() == null)

{

answer.setStateE1(question.getE1());

answer.setStateE2(question.getE2());

answer.setStateE3(question.getE3());

answer.setStateE4(question.getE4());

return;

}

answer.setStateE1(answer.getE1() + question.getE1());

answer.setStateE2(answer.getE2() + question.getE2());

answer.setStateE3(answer.getE3() + question.getE3());

answer.setStateE4(answer.getE4() + question.getE4());

}

/**

* Get text message based on specified message type.

*

* @param type Message type

* @return Text message

*/

private String getMessage(MessageType type) {

Message message = speechFacade.getMessage(type);

String result = message == null ? "" : message.getMessage();

return result;

}

/**

* Set redirect page.

*

* @param answer Answer

* @param pageName Redirected page name

Page 104: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

104

* @param www URL address of redirected page

*/

private void gotoPage(Answer answer, String pageName, String www) {

answer.setMessage(answer.getMessage() + " " + pageName);

answer.setIsRedirect(true);

answer.setRedirectPage(www);

}

}

Administrator – Administrator

Administrator\src\com\janklimczak\speech\admin\SpeechAdmin.java:

package com.janklimczak.speech.admin;

import com.janklimczak.speech.facade.SpeechFacade;

import com.janklimczak.speech.facade.Utils;

import com.janklimczak.speech.model.Pages;

import com.janklimczak.speech.model.People;

import com.janklimczak.speech.model.Speech;

import com.janklimczak.speech.model.SpeechType;

import com.janklimczak.speech.model.SpeechWeight;

import com.janklimczak.speech.model.Subject;

import com.janklimczak.speech.model.SubjectData;

import java.io.IOException;

import java.net.MalformedURLException;

import java.util.LinkedList;

import javax.naming.NamingException;

import org.jsoup.Jsoup;

import org.jsoup.nodes.Document;

import org.jsoup.nodes.Element;

import org.jsoup.select.Elements;

/**

* Speech admin.

*

* @author Jan Klimczak

*/

public class SpeechAdmin {

/** Store parsed document */

private Document doc;

/** Store error messages prepared to display for user */

private LinkedList<String> errorMessages;

/** Sitemap URL */

private String sitemapUrl;

/** Spech facade. Is accessor to database */

private SpeechFacade speechFacade;

/**

Page 105: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

105

* SpeechAdmin constructor.

*

* @param sitemapUrl Sitemap URL.

* @throws NamingException Error throw when is not posible to locate speech facade from JDNI address.

*/

public SpeechAdmin(String sitemapUrl) throws NamingException {

this.errorMessages = new LinkedList<String>();

this.sitemapUrl = sitemapUrl;

this.speechFacade = Utils.getSpeechFacade();

}

/**

* Genarate data for speech in database.

* First is clear database.

*

* @return Error messages.

* @throws MalformedURLException Throw when URL sitemap address cannot be resolved.

* @throws IOException Throw when cannot read sitemap file.

*/

public LinkedList<String> generateSpeechDB() throws MalformedURLException, IOException {

speechFacade.cleanSpeechDB();

LinkedList<String> webPages = SitemapUtils.getPageNamesFromSitemap(this.sitemapUrl);

int pageNumber = 0;

for (String page : webPages) {

Pages savedPage = speechFacade.persistPages(new Pages(page, pageNumber++));

try {

doc = Jsoup.connect(page).get();

Elements elements = doc.getElementsByTag("speech");

for (Element element : elements) {

try {

final String text = element.text();

final SpeechType type = SpeechType.valueOf(element.attr("value"));

switch (type) {

case PEOPLE:

savePeople(element, text);

break;

case SUBJECT:

saveSubject(element, text);

break;

case SUBJECT_DATA:

saveSubjectData(element);

break;

default:

SpeechWeight weight = getWeight(element);

saveSpeech(savedPage, type, weight, text);

}

} catch (IllegalArgumentException e) {

String msg = "Can't read ELEMENT: " + element;

errorMessages.add(msg);

}

}

Page 106: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

106

} catch (IOException e) {

String msg = "Can't read PAGE: " + page;

errorMessages.add(msg);

} catch (IllegalArgumentException e) {

String msg = "Can't read PAGE: " + page;

errorMessages.add(msg);

}

}

return errorMessages;

}

/**

* Save speech data into database.

* Is based on speech tags incuded on the portal.

*

* @param savedPage Page url.

* @param type Speech type.

* @param weight Speech weight.

* @param text Speech text.

*/

private void saveSpeech(Pages savedPage, SpeechType type, SpeechWeight weight, String text) {

speechFacade.persistSpeech(new Speech(savedPage, type, weight, text));

}

/**

* Save speech people data into database.

* Is based on speech tags incuded on the portal.

*

* @param element Tag element.

* @param name People name.

*/

private void savePeople(Element element, String name) {

String degree = element.attr("degree");

String function = element.attr("function");

String moreUrl = element.attr("moreUrl");

People people = new People();

people.setName(name);

people.setFunction(function.trim().isEmpty() ? null : function);

people.setDegree(degree.trim().isEmpty() ? null : degree);

people.setUrlMore(moreUrl.trim().isEmpty() ? null : moreUrl);

speechFacade.persistPeople(people);

}

/**

* Save speech subject/specialisation name into database.

* Is based on speech tags incuded on the portal.

*

* @param element Tag element.

* @param name Subject/specialisation name.

*/

private void saveSubject(Element element, String name) {

Page 107: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

107

Subject subject = speechFacade.getSubject(name);

if (subject != null) {

return;

}

String type = element.attr("type");

speechFacade.persistSubject(new Subject(name, type));

}

/**

* Save speech subject/specialisation data into database.

* Is based on speech tags incuded on the portal.

* The data is: name, subject form, number of hours, teachers, taught in, study level, semester and

department.

*

* @param element Tag element.

*/

private void saveSubjectData(Element element) {

String name = element.attr("name");

String subjectForm = element.attr("subjectForm".toLowerCase());

String noOfHours = element.attr("noOfHours".toLowerCase());

String teachers = element.attr("teachers");

String taughtIn = element.attr("taughtIn".toLowerCase());

String studyLevel = element.attr("studyLevel".toLowerCase());

String semester = element.attr("semester");

String department = element.attr("department");

SubjectData sData = new SubjectData();

Subject subject = new Subject();

subject.setName(name);

sData.setSubject(subject);

sData.setNoOfHours(new Integer(noOfHours));

sData.setSemester(semester);

sData.setStudyLevel(studyLevel);

sData.setSubjectForm(subjectForm);

sData.setTaughtIn(taughtIn);

sData.setTeachers(teachers);

sData.setDepartment(department);

speechFacade.persistSubjectData(sData);

}

/**

* Get speech weight stored in speech tag.

*

* @param element Tag element.

* @return Speech weigth.

*/

private SpeechWeight getWeight(Element element) {

SpeechWeight weight;

String w = element.attr("weight");

switch (new Integer(w)) {

case 1:

weight = SpeechWeight.SECOND;

break;

case 2:

Page 108: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

108

weight = SpeechWeight.THIRD;

break;

case 0:

default:

weight = SpeechWeight.FIRST;

}

return weight;

}

}

Administrator\src\com\janklimczak\speech\admin\SitemapUtils.java:

package com.janklimczak.speech.admin;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.net.MalformedURLException;

import java.net.URL;

import java.util.LinkedList;

/**

* Sitemap utils.

*

* @author Jan Klimczak

*/

public class SitemapUtils {

/**

* Gather page names from sitemap in list.

*

* @param sitemapUrl Sitemap URL.

* @return Sitemap page list.

* @throws MalformedURLException Throw when sitemap cannot be gathered from specified URL.

* @throws IOException Throw when is not possible to read sitemapo file.

*/

public static LinkedList<String> getPageNamesFromSitemap(String sitemapUrl) throws

MalformedURLException,

IOException {

URL url = new URL(sitemapUrl);

InputStream is = url.openStream();

BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));

LinkedList<String> result = new LinkedList<String>();

String line = reader.readLine();

while (line != null) {

result.add(line);

}

return result;

}

}

Page 109: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

109

Administrator\src\com\janklimczak\speech\admin\backing\Index.java:

package com.janklimczak.speech.admin.backing;

import com.janklimczak.speech.model.Message;

import javax.faces.bean.ManagedBean;

import javax.faces.bean.SessionScoped;

import javax.faces.component.html.HtmlCommandButton;

import javax.faces.component.html.HtmlForm;

import javax.faces.component.html.HtmlInputText;

import javax.faces.component.html.HtmlOutputLabel;

import javax.faces.model.DataModel;

import javax.faces.model.ListDataModel;

import javax.naming.NamingException;

import java.io.Serializable;

import java.util.List;

/**

* Backing end for index page.

*

* @author Jan Klimczak

*/

@ManagedBean(name = "backing_index")

@SessionScoped

public class Index extends Utils implements Serializable {

/** HTML form */

private HtmlForm form;

/** Sitemap name */

private HtmlInputText sitemapName;

/** HTML generate button */

private HtmlCommandButton generateButton;

/** HTML show sitemap button */

private HtmlCommandButton showSitemapButton;

/** Info */

private HtmlOutputLabel info;

/** Speech messages container */

private ListDataModel model;

/**

* Get speech messages from database.

*

* @return Speech messages list

*/

public DataModel getList() {

try {

if (model == null) {

model = new ListDataModel();

connectToDb();

List<Message> list = getSpeechFacade().getMessageFindAll();

Page 110: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

110

model.setWrappedData(list);

}

} catch (NamingException e) {

e.printStackTrace();

}

return model;

}

/**

* Edit current message action

*

* @return null

*/

public Object editAction() {

Message message = (Message)model.getRowData();

message.setEditable(true);

return null;

}

/**

* Reload speech messages from database.

*

* @return null

*/

public Object reloadAction() {

try {

model = new ListDataModel();

connectToDb();

List<Message> list = getSpeechFacade().getMessageFindAll();

model.setWrappedData(list);

} catch (NamingException e) {

e.printStackTrace();

}

return null;

}

/**

* Save speech message in database.

*

* @return null

*/

public Object saveAction() {

Message msg = (Message)model.getRowData();

getSpeechFacade().mergeMessage(msg);

msg.setEditable(false);

return null;

}

/**

* Delete message in database.

*

* @return null

Page 111: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

111

*/

public Object deleteMessageAction(Message message) {

getSpeechFacade().removeMessage(message);

return null;

}

public void setForm(HtmlForm form1) {

this.form = form1;

}

public HtmlForm getForm() {

return form;

}

public void setSitemapName(HtmlInputText inputText1) {

this.sitemapName = inputText1;

}

public HtmlInputText getSitemapName() {

return sitemapName;

}

public void setGenerateButton(HtmlCommandButton commandButton1) {

this.generateButton = commandButton1;

}

public HtmlCommandButton getGenerateButton() {

return generateButton;

}

public void setShowSitemapButton(HtmlCommandButton showSitemapButton) {

this.showSitemapButton = showSitemapButton;

}

public HtmlCommandButton getShowSitemapButton() {

return showSitemapButton;

}

public void setInfo(HtmlOutputLabel info) {

this.info = info;

}

public HtmlOutputLabel getInfo() {

return info;

}

}

Portal demonstarcyjny – PortalPG

PortalPG\public_html\index.xhtml:

<?xml version='1.0' encoding='UTF-8' ?>

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<ui:composition template="./WEB-INF/template/layout.xhtml"

xmlns="http://www.w3.org/1999/xhtml"

xmlns:ui="http://java.sun.com/jsf/facelets"

xmlns:h="http://java.sun.com/jsf/html"

Page 112: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

112

xmlns:ezcomp="http://java.sun.com/jsf/composite/ezcomp">

<ui:define name="content">

<ezcomp:title value="About Department"/>

<h:graphicImage value="#{resource['image/department.jpg']}"/>

<ezcomp:text value="&lt;speech value='INTRO' weight='0'&gt; &lt;b&gt;The Department of Decision

Systems&lt;/b&gt; was created in 2006 by professor Zdzislaw Kowalczuk and, of interests of the Department

concern modeling and identification, diagnostics, control and decision systems.&lt;/speech&gt; Scientific

research involve planning and control both industrial and economical processes as well as developing modern

design methods using computer techniques and tools. The methods derived result both from classical analysis

and artificial/computational intelligence. Industrial process diagnosis, methods of system and signal analysis

and filtering, estimation of dynamical plants state, production and path planning and other problems, which

enhance the characterization of the Department, are utilized in automatic control systems, mobile and flying

robots, automotive vehicles and other industrial objects. In the field of teaching the Department’s staff

together with the staff of the Automatic Control Department play the role of a principal leader in the

BSc/MSc course of Automatic Control and Robotics in the Faculty of Electronics Telecommunication and

Informatics of the Gdansk University of Technology."/>

<ezcomp:endDocument/>

</ui:define>

</ui:composition>

PortalPG\public_html\avatar\avatar.xhtml:

<?xml version='1.0' encoding='UTF-8' ?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<ui:composition xmlns="http://www.w3.org/1999/xhtml"

xmlns:ui="http://java.sun.com/jsf/facelets"

xmlns:h="http://java.sun.com/jsf/html"

xmlns:f="http://java.sun.com/jsf/core">

<script language="JavaScript" type="text/javascript">

<!--

// Version check for the Flash Player that has the ability to start Player Product Install (6.0r65)

var hasProductInstall = DetectFlashVer(6, 0, 65);

// Version check based upon the values defined in globals

var hasRequestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion,

requiredRevision);

if ( hasProductInstall && !hasRequestedVersion ) {

// DO NOT MODIFY THE FOLLOWING FOUR LINES

// Location visited after installation is complete if installation is required

var MMPlayerType = (isIE == true) ? "ActiveX" : "PlugIn";

var MMredirectURL = window.location;

//document.title = document.title.slice(0, 47) + " - Flash Player Installation";

var MMdoctitle = document.title;

AC_FL_RunContent(

"src", "playerProductInstall",

"FlashVars",

"MMredirectURL="+MMredirectURL+'&MMplayerType='+MMPlayerType+'&MMdoctitle='+MMdoctitle

+"",

"width", "100%",

"height", "100%",

"align", "middle",

Page 113: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

113

"id", "SpeechAvatar",

"quality", "high",

"bgcolor", "#ffffff",

"name", "SpeechAvatar",

"allowScriptAccess","sameDomain",

"type", "application/x-shockwave-flash",

"pluginspage", "http://www.adobe.com/go/getflashplayer"

);

} else if (hasRequestedVersion) {

// if we've detected an acceptable version

// embed the Flash Content SWF when all tests are passed

/*AC_FL_RunContent(

"src", "#{request.contextPath}/avatar/SpeechAvatar.swf",

"flashVars", "client_id=#{session.id}",

"width", "215",

"height", "138",

"align", "middle",

"id", "SpeechAvatar",

"quality", "high",

"bgcolor", "#ffffff",

"name", "SpeechAvatar",

"allowScriptAccess","sameDomain",

"type", "application/x-shockwave-flash",

"pluginspage", "http://www.adobe.com/go/getflashplayer"

);*/

} else { // flash is too old or we can't detect the plugin

var alternateContent = ''

+ 'This content requires the Adobe Flash Player. '

+ '<a href=http://www.adobe.com/go/getflash/>Get Flash</a>';

document.write(alternateContent); // insert non-flash content

}

// -->

</script>

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"

id="SpeechAvatar" width="215" height="138"

codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">

<param name="movie" value="#{request.contextPath}/avatar/SpeechAvatar.swf" />

<param name='flashVars' value='client_id=#{session.id}'/>

<param name="quality" value="high" />

<param name="bgcolor" value="#ffffff" />

<param name="allowScriptAccess" value="sameDomain" />

<embed src="#{request.contextPath}/avatar/SpeechAvatar.swf" quality="high"

bgcolor="#ffffff"

width="215" height="138" name="SpeechAvatar.swf" align="middle"

flashVars="client_id=#{session.id}"

play="true"

loop="false"

allowScriptAccess="sameDomain"

type="application/x-shockwave-flash"

pluginspage="http://www.adobe.com/go/getflashplayer">

</embed>

</object>

<noscript>

</noscript>

</ui:composition>

PortalPG\public_html\resources\ezcomp\menuItem.xhtml:

Page 114: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

114

<?xml version='1.0' encoding='UTF-8' ?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"

xmlns:cc="http://java.sun.com/jsf/composite"

xmlns:h="http://java.sun.com/jsf/html">

<!-- INTERFACE -->

<cc:interface>

<cc:attribute name="name" required="true"/>

<cc:attribute name="url" required="true"/>

<cc:attribute name="weight" default="0"/>

</cc:interface>

<!-- IMPLEMENTATION -->

<cc:implementation>

<h:outputLink value="#{cc.attrs.url}" title="#{cc.attrs.name}" styleClass="menuItem">

<speech value="MENU" weight="#{cc.attrs.weight}"><h:outputText

value="#{cc.attrs.name}"/></speech>

</h:outputLink>

</cc:implementation>

</html>

PortalPG\public_html\resources\ezcomp\text.xhtml:

<?xml version='1.0' encoding='UTF-8' ?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"

xmlns:cc="http://java.sun.com/jsf/composite"

xmlns:h="http://java.sun.com/jsf/html">

<!-- INTERFACE -->

<cc:interface>

<cc:attribute name="value" required="true"/>

<cc:attribute name="weight" default="0"/>

</cc:interface>

<!-- IMPLEMENTATION -->

<cc:implementation>

<speech value="TITLE" weight="#{cc.attrs.weight}">

<h:outputText value="#{cc.attrs.value}" escape="false" styleClass="text"/>

</speech>

</cc:implementation>

</html>

PortalPG\public_html\resources\js\avatar.sj:

var isFirstLog = true, showLogLayer = false, showInfoLayer = false;

function openWindowLog() {

document.getElementById('logLayer').style.display = "block";

showLogLayer = true;

}

function closeWindowLog() {

document.getElementById('logLayer').style.display = "none";

showLogLayer = false;

Page 115: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

115

}

function openWindowInfo() {

document.getElementById('infoLayer').style.display = "block";

showInfoLayer = true;

}

function closeWindowInfo() {

document.getElementById('infoLayer').style.display = "none";

showInfoLayer = false;

}

var infoE1, infoE2, infoE3, infoE4;

function updateE(e1, e2, e3, e4) {

if (showInfoLayer == false) {

return;

}

if (infoE1 == null)

infoE1 = document.getElementById('infoE1');

if (infoE2 == null)

infoE2 = document.getElementById('infoE2');

if (infoE3 == null)

infoE3 = document.getElementById('infoE3');

if (infoE4 == null)

infoE4 = document.getElementById('infoE4');

document.getElementById('e1table').style.height = (e1 + 30)/2;

document.getElementById('e2table').style.height = (e2 + 30)/2;

document.getElementById('e3table').style.height = (e3 + 30)/2;

document.getElementById('e4table').style.height = (e4 + 30)/2;

document.getElementById('e1table').height = (e1 + 30)/2;

document.getElementById('e2table').height = (e2 + 30)/2;

document.getElementById('e3table').height = (e3 + 30)/2;

document.getElementById('e4table').height = (e4 + 30)/2;

if (infoE1.hasChildNodes()) {

infoE1.removeChild(infoE1.firstChild);

}

if (infoE2.hasChildNodes()) {

infoE2.removeChild(infoE2.firstChild);

}

if (infoE3.hasChildNodes()) {

infoE3.removeChild(infoE3.firstChild);

}

if (infoE4.hasChildNodes()) {

infoE4.removeChild(infoE4.firstChild);

}

e1Node = document.createTextNode(e1);

e2Node = document.createTextNode(e2);

e3Node = document.createTextNode(e3);

e4Node = document.createTextNode(e4);

infoE1.appendChild(e1Node);

infoE2.appendChild(e2Node);

infoE3.appendChild(e3Node);

infoE4.appendChild(e4Node);

}

Page 116: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

116

function addMessageToLog(msg, mode, isFromServer) {

if (showLogLayer == false) {

return;

}

dv = document.createElement('font');

txt = document.createTextNode(msg);

switch (mode) {

case 'info':

color = 'orange';

break;

case 'warning':

color = 'brown';

break;

case 'error':

color = 'red';

break;

case 'debug':

color = 'darkgreen';

break;

default :

color = 'black';

}

dv.setAttribute('color', color);

if (isFromServer) {

dv.setAttribute('style', 'display:block; font-weight: bold;');

}

else {

dv.setAttribute('style', 'display:block;');

}

dv.appendChild(txt);

logNode = document.getElementById('logMessage');

if (isFirstLog) {

logNode.appendChild(dv);

isFirstLog = false;

}

else {

fs = logNode.firstChild;

logNode.insertBefore(dv, fs);

}

}

PortalPG\public_html\WEB-INF\template\header.xhtml:

<?xml version='1.0' encoding='UTF-8' ?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<ui:composition xmlns="http://www.w3.org/1999/xhtml"

xmlns:ui="http://java.sun.com/jsf/facelets">

<title>Department of Decision Systems, Gdansk University of Technology, Poland</title>

<!--Meta Tags-->

Page 117: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

117

<meta name="description" lang="en-us" content="Department of Decision Systems, Gdansk University

of Technology, Poland"/>

<meta name="keywords" lang="en-us" content="decision systems, decision, systems, ai, speech"/>

<meta http-equiv="Content-Language" content="en-us"/>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta name="robots" content="all"/>

<meta http-equiv="refresh" content="public"/>

<meta name="Copyright" lang="en-us" content="Copyright (c) 2011 Gdansk University of Technology,

Poland"/>

<meta name="Author" lang="en-us" content="Jan Klimczak, Zdzislaw Kowalczuk"/>

<!--Styles-->

<link href="#{resource['css:default.css']}" rel="stylesheet" type="text/css" />

<link href="#{resource['css:cssLayout.css']}" rel="stylesheet" type="text/css" />

<link href="#{resource['css:ui-lightness/jquery-ui-1.8.16.custom.css']}" rel="stylesheet" type="text/css"

/>

<!--JQuery-->

<script src="#{resource['js:jquery-1.6.2.min.js']}" language="javascript" type="text/javascript"/>

<script src="#{resource['js:jquery-ui-1.8.16.custom.min.js']}" language="javascript"

type="text/javascript"/>

<!--Avatar-->

<script src="#{resource['js:avatar.js']}" language="javascript" type="text/javascript"/>

<!--Flash-->

<script src="#{resource['js:flash/AC_OETags.js']}" language="javascript" type="text/javascript"/>

<script src="#{resource['js:flash/requiredVersion.js']}" language="javascript" type="text/javascript"/>

<!--PNG Alpha in IE6 -->

<link href="#{resource['iepng:iepng.css']}" rel="stylesheet" type="text/css" />

<link href="#{resource['iepng:iepngfix_tilebg.js']}" rel="javascript" type="text/javascript" />

<!--Statistics - Google Analitics-->

<script type="text/javascript">

var _gaq = _gaq || [];

_gaq.push(['_setAccount', 'UA-17253483-5']);

_gaq.push(['_trackPageview']);

(function() {

var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;

ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-

analytics.com/ga.js';

var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);

})();

</script>

</ui:composition>

PortalPG\public_html\WEB-INF\template\bottom.xhtml:

<?xml version='1.0' encoding='UTF-8' ?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<ui:composition xmlns="http://www.w3.org/1999/xhtml"

xmlns:h="http://java.sun.com/jsf/html"

xmlns:ui="http://java.sun.com/jsf/facelets">

Page 118: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

118

<div style="background: white;">

<table border="0" width="98%" align="center">

<tr>

<td width="215">

<div id="infoLayer" style="display:none;" >

<table width="100%" height="130">

<tr valign="bottom">

<td align="center" width="25%"> <table id="" bgcolor="yellow" width="50"

style="height:100;"><tr><td align="center" height="80"

id="e1table"><div>Happines</div></td></tr></table> </td>

<td align="center" width="25%"> <table id="" bgcolor="orange" width="50"

style="height:100;"><tr><td align="center" height="80"

id="e2table"><div>Satisfaction</div></td></tr></table> </td>

<td align="center" width="25%"> <table id="" bgcolor="red" width="50"

style="height:100;"><tr><td align="center" height="80"

id="e3table"><div>Excitement</div></td></tr></table> </td>

<td align="center" width="25%"> <table id="" bgcolor="brown" width="50"

style="height:100;"><tr><td align="center" height="80" id="e4table"><div>Joy</div></td></tr></table>

</td>

</tr>

<tr>

<td align="center"><div id="infoE1"></div></td>

<td align="center"><div id="infoE2"></div></td>

<td align="center"><div id="infoE3"></div></td>

<td align="center"><div id="infoE4"></div></td>

</tr>

</table>

</div>

</td>

<td width="215">

<ui:include src="../../avatar/avatar.xhtml"/>

</td>

<td width="*">

<div id="logLayer" style="display:none;" >

<div id="logMessage" style="height: 130px; overflow: auto; padding: 5px"></div>

</div>

</td>

</tr>

</table>

</div>

<div style="text-align:center; padding-top: 2px;">

<h:outputText value="All Rights Reserved ® 2011 by DecisionSystems.pl, Gdansk University of

Technology"/>

</div>

</ui:composition>

13.Bibliografia

[1] Huang Z., Eliëns H., Vissser C.: Programmability of Intelligent Agent Avatars. PDF

(http://wasp.cs.vu.nl/wasp/papers/avatar.pdf), Vrije University of Amsterdam, Montreal

(Canada) 2001.

[2] O'Shaughnessy D., Interacting With Computers by Voice: Automatic Speech Recognition

and Synthesis, vol. 91, no. 9. PDF (http://www.hoviat.dpsh.net/download/maghale-

signal/15.pdf), IEEE, Montreal (Canada) 2003.

[3] A. Kemble K., An Introduction to Speech Recognition. PDF

(ftp://ftp.software.ibm.com/software/pervasive/info/products/Introduction_to_Speech_Rec

ognition.pdf), IBM.

Page 119: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

119

[4] Keller E., Keller B. Z., New Uses for Speech Synthesis, The Phonetician 81, ss. 35-40. PDF

(http://www.uniger.ch/BrigitteZellnerKeller/Brigitte_ZellnerKeller_files/Publications/Kell

er-ZellnerKeller-00-Phonetician81.pdf), Université de Lausanne, Lausanne (Switzerland)

2000.

[5] http: Microsoft Speech Technologies. http://msdn.microsoft.com/en-us/speech/default,

(2012).

[6] http: Java Speech API. http://java.sun.com/products/java-media/speech/, (2011).

[7] http: JavaTM Speech API Programmer's Guide, 1998. http://java.sun.com/products/java-

media/speech/forDevelopers/jsapi-guide/index.html, (2011).

[8] Bruce E.: Thinking in Java, (3nd edition). Helion, Gliwice 2003.

[9] http: White Papers. http://java.sun.com/products/java-

media/speech/reference/whitepapers/index.html, (2011).

[10] http: The Open Source Definition. http://www.opensource.org/docs/osd, (2011).

[11] http: Oracle Corporation. http://www.oracle.com, (2011).

[12] http: Apple. http://www.apple.com, (2011).

[13] http: AT&T. http://www.att.com, (2011).

[14] http: Dragon System. http://www.nuance.com, (2011).

[15] http: IBM Corporation. http://www.ibm.com, (2011).

[16] http: Novell. http://www.novell.com, (2011).

[17] http: Philips Electronics. http://www.philips.com, (2011).

[18] http: Texas Instruments. http://www.ti.com, (2011).

[19] http: JSR 113: JavaTM Speech API 2.0, 2009. http://www.jcp.org/en/jsr/detail?id=113,

(2011).

[20] http: Introduction and Overview of W3C Speech Interface Framework, 2000.

http://www.w3.org/TR/voice-intro/, (2011).

[21] http: Microsoft Speech API (SAPI) 5.3. http://msdn.microsoft.com/en-

us/library/ms723627(v=vs.85).aspx, (2011).

[22] http: Microsoft Tellme speech innovation. http://www.microsoft.com/en-

us/Tellme/default.aspx , (2011).

[23] http: Bell Laboratories, Inc. http://www.belllabs.com, (2011).

[24] http: Pioneering Speech Recognition.

http://www.ibm.com/ibm100/us/en/icons/speechreco/breakthroughs/, (2011).

[25] http: Speech Recognition Through the Decades: How We Ended Up With Siri, (2011).

http://www.pcworld.com/article/243060/speech_recognition_through_the_decades_how_w

e_ended_up_with_siri.html, (2011).

[26] http: Dragon Medical Solutions. http://www.nuance.com/products/dragon-medical-

family/index.htm, (2011).

[27] http: Dragon Speech Recognition Software. http://nuance.com/dragon/index.htm, (2011).

[28] http: TalkingJava SDK with Java Speech API implementation, (2011).

http://www.cloudgarden.com/JSAPI/, (2011).

[29] http: Acapela box (Elan Speech Cube). http://www.acapela-group.com/, (20110).

[30] http: Lumen Vox. http://www.lumenvox.com/, (2011).

[31] http: Ivona. http://www.ivona.com/en/, (2011).

[32] http: Sphinx-4, A speech recognizer written entirely in the JavaTM programming

language. http://cmusphinx.sourceforge.net/sphinx4/, (2011).

[33] http: Voice and Speech Recognition. http://www.e-speaking.com/, (2011).

[34] http: FreeTTS 1.2 - A speech synthesizer written entirely in the JavaTM programming

language. http://freetts.sourceforge.net/docs/index.php, (2011).

[35] http: Flite: a small, fast run time synthesis engine. http://www.speech.cs.cmu.edu/flite/,

(2011).

[36] http: The Festival Speech Synthesis System. http://www.cstr.ed.ac.uk/projects/festival/,

(2011).

Page 120: System inteligentnej nawigacji sterowanej głosem po serwisie internetowym

120

[37] http: FestVox. http://festvox.org/, (2011).

[38] http: Real-Time Messaging Protocol (RTMP) specification.

http://www.adobe.com/devnet/rtmp.html, (2011).

[39] http: Adobe. http://www.adobe.com/, (2011).

[40] http: Adobe Flash Media Server family. http://www.adobe.com/products/flashmediaserver/,

(2011).

[41] http: Adobe LiveCycle Data Services ES3.

http://www.adobe.com/products/livecycle/dataservices/, (2011).

[42] http: Next-Generation Media Delivery Platform. http://www.wowza.com/, (2011).

[43] http: Red5. http://www.red5.org/, (2011).

[44] http: The Java EE 5 Tutorial. http://docs.oracle.com/javaee/5/tutorial/doc/, (2011).

[45] Burke B., Monson-Haefel R.: Enterprise JavaBeans 3.0. Helion, Gliwice 2007.

[46] http: Oracle Mojarra JavaServer Faces. http://javaserverfaces.java.net/, (2011).

[47] http: Facelets. http://facelets.java.net/, (2011).

[48] Goetz B., Peierls T., Bloch J., Bowbeer J., Holmes D., Lea D.: Java. Współbieżność dla

praktyków. Helion, Gliwice 2007.

[49] Pilone D., Pitman N.: UML 2.0 Alamanch. Helion, Gliwice 2007.

[50] Śmiałek M.: Zrozumieć UML 2.0. Helion, Gliwice 2005.

[51] Crawford W., Kaplan J.: J2EE Stosowanie wzorców projektowych. Helion, Gliwice 2004.

[52] McLaughlin B. D., Pollice G., West D.: Head First. Object-Oriented Analisys & Design.

Helion, Gliwice, 2008.

[53] Jayaswal B. K., Patton P. C.: Oprogramowanie godne zaufania. Helion, Gliwice 2007.

[54] Pilone D., Miles R.: Head First. Software development. Helion, Gliwice 2008.

[55] Mak G., Long J., Rubio D.: Spring Recipies. Apress, USA 2010.

[56] Kowalczuk Z., Czubenko M.: Dictobot – An autonomous agent with the ability to

communicate. Technologie Informacyjne, str. 87-92. Zeszyty naukowe WETI, 2011.