I det här inlägget visar vi hur man använder Amazon Polly—en ledande molntjänst som omvandlar text till verklighetstrogen tal — för att läsa innehållet på en webbsida och framhäva innehållet när det läses. Att lägga till ljuduppspelning på en webbsida förbättrar tillgängligheten och besökarnas upplevelse av sidan. Ljudförbättrat innehåll är mer effektfullt och minnesvärt, drar mer trafik till sidan och utnyttjar besökarnas köpkraft. Det förbättrar också varumärket för företaget eller organisationen som publicerar sidan. Text-till-tal-teknik gör att dessa affärsfördelar kan uppnås. Vi påskyndar den resan genom att visa hur man uppnår detta mål med Amazon Polly.
Denna funktion förbättrar tillgängligheten för besökare med funktionshinder och kan användas som en del av din organisations tillgänglighetsstrategi. Lika viktigt är att det förbättrar sidupplevelsen för besökare utan funktionshinder. Båda grupperna har betydande köpkraft och spenderar mer fritt från sidor som använder ljudförbättring för att fånga deras uppmärksamhet.
Översikt över lösningen
PollyReadsThePage
(PRTP) – som vi hänvisar till lösningen – gör att en webbsidesutgivare kan släppa en ljudkontroll på sin webbsida. När besökaren väljer Spela på kontrollen läser kontrollen sidan och markerar innehållet. PRTP använder den allmänna förmågan hos Amazon Polly för att syntetisera tal från text. Det anropar Amazon Polly för att generera två artefakter för varje sida:
- Ljudinnehållet i ett format som kan spelas upp av webbläsaren: MP3
- En talmarkeringsfil som anger för varje textsats:
- Tiden under uppspelning som meningen läses
- Platsen på sidan där meningen visas
När besökaren väljer Spela, webbläsaren spelar upp MP3-filen. När ljudet läses kontrollerar webbläsaren tiden, hittar i markeringsfilen vilken mening som ska läsas vid den tidpunkten, lokaliserar den på sidan och markerar den.
PRTP låter besökaren läsa på olika röster och språk. Varje röst kräver sitt eget filpar. PRTP använder neurala röster. För en lista över neurala röster och språk som stöds, se Neurala röster. För en fullständig lista över standard- och neurala röster i Amazon Polly, se Röster i Amazon Polly.
Vi överväger två typer av webbsidor: statiska och dynamiska sidor. I en statisk sida, innehållet finns på sidan och ändras endast när en ny version av sidan publiceras. Företaget kan uppdatera sidan dagligen eller veckovis som en del av sin webbbyggnadsprocess. För den här typen av sida är det möjligt att förgenerera ljudfilerna vid byggtiden och placera dem på webbservern för uppspelning. Som följande figur visar, skriptet PRTP Pre-Gen
anropar Amazon Polly för att generera ljudet. Det tar som indata själva HTML-sidan och, valfritt, en konfigurationsfil som anger vilken text från sidan som ska extraheras (Text Extract Config
). Om extraktkonfigurationen utelämnas gör pre-gen-skriptet ett vettigt val av text att extrahera från sidans brödtext. Amazon Polly matar ut filerna i en Amazon enkel lagringstjänst (Amazon S3) hink; skriptet kopierar dem till din webbserver. När besökaren spelar upp ljudet laddar webbläsaren ned MP3 direkt från webbservern. För höjdpunkter, ett drop-in-bibliotek, PRTP.js
, använder markeringsfilen för att markera texten som läses.
Innehållet i en dynamisk sidan ändras som svar på besökarnas interaktion, så ljud kan inte förgenereras utan måste syntetiseras dynamiskt. Som följande figur visar, när besökaren spelar upp ljudet, använder sidan PRTP.js
för att generera ljudet i Amazon Polly, och det framhäver det syntetiserade ljudet med samma tillvägagångssätt som med statiska sidor. För att komma åt AWS-tjänster från webbläsaren kräver besökaren en AWS-identitet. Vi visar hur man använder en Amazon Cognito identitetspool för att ge besökaren precis tillräckligt med tillgång till Amazon Polly och S3-hinken för att återge ljudet.
Att generera både mp3-ljud och talmärken kräver att Polly-tjänsten syntetiserar samma ingång två gånger. Referera till Prissida för Amazon Polly för att förstå kostnadskonsekvenserna. Förgenerering sparar kostnader eftersom syntesen utförs vid byggtid snarare än on-demand för varje besöksinteraktion.
Koden som medföljer detta inlägg är tillgänglig som ett arkiv med öppen källkod på GitHub.
För att utforska lösningen följer vi dessa steg:
- Konfigurera resurserna, inklusive pre-gen build-servern, S3-bucket, webbserver och Amazon Cognito-identitet.
- Kör den statiska pre-gen builden och testa statiska sidor.
- Testa dynamiska sidor.
Förutsättningar
För att köra detta exempel behöver du en AWS-konto med tillstånd att använda Amazon Polly, Amazon S3, Amazon Cognito och (för demoändamål) AWS Cloud9.
Tillhandahållande resurser
Vi delar en AWS molnformation mall för att skapa en fristående demomiljö på ditt konto som hjälper dig att följa inlägget. Om du föredrar att ställa in PRTP i din egen miljö, se instruktionerna i README.md.
För att tillhandahålla demomiljön med CloudFormation, ladda först ner en kopia av CloudFormation-mall. Slutför sedan följande steg:
- Välj på AWS CloudFormation-konsolen Skapa stack.
- Välja Med nya resurser (standard).
- Välja Ladda upp en mallfil.
- Välja Välj FIL för att ladda upp den lokala kopian av mallen som du laddade ner. Namnet på filen är
prtp.yml
. - Välja Nästa.
- Ange ett stacknamn som du väljer. Senare anger du detta igen som ersättning för .
- Du kan behålla standardvärdena i parametrar sektion.
- Välja Nästa.
- Fortsätt genom de återstående avsnitten.
- Läs och markera kryssrutorna i Capabilities sektion.
- Välja Skapa stack.
- När stacken är klar, hitta värdet för
BucketName
i stackutgångarna.
Vi uppmuntrar dig att granska stacken med ditt säkerhetsteam innan du använder den i en produktionsmiljö.
Konfigurera webbservern och pre-gen-servern i en AWS Cloud9 IDE
Därefter, på AWS Cloud9-konsolen, lokalisera miljön PRTPDemoCloud9
skapad av CloudFormation-stacken. Välja Öppna IDE för att öppna AWS Cloud9-miljön. Öppna ett terminalfönster och kör följande kommandon, som klonar PRTP-koden, ställer in pre-gen-beroenden och startar en webbserver att testa med:
För , använd namnet du gav CloudFormation-stacken. För , ange ett intervall av IP-adresser som får åtkomst till webbservern. För att begränsa åtkomsten till webbläsaren på din lokala dator, hitta din IP-adress med hjälp av https://whatismyipaddress.com/ och lägg till /32
för att ange intervallet. Till exempel, om din IP är 10.2.3.4, use 10.2.3.4/32
. Servern lyssnar på port 8080. Den publika IP-adressen som servern lyssnar på anges i utgången. Till exempel:
Testa statiska sidor
Navigera till i din webbläsare PRTPStaticDefault.html
. (Om du använder demon är webbadressen http://:8080/web/PRTPStaticDefault.html
Där är den offentliga IP-adress som du upptäckte när du konfigurerade IDE.) Välj Spela på ljudkontrollen överst. Lyssna på ljudet och se höjdpunkterna. Utforska kontrollen genom att ändra hastigheter, ändra röster, pausa, snabbspola framåt och bakåt. Följande skärmdump visar sidan; texten "Hoppa över dold stycke" är markerad eftersom den för närvarande läses.
Prova samma för PRTPStaticConfig.html
och PRTPStaticCustom.html
. Resultaten är liknande. Till exempel läste alla tre alt-texten för fotot av katten ("Slumpmässig bild av en katt"). Alla tre läser NE, NW, SE och SW som fullständiga ord ("nordost", "nordväst", "sydöst", "sydväst"), och drar fördel av Amazon Polly-lexikon.
Lägg märke till de viktigaste skillnaderna i ljud:
PRTPStaticDefault.html
läser all text i brödtexten på sidan, inklusive avslutningsdelen längst ned med "Dina tankar i ett ord", "Skicka fråga", "Senast uppdaterad 1 april 2020" och "Frågor till utvecklarteamet."PRTPStaticConfig.html
ochPRTPStaticCustom.html
läs inte dessa eftersom de uttryckligen utesluter avslutningen från talsyntes.PRTPStaticCustom.html
läser QB bästsäljare bord annorlunda än de andra. Den läser endast de tre första raderna och läser radnumret för varje rad. Den upprepar kolumnerna för varje rad.PRTPStaticCustom.html
använder en anpassad transformation för att skräddarsy avläsningen av tabellen. De andra sidorna använder standardtabellrendering.PRTPStaticCustom.html
läser "Tom Brady" med en högre volym än resten av texten. Den använder SSML (Speech Synthesis Markup Language)prosody
tagga för att skräddarsy läsningen av Tom Brady. De andra sidorna skräddarsys inte på detta sätt.PRTPStaticCustom.html
, tack vare en anpassad transformation, läser huvudbrickorna i NW, SW, NE, SE ordning; det vill säga det står "Dagens artiklar", "Dagens citat", "Dagens foto", "Dagens skämt." De andra sidorna läses i den ordning som brickorna visas i den naturliga ordningen NW, NE, SW, SE som de visas i HTML:en: "Dagens artiklar", "Dagens foto", "Dagens citat", "Jokes of the Dag."
Låt oss gräva djupare i hur ljudet genereras och hur sidan framhäver texten.
Statisk förgenerator
Vår GitHub-repo innehåller förgenererade ljudfiler för PRPTStatic
sidor, men om du vill skapa dem själv, från bash-skalet i AWS Cloud9 IDE, kör följande kommandon:
Låt oss nu titta på hur dessa skript fungerar.
Standardfall
Vi börjar med gen_default.sh
:
Skriptet börjar med att köra Python-programmet FixHTML.py
för att skapa HTML-källfilen PRTPStaticDefault.html
välformad. Den skriver den välformade versionen av filen till example/tmp_wff.html
. Detta steg är avgörande av två anledningar:
- De flesta käll-HTML är inte väl utformad. Detta steg reparerar käll-HTML så att den är välformad. Till exempel, många HTML-sidor stängs inte
P
element. Detta steg stänger dem. - Vi håller koll på var på HTML-sidan vi hittar text. Vi måste spåra platser med samma dokumentobjektmodell (DOM) struktur som webbläsaren använder. Till exempel lägger webbläsaren automatiskt till en
TBODY
till enTABLE
. Python-programmet följer samma välformade reparationer som webbläsaren.
gen_ssml.sh
tar den välformade HTML-koden som indata, tillämpar en XML-stilmallstransformation (XSLT) på den och matar ut en SSML-fil. (SSML är språket i Amazon Polly för att styra hur ljud renderas från text.) I det aktuella exemplet är inmatningen example/tmp_wff.html
. Utgången är example/tmp.ssml
. Transformens jobb är att bestämma vilken text som ska extraheras från HTML och matas till Amazon Polly. generic.xslt
är en förnuftig standard-XSLT-transformation för de flesta webbsidor. I följande exempelkodavsnitt utesluter det ljudkontrollen, HTML-huvudet samt HTML-element som script
och form
. Det exkluderar också element med det dolda attributet. Den innehåller element som vanligtvis innehåller text, som t.ex P
, H1
och SPAN
. För dessa återger det både ett märke, inklusive elementets fullständiga XPath-uttryck, och elementets värde.
Följande är ett utdrag av SSML som renderas. Detta matas som input till Amazon Polly. Lägg till exempel märke till att texten "Hoppa över dold stycke" ska läsas i ljudet, och vi associerar den med en markering som talar om för oss att denna text förekommer på den plats på sidan som ges av XPath-uttrycket /html/body[1]/div[2]/ul[1]/li[1]
.
För att generera ljud i Amazon Polly kallar vi skriptet run_polly.sh
. Den kör AWS-kommandoradsgränssnitt (AWS CLI) kommando aws polly start-speech-synthesis-task
två gånger: en gång för att generera MP3-ljud och igen för att generera märkesfilen. Eftersom genereringen är asynkron pollar skriptet tills det hittar utdata i den angivna S3-bucket. När den hittar utdata laddas den ner till byggservern och kopierar filerna till web/polly
mapp. Följande är en lista över webbmappar:
- PRTPStaticDefault.html
- PRTPStaticConfig.html
- PRTPStaticCustom.html
- PRTP.js
- polly/PRTPStaticDefault/Joanna.mp3, Joanna.marks, Matthew.mp3, Matthew.marks
- polly/PRTPStaticConfig/Joanna.mp3, Joanna.marks, Matthew.mp3, Matthew.marks
- polly/PRTPStaticCustom/Joanna.mp3, Joanna.marks, Matthew.mp3, Matthew.marks
Varje sida har sin egen uppsättning röstspecifika MP3 och markerar filer. Dessa filer är de förgenererade filerna. Sidan behöver inte anropa Amazon Polly under körning; filerna är en del av webbbygget.
Konfigurationsdrivet fodral
Tänk sedan på gen_config.sh
:
Skriptet liknar skriptet i standardfallet, men de fetstilta linjerna indikerar huvudskillnaden. Vårt tillvägagångssätt är konfigurationsdrivet. Vi skräddarsyr innehållet som ska extraheras från sidan genom att ange vad som ska extraheras genom konfiguration, inte kod. I synnerhet använder vi JSON-filen transform_config.json
, som anger att innehållet som ska inkluderas är elementen med ID title
, main
, maintable
och qbtable
. Elementet med ID wrapup
bör uteslutas. Se följande kod:
Vi kör Python-programmet ModGenericXSLT.py
att modifiera generic.xslt
, som används i standardfallet, för att använda inkluderingarna och undantagen som vi anger i transform_config.json
. Programmet skriver resultaten till en temporär fil (example/tmp.xslt
), som den övergår till gen_ssml.sh
som sin XSLT-transform.
Detta är ett alternativ med låg kod. Webbutgivaren behöver inte veta hur man skriver XSLT. Men de behöver förstå strukturen på HTML-sidan och de ID:n som används i dess huvudsakliga organiseringselement.
Anpassningsfodral
Slutligen överväga gen_custom.sh
:
Det här skriptet är nästan identiskt med standardskriptet, förutom att det använder sin egen XSLT—example/custom.xslt
— snarare än den generiska XSLT. Följande är ett utdrag av XSLT:
Om du vill studera koden i detalj, se skripten och programmen i GitHub-repo.
Webbläsarinställningar och höjdpunkter
De statiska sidorna inkluderar en HTML5-ljudkontroll, som tar som ljudkälla MP3-filen som genereras av Amazon Polly och finns på webbservern:
Vid laddningstid laddar sidan också den Amazon Polly-genererade märkesfilen. Detta inträffar i PRTP.js
fil, som HTML-sidan innehåller. Följande är ett utdrag av märkesfilen för PRTPStaticDefault
:
Under ljuduppspelning finns det en ljudtimerhändelsehanterare PRTP.js
som kontrollerar ljudets aktuella tid, hittar texten att markera, hittar dess plats på sidan och markerar den. Texten som ska markeras är en post av typ sentence
i märkesfilen. Platsen är XPath-uttrycket i namnattributet för posten av typen SSML som föregår meningen. Till exempel, om klockan är 18400, enligt markeringsfilen, är meningen som ska markeras "Hoppa över dolda stycke", som börjar på 18334. Platsen är SSML-posten vid tidpunkten 17667: /html/body[1]/div[2]/ul[1]/li[1]
.
Testa dynamiska sidor
Sidan PRTPDynamic.html
demonstrerar dynamisk ljudåterläsning med standardmetoder, konfigurationsdrivna och anpassade ljudextraheringsmetoder.
Standardfall
Navigera till i din webbläsare PRTPDynamic.html
. Sidan har en frågeparameter, dynOption
, som accepterar värderingar default
, config
och custom
. Den har som standard default
, så du kan utelämna det i det här fallet. Sidan har två sektioner med dynamiskt innehåll:
- Senaste artiklarna – Byter ofta under dagen
- Grekiska filosofer Sök efter datum – Tillåter besökaren att söka efter grekiska filosofer efter datum och visar resultaten i en tabell
Skapa lite innehåll i Grekisk filosof genom att ange ett datumintervall på -800 till 0, som visas i exemplet. Sedan Välj hitta.
Spela nu upp ljudet genom att välja Spela i ljudkontrollen.
Bakom kulisserna kör sidan följande kod för att rendera och spela upp ljudet:
Först anropar den funktionen buildSSMLFromDefault
in PRTP.js
för att extrahera det mesta av texten från HTML-sidans brödtext. Den funktionen går igenom DOM-trädet och letar efter text i vanliga element som t.ex p
, h1
, pre
, span
och td
. Den ignorerar text i element som vanligtvis inte innehåller text som ska läsas upp, som t.ex audio
, option
och script
. Den bygger SSML-markering för att matas in till Amazon Polly. Följande är ett utdrag som visar extraktion av den första raden från philosopher
tabell:
Smakämnen chooseRenderAudio
funktion i PRTP.js
börjar med att initiera AWS SDK för Amazon Cognito, Amazon S3 och Amazon Polly. Denna initiering sker endast en gång. Om chooseRenderAudio
anropas igen eftersom innehållet på sidan har ändrats, initieringen hoppas över. Se följande kod:
Den genererar MP3-ljud från Amazon Polly. Genereringen är synkron för små SSML-ingångar och asynkron (med utdata skickad till S3-skopan) för stora SSML-ingångar (mer än 6,000 3 tecken). I det synkrona fallet ber vi Amazon Polly att tillhandahålla MPXNUMX-filen med en förutbestämd URL. När den syntetiserade utgången är klar ställer vi in src
ljudkontrollens attribut till den URL:en och ladda kontrollen. Vi begär sedan markeringsfilen och laddar den på samma sätt som i det statiska fallet. Se följande kod:
Konfigurationsdrivet fodral
Navigera till i din webbläsare PRTPDynamic.html?dynOption=config
. Spela upp ljudet. Ljuduppspelningen liknar standardfallet, men det finns mindre skillnader. Speciellt visst innehåll hoppas över.
Bakom kulisserna, när du använder config
alternativet extraherar sidan innehåll på ett annat sätt än i standardfallet. I standardfallet använder sidan buildSSMLFromDefault
. I det konfigurationsdrivna fallet anger sidan de avsnitt som den vill inkludera och exkludera:
Smakämnen buildSSMLFromConfig
funktion, definierad i PRTP.js
, går i DOM-trädet i var och en av sektionerna vars ID anges under inclusions
. Den extraherar innehåll från var och en och kombinerar dem tillsammans, i angiven ordning, för att bilda ett SSML-dokument. Det utesluter de avsnitt som anges under exclusions
. Det extraherar innehåll från varje avsnitt på samma sätt buildSSMLFromDefault
extraherar innehåll från sidkroppen.
Anpassningsfodral
Navigera till i din webbläsare PRTPDynamic.html?dynOption=custom
. Spela upp ljudet. Det finns tre märkbara skillnader. Låt oss notera dessa och överväga den anpassade koden som körs bakom kulisserna:
- Den läser huvudbrickorna i NW, SW, NE, SE ordning. Den anpassade koden hämtar vart och ett av dessa cellblock från
maintable
och lägger till dem i SSML i NW, SW, NE, SE ordning:
- "Tom Brady" sägs högt. Den anpassade koden placerar "Tom Brady"-text i en SSML
prosody
märka:
- Den läser bara de tre första raderna i quarterbacktabellen. Den läser kolumnrubrikerna för varje rad. Kontrollera koden i GitHub-repo för att upptäcka hur detta implementeras.
Städa upp
Ta bort CloudFormation-stacken för att undvika framtida avgifter.
Slutsats
I det här inlägget visade vi en teknisk lösning på ett värdefullt affärsproblem: hur man använder Amazon Polly för att läsa innehållet på en webbsida och framhäva innehållet när det läses. Vi visade detta med både statiska och dynamiska sidor. För att extrahera innehåll från sidan använde vi DOM-traversal och XSLT. För att underlätta framhävning använde vi funktionen för talmärken i Amazon Polly.
Lär dig mer om Amazon Polly genom att besöka dess service sida.
Ställ gärna frågor i kommentarerna.
Om författarna
Mike Havey är en lösningsarkitekt för AWS med över 25 års erfarenhet av att bygga företagsapplikationer. Mike är författare till två böcker och många artiklar. Besök hans Amazon författarsida att läsa mer.
Vineet Kachhawaha är en lösningsarkitekt på AWS med expertis inom maskininlärning. Han är ansvarig för att hjälpa kunder att utforma skalbara, säkra och kostnadseffektiva arbetsbelastningar på AWS.