Citiți pagini web și evidențiați conținut folosind Amazon Polly PlatoBlockchain Data Intelligence. Căutare verticală. Ai.

Citiți pagini web și evidențiați conținut folosind Amazon Polly

În această postare, demonstrăm cum se utilizează Amazon Polly—un serviciu cloud de top care convertește textul în vorbire reală — pentru a citi conținutul unei pagini web și a evidenția conținutul pe măsură ce este citită. Adăugarea redării audio la o pagină web îmbunătățește accesibilitatea și experiența vizitatorilor paginii. Conținutul îmbunătățit audio este mai de impact și mai memorabil, atrage mai mult trafic către pagină și profită de puterea de cheltuire a vizitatorilor. De asemenea, îmbunătățește marca companiei sau organizației care publică pagina. Tehnologia text-to-speech face ca aceste beneficii de afaceri să fie atinse. Accelerăm această călătorie demonstrând cum să atingem acest obiectiv folosind Amazon Polly.

Această capacitate îmbunătățește accesibilitatea pentru vizitatorii cu dizabilități și ar putea fi adoptată ca parte a strategiei de accesibilitate a organizației dvs. La fel de important, îmbunătățește experiența paginii pentru vizitatorii fără dizabilități. Ambele grupuri au o putere semnificativă de cheltuire și cheltuiesc mai liber din paginile care folosesc îmbunătățirea audio pentru a le atrage atenția.

Prezentare generală a soluției

PollyReadsThePage (PRTP) - așa cum ne referim la soluție - permite unui editor de pagini web să introducă un control audio pe pagina sa web. Când vizitatorul alege Joaca pe control, controlul citește pagina și evidențiază conținutul. PRTP folosește capacitatea generală a Amazon Polly pentru a sintetiza vorbirea din text. Invocă Amazon Polly pentru a genera două artefacte pentru fiecare pagină:

  • Conținutul audio într-un format redabil de browser: MP3
  • Un fișier de semne de vorbire care indică pentru fiecare propoziție de text:
    • Timpul în timpul redării în care este citită propoziția
    • Locația de pe pagina în care apare propoziția

Când vizitatorul alege Joaca, browserul redă fișierul MP3. Pe măsură ce sunetul este citit, browserul verifică ora, găsește în fișierul cu semne ce propoziție să citească la acel moment, o localizează pe pagină și o evidențiază.

PRTP permite vizitatorului să citească în diferite voci și limbi. Fiecare voce necesită propria sa pereche de fișiere. PRTP folosește voci neuronale. Pentru o listă de voci neuronale și limbi acceptate, consultați Voci neuronale. Pentru o listă completă a vocilor standard și neuronale din Amazon Polly, consultați Voci în Amazon Polly.

Luăm în considerare două tipuri de pagini web: pagini statice și dinamice. Într-o static pagina, conținutul este conținut în pagină și se modifică numai atunci când este publicată o nouă versiune a paginii. Compania poate actualiza pagina zilnic sau săptămânal, ca parte a procesului său de creare web. Pentru acest tip de pagină, este posibil să pre-generați fișierele audio în timpul construirii și să le plasați pe serverul web pentru redare. După cum arată figura următoare, scriptul PRTP Pre-Gen invocă Amazon Polly pentru a genera audio. Ia ca intrare pagina HTML însăși și, opțional, un fișier de configurare care specifică ce text din pagină să extragă (Text Extract Config). Dacă configurația de extragere este omisă, scriptul pre-gen alege textul de extras din corpul paginii. Amazon Polly scoate fișierele într-un Serviciul Amazon de stocare simplă (Amazon S3) găleată; scriptul le copiază pe serverul dvs. web. Când vizitatorul redă audio, browserul descarcă MP3-ul direct de pe serverul web. Pentru momentele evidențiate, o bibliotecă drop-in, PRTP.js, folosește fișierul de marcaje pentru a evidenția textul citit.

Conținutul a dinamic pagina se modifică ca răspuns la interacțiunea vizitatorului, astfel încât sunetul nu poate fi pregenerat, ci trebuie sintetizat dinamic. După cum arată figura următoare, atunci când vizitatorul redă audio, pagina folosește PRTP.js pentru a genera audio în Amazon Polly și evidențiază sunetul sintetizat folosind aceeași abordare ca și în cazul paginilor statice. Pentru a accesa serviciile AWS din browser, vizitatorul are nevoie de o identitate AWS. Vă arătăm cum să folosiți un Amazon Cognito grup de identitate pentru a permite vizitatorului accesul suficient la Amazon Polly și găleata S3 pentru a reda audio.

Conținut dinamic

Generarea atât a semnalelor audio Mp3, cât și a semnelor de vorbire necesită ca serviciul Polly să sintetizeze aceeași intrare de două ori. Consultați Pagina de prețuri Amazon Polly pentru a înțelege implicațiile costurilor. Pregenerarea economisește costuri, deoarece sinteza este efectuată în timpul construirii, mai degrabă decât la cerere pentru fiecare interacțiune cu vizitatorul.

Codul care însoțește această postare este disponibil ca un depozit open-source pe GitHub.

Pentru a explora soluția, urmează acești pași:

  1. Configurați resursele, inclusiv serverul de compilare pre-gen, compartimentul S3, serverul web și identitatea Amazon Cognito.
  2. Rulați compilarea statică pre-gen și testați paginile statice.
  3. Testați paginile dinamice.

Cerințe preliminare

Pentru a rula acest exemplu, aveți nevoie de un Cont AWS cu permisiunea de a folosi Amazon Polly, Amazon S3, Amazon Cognito și (în scop demonstrativ) AWS Cloud9.

Asigurarea resurselor

Împărtășim un Formarea AWS Cloud șablon pentru a crea în contul dvs. un mediu demonstrativ autonom, care să vă ajute să urmăriți postarea. Dacă preferați să configurați PRTP în propriul mediu, consultați instrucțiunile din README.md.

Pentru a furniza mediul demonstrativ folosind CloudFormation, mai întâi descărcați o copie a fișierului Șablonul CloudFormation. Apoi parcurgeți următorii pași:

  1. În consola AWS CloudFormation, alegeți Creați stivă.
  2. Alege Cu resurse noi (standard).
  3. Selectați Încărcați un fișier șablon.
  4. Alege Alegeți fișierul pentru a încărca copia locală a șablonului pe care l-ați descărcat. Numele fișierului este prtp.yml.
  5. Alege Pagina Următoare →.
  6. Introduceți un nume de stivă la alegere. Mai târziu îl introduceți din nou ca înlocuitor pentru <StackName>.
  7. Puteți păstra valorile implicite în parametrii secţiune.
  8. Alege Pagina Următoare →.
  9. Continuați prin secțiunile rămase.
  10. Citiți și bifați casetele de selectare din Capabilitățile secţiune.
  11. Alege Creați stivă.
  12. Când stiva este completă, găsiți valoarea pentru BucketName în ieșirile stivei.

Vă încurajăm să examinați stiva împreună cu echipa de securitate înainte de a-l folosi într-un mediu de producție.

Configurați serverul web și serverul pre-gen într-un IDE AWS Cloud9

Apoi, pe consola AWS Cloud9, localizați mediul PRTPDemoCloud9 creat de stiva CloudFormation. Alege Deschideți IDE pentru a deschide mediul AWS Cloud9. Deschideți o fereastră de terminal și rulați următoarele comenzi, care clonează codul PRTP, setează dependențe pre-gen și pornește un server web pentru a testa:

#Obtain PRTP code
cd /home/ec2-user/environment
git clone https://github.com/aws-samples/amazon-polly-reads-the-page.git

# Navigate to that code
cd amazon-polly-reads-the-page/setup

# Install Saxon and html5 Python lib. For pre-gen.
sh ./setup.sh <StackName>

# Run Python simple HTTP server
cd ..
./runwebserver.sh <IngressCIDR> 

Pentru <StackName>, utilizați numele pe care l-ați dat stivei CloudFormation. Pentru <IngressCIDR>, specificați o serie de adrese IP permise pentru a accesa serverul web. Pentru a restricționa accesul la browser pe computerul dvs. local, găsiți adresa IP folosind https://whatismyipaddress.com/ și anexează /32 pentru a specifica intervalul. De exemplu, dacă IP-ul dvs. este 10.2.3.4, use 10.2.3.4/32. Serverul ascultă pe portul 8080. Adresa IP publică pe care ascultă serverul este dată în ieșire. De exemplu:

Public IP is

3.92.33.223

Testați paginile statice

În browser, navigați la PRTPStaticDefault.html. (Dacă utilizați demonstrația, adresa URL este http://<cloud9host>:8080/web/PRTPStaticDefault.html, În cazul în care <cloud9host> este adresa IP publică pe care ați descoperit-o la configurarea IDE-ului.) Alegeți Joaca pe controlul audio din partea de sus. Ascultați audio și urmăriți cele mai importante momente. Explorați controlul prin schimbarea vitezei, modificarea vocilor, pauză, derulare rapidă înainte și derulare înapoi. Următoarea captură de ecran arată pagina; textul „Oriește paragraful ascuns” este evidențiat deoarece este în curs de citire.

Citiți pagini web și evidențiați conținut folosind Amazon Polly PlatoBlockchain Data Intelligence. Căutare verticală. Ai.

Incearca la fel pt PRTPStaticConfig.html și PRTPStaticCustom.html. Rezultatele sunt similare. De exemplu, toți trei citesc textul alternativ pentru fotografia pisicii („Poza aleatorie a unei pisici”). Toți trei citesc NE, NW, SE și SW ca cuvinte complete („nord-est”, „nord-vest”, „sud-est”, „sud-vest”), profitând de lexiconele Amazon Polly.

Observați principalele diferențe de sunet:

  • PRTPStaticDefault.html citește tot textul din corpul paginii, inclusiv partea de încheiere din partea de jos cu „Gândurile tale într-un singur cuvânt”, „Trimite interogarea”, „Ultima actualizare 1 aprilie 2020” și „Întrebări pentru echipa de dezvoltare”. PRTPStaticConfig.html și PRTPStaticCustom.html nu le citiți, deoarece exclud în mod explicit încheierea din sinteza vorbirii.
  • PRTPStaticCustom.html citește Cele mai bine vândute QB masa diferit de celelalte. Citește numai primele trei rânduri și citește numărul rândului pentru fiecare rând. Se repetă coloanele pentru fiecare rând. PRTPStaticCustom.html folosește o transformare personalizată pentru a personaliza citirea tabelului. Celelalte pagini folosesc redarea implicită a tabelului.
  • PRTPStaticCustom.html citește „Tom Brady” la un volum mai mare decât restul textului. Utilizează limbajul de marcare a sintezei vorbirii (SSML) prosody etichetă pentru a adapta lectura lui Tom Brady. Celelalte pagini nu se croiesc în acest fel.
  • PRTPStaticCustom.html, datorită unei transformări personalizate, citește plăcile principale în ordinea NV, SW, NE, SE; adică, scrie „Articolele de astăzi”, „Citatul zilei”, „Fotografia zilei”, „Glumele zilei”. Celelalte pagini citesc în ordinea în care apar plăcile în ordinea naturală NV, NE, SW, SE în care apar în HTML: „Articolele de astăzi”, „Fotografia zilei”, „Citatul zilei”, „Glume ale zilei”. Zi."

Să cercetăm mai profund modul în care este generat sunetul și modul în care pagina evidențiază textul.

Pregenerator static

Repo-ul nostru GitHub include fișiere audio pregenerate pentru PRPTStatic pagini, dar dacă doriți să le generați singur, din shell-ul bash din IDE-ul AWS Cloud9, executați următoarele comenzi:

# navigate to examples
cd /home/ec2-user/environment/amazon-polly-reads-the-page-blog/pregen/examples

# Set env var for my S3 bucket. Example, I called mine prtp-output
S3_BUCKET=prtp-output # Use output BucketName from CloudFormation

#Add lexicon for pronuniciation of NE NW SE NW
#Script invokes aws polly put-lexicon
./addlexicon.sh.

#Gen each variant
./gen_default.sh
./gen_config.sh
./gen_custom.sh

Acum să vedem cum funcționează acele scripturi.

Cazul implicit

Începem cu gen_default.sh:

cd ..
python FixHTML.py ../web/PRTPStaticDefault.html  
   example/tmp_wff.html
./gen_ssml.sh example/tmp_wff.html generic.xslt example/tmp.ssml
./run_polly.sh example/tmp.ssml en-US Joanna 
   ../web/polly/PRTPStaticDefault compass
./run_polly.sh example/tmp.ssml en-US Matthew 
   ../web/polly/PRTPStaticDefault compass

Scriptul începe prin rularea programului Python FixHTML.py pentru a face fișierul HTML sursă PRTPStaticDefault.html bine format. Acesta scrie versiunea bine formată a fișierului în example/tmp_wff.html. Acest pas este crucial din două motive:

  • Majoritatea surselor HTML nu sunt bine formate. Acest pas repară HTML-ul sursă să fie bine format. De exemplu, multe pagini HTML nu se închid P elemente. Acest pas le închide.
  • Ținem evidența unde găsim textul în pagina HTML. Trebuie să urmărim locațiile folosind aceeași structură a modelului de obiect de document (DOM) pe care o folosește browserul. De exemplu, browserul adaugă automat un TBODY la TABLE. Programul Python urmează aceleași reparații bine formate ca și browserul.

gen_ssml.sh ia HTML bine format ca intrare, îi aplică o transformare XML stylesheet transformation (XSLT) și scoate un fișier SSML. (SSML este limba din Amazon Polly pentru a controla modul în care audio este redat din text.) În exemplul curent, intrarea este example/tmp_wff.html. Ieșirea este example/tmp.ssml. Sarcina transformării este să decidă ce text să extragă din HTML și să alimenteze Amazon Polly. generic.xslt este o transformare XSLT implicită sensibilă pentru majoritatea paginilor web. În următorul exemplu de fragment de cod, acesta exclude controlul audio, antetul HTML, precum și elementele HTML precum script și form. De asemenea, exclude elementele cu atributul ascuns. Include elemente care conțin de obicei text, cum ar fi P, H1, și SPAN. Pentru acestea, redă atât un semn, inclusiv expresia XPath completă a elementului, cât și valoarea elementului.

<!-- skip the header -->
<xsl:template match="html/head">
</xsl:template>

<!-- skip the audio itself -->
<xsl:template match="html/body/table[@id='prtp-audio']">
</xsl:template>

<!-- For the body, work through it by applying its templates. This is the default. -->
<xsl:template match="html/body">
<speak>
      <xsl:apply-templates />
</speak>
</xsl:template>

<!-- skip these -->
<xsl:template match="audio|option|script|form|input|*[@hidden='']">
</xsl:template>

<!-- include these -->
<xsl:template match="p|h1|h2|h3|h4|li|pre|span|a|th/text()|td/text()">
<xsl:for-each select=".">
<p>
      <mark>
          <xsl:attribute name="name">
          <xsl:value-of select="prtp:getMark(.)"/>
          </xsl:attribute>
      </mark>
      <xsl:value-of select="normalize-space(.)"/>
</p>
</xsl:for-each>
</xsl:template>

Următorul este un fragment din SSML care este redat. Acesta este furnizat ca intrare către Amazon Polly. Observați, de exemplu, că textul „Oriește paragraful ascuns” urmează să fie citit în audio și îl asociem cu un semn, care ne spune că acest text apare în locația din pagină dată de expresia XPath /html/body[1]/div[2]/ul[1]/li[1].

<speak>
<p><mark name="/html/body[1]/div[1]/h1[1]"/>PollyReadsThePage Normal Test Page</p>
<p><mark name="/html/body[1]/div[2]/p[1]"/>PollyReadsThePage is a test page for audio readout with highlights.</p>
<p><mark name="/html/body[1]/div[2]/p[2]"/>Here are some features:</p>
<p><mark name="/html/body[1]/div[2]/ul[1]/li[1]"/>Skips hidden paragraph</p>
<p><mark name="/html/body[1]/div[2]/ul[1]/li[2]"/>Speaks but does not highlight collapsed content</p>
…
</speak>

Pentru a genera audio în Amazon Polly, numim scriptul run_polly.sh. Acesta rulează Interfața liniei de comandă AWS (AWS CLI). aws polly start-speech-synthesis-task de două ori: o dată pentru a genera audio MP3 și din nou pentru a genera fișierul de semne. Deoarece generarea este asincronă, scriptul interogează până când găsește rezultatul în compartimentul S3 specificat. Când găsește rezultatul, se descarcă pe serverul de compilare și copiază fișierele în web/polly pliant. Următoarea este o listă a folderelor web:

  • 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

Fiecare pagină are propriul set de fișiere MP3 specifice vocii și de marcare. Aceste fișiere sunt fișiere pre-generate. Pagina nu trebuie să invoce Amazon Polly în timpul execuției; fișierele fac parte din construcția web.

Carcasă bazată pe configurație

Apoi, luați în considerare gen_config.sh:

cd ..
python FixHTML.py ../web/PRTPStaticConfig.html 
  example/tmp_wff.html
python ModGenericXSLT.py example/transform_config.json 
  example/tmp.xslt
./gen_ssml.sh example/tmp_wff.html example/tmp.xslt 
  example/tmp.ssml
./run_polly.sh example/tmp.ssml en-US Joanna 
  ../web/polly/PRTPStaticConfig compass
./run_polly.sh example/tmp.ssml en-US Matthew 
  ../web/polly/PRTPStaticConfig compass

Scriptul este similar cu scriptul în cazul implicit, dar liniile îngroșate indică diferența principală. Abordarea noastră este bazată pe config. Personalizăm conținutul care urmează să fie extras din pagină specificând ce să extragem prin configurare, nu prin cod. În special, folosim fișierul JSON transform_config.json, care precizează că conținutul de inclus sunt elementele cu ID-uri title, main, maintable, și qbtable. Elementul cu ID wrapup ar trebui exclus. Vezi următorul cod:

{
 "inclusions": [ 
 	{"id" : "title"} , 
 	{"id": "main"}, 
 	{"id": "maintable"}, 
 	{"id": "qbtable" }
 ],
 "exclusions": [
 	{"id": "wrapup"}
 ]
}

Rulam programul Python ModGenericXSLT.py a modifica generic.xslt, folosit în cazul implicit, pentru a folosi incluziunile și excluderile pe care le specificăm în transform_config.json. Programul scrie rezultatele într-un fișier temp (example/tmp.xslt), la care trece gen_ssml.sh ca transformarea sa XSLT.

Aceasta este o opțiune low-code. Editorul web nu trebuie să știe cum să scrie XSLT. Dar ei trebuie să înțeleagă structura paginii HTML și ID-urile utilizate în principalele sale elemente de organizare.

Carcasă de personalizare

În cele din urmă, ia în considerare gen_custom.sh:

cd ..
python FixHTML.py ../web/PRTPStaticCustom.html 
   example/tmp_wff.html
./gen_ssml.sh example/tmp_wff.html example/custom.xslt  
   example/tmp.ssml
./run_polly.sh example/tmp.ssml en-US Joanna 
   ../web/polly/PRTPStaticCustom compass
./run_polly.sh example/tmp.ssml en-US Matthew 
   ../web/polly/PRTPStaticCustom compass

Acest script este aproape identic cu scriptul implicit, cu excepția faptului că folosește propriul XSLT—example/custom.xslt— mai degrabă decât XSLT generic. Următorul este un fragment din XSLT:

<!-- Use NW, SW, NE, SE order for main tiles! -->
<xsl:template match="*[@id='maintable']">
    <mark>
        <xsl:attribute name="name">
        <xsl:value-of select="stats:getMark(.)"/>
        </xsl:attribute>
    </mark>
    <xsl:variable name="tiles" select="./tbody"/>
    <xsl:variable name="tiles-nw" select="$tiles/tr[1]/td[1]"/>
    <xsl:variable name="tiles-ne" select="$tiles/tr[1]/td[2]"/>
    <xsl:variable name="tiles-sw" select="$tiles/tr[2]/td[1]"/>
    <xsl:variable name="tiles-se" select="$tiles/tr[2]/td[2]"/>
    <xsl:variable name="tiles-seq" select="($tiles-nw,  $tiles-sw, $tiles-ne, $tiles-se)"/>
    <xsl:for-each select="$tiles-seq">
         <xsl:apply-templates />  
    </xsl:for-each>
</xsl:template>   

<!-- Say Tom Brady load! -->
<xsl:template match="span[@style = 'color:blue']" >
<p>
      <mark>
          <xsl:attribute name="name">
          <xsl:value-of select="prtp:getMark(.)"/>
          </xsl:attribute>
      </mark>
      <prosody volume="x-loud">Tom Brady</prosody>
</p>
</xsl:template>

Dacă doriți să studiați codul în detaliu, consultați scripturile și programele din depozitul GitHub.

Configurarea browserului și evidențieri

Paginile statice includ un control audio HTML5, care ia ca sursă audio fișierul MP3 generat de Amazon Polly și care se află pe serverul web:

<audio id="audio" controls>
  <source src="polly/PRTPStaticDefault/en/Joanna.mp3" type="audio/mpeg">
</audio>

În momentul încărcării, pagina încarcă și fișierul de mărci generate de Amazon Polly. Acest lucru se întâmplă în PRTP.js fișier, pe care pagina HTML îl include. Următorul este un fragment din fișierul de note pentru PRTPStaticDefault:

{“time”:11747,“type”:“sentence”,“start”:289,“end”:356,“value”:“PollyReadsThePage is a test page for audio readout with highlights.“}
{“time”:15784,“type”:“ssml”,“start”:363,“end”:403,“value”:“/html/body[1]/div[2]/p[2]“}
{“time”:16427,“type”:“sentence”,“start”:403,“end”:426,“value”:“Here are some features:“}
{“time”:17677,“type”:“ssml”,“start”:433,“end”:480,“value”:“/html/body[1]/div[2]/ul[1]/li[1]“}
{“time”:18344,“type”:“sentence”,“start”:480,“end”:502,“value”:“Skips hidden paragraph”}
{“time”:19894,“type”:“ssml”,“start”:509,“end”:556,“value”:“/html/body[1]/div[2]/ul[1]/li[2]“}
{“time”:20537,“type”:“sentence”,“start”:556,“end”:603,“value”:“Speaks but does not highlight collapsed content”}

În timpul redării audio, există un handler de evenimente cu temporizator audio PRTP.js care verifică ora curentă a audio, găsește textul de evidențiat, găsește locația acestuia pe pagină și îl evidențiază. Textul care trebuie evidențiat este o intrare de tip sentence în dosarul de mărci. Locația este expresia XPath din atributul name al intrării de tip SSML care precede propoziția. De exemplu, dacă ora este 18400, conform fișierului cu semne, propoziția care trebuie evidențiată este „Omite paragraful ascuns”, care începe la 18334. Locația este intrarea SSML la momentul 17667: /html/body[1]/div[2]/ul[1]/li[1].

Testați paginile dinamice

Pagina PRTPDynamic.html demonstrează citirea audio dinamică folosind abordări implicite, bazate pe configurație și personalizate de extracție audio.

Cazul implicit

În browser, navigați la PRTPDynamic.html. Pagina are un parametru de interogare, dynOption, care acceptă valori default, config, și custom. Este implicit default, deci îl puteți omite în acest caz. Pagina are două secțiuni cu conținut dinamic:

  • Ultimele articole – Se schimbă frecvent pe parcursul zilei
  • Filosofii greci caută după dată – Permite vizitatorului să caute filozofi greci după dată și arată rezultatele într-un tabel

Citiți pagini web și evidențiați conținut folosind Amazon Polly PlatoBlockchain Data Intelligence. Căutare verticală. Ai.

Creați conținut în Filosof grec secțiune prin introducerea unui interval de date de la -800 la 0, așa cum se arată în exemplu. Atunci alege Găsi.

Acum redați sunetul alegând Joaca în controlul audio.

În culise, pagina rulează următorul cod pentru a reda și a reda audio:

   buildSSMLFromDefault();
   chooseRenderAudio();
   setVoice();

Mai întâi apelează funcția buildSSMLFromDefault in PRTP.js pentru a extrage cea mai mare parte a textului din corpul paginii HTML. Această funcție parcurge arborele DOM, căutând text în elemente comune, cum ar fi p, h1, pre, span, și td. Ignoră textul în elementele care de obicei nu conțin text pentru a fi citit cu voce tare, cum ar fi audio, option, și script. Acesta creează un marcaj SSML pentru a fi introdus în Amazon Polly. Următorul este un fragment care arată extragerea primului rând din philosopher masa:

<speak>
...
  <p><mark name="/HTML[1]/BODY[1]/DIV[3]/DIV[1]/DIV[1]/TABLE[1]/TBODY[1]/TR[2]/TD[1]"/>Thales</p>
  <p><mark name="/HTML[1]/BODY[1]/DIV[3]/DIV[1]/DIV[1]/TABLE[1]/TBODY[1]/TR[2]/TD[2]"/>-624 to -546</p>
  <p><mark name="/HTML[1]/BODY[1]/DIV[3]/DIV[1]/DIV[1]/TABLE[1]/TBODY[1]/TR[2]/TD[3]"/>Miletus</p>
  <p><mark name="/HTML[1]/BODY[1]/DIV[3]/DIV[1]/DIV[1]/TABLE[1]/TBODY[1]/TR[2]/TD[4]"/>presocratic</p>
...
</speak>

chooseRenderAudio funcția în PRTP.js începe prin inițializarea AWS SDK pentru Amazon Cognito, Amazon S3 și Amazon Polly. Această inițializare are loc o singură dată. Dacă chooseRenderAudio este invocat din nou deoarece conținutul paginii s-a schimbat, inițializarea este omisă. Vezi următorul cod:

AWS.config.region = env.REGION
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
            IdentityPoolId: env.IDP});
audioTracker.sdk.connection = {
   polly: new AWS.Polly({apiVersion: '2016-06-10'}),
   s3: new AWS.S3()
};

Acesta generează audio MP3 de la Amazon Polly. Generarea este sincronă pentru intrări SSML mici și asincronă (cu ieșire trimisă la bucket-ul S3) pentru intrări SSML mari (mai mare de 6,000 de caractere). În cazul sincron, îi cerem lui Amazon Polly să furnizeze fișierul MP3 folosind o adresă URL presemnată. Când ieșirea sintetizată este gata, setăm src atributul controlului audio la acea adresă URL și încărcați controlul. Solicităm apoi fișierul de mărci și îl încărcăm în același mod ca în cazul static. Vezi următorul cod:

// create signed URL
const signer = new AWS.Polly.Presigner(pollyAudioInput, audioTracker.sdk.connection.polly);

// call Polly to get MP3 into signed URL
signer.getSynthesizeSpeechUrl(pollyAudioInput, function(error, url) {
  // Audio control uses signed URL
  audioTracker.audioControl.src =
    audioTracker.sdk.audio[audioTracker.voice];
  audioTracker.audioControl.load();

  // call Polly to get marks
  audioTracker.sdk.connection.polly.synthesizeSpeech(
    pollyMarksInput, function(markError, markData) {
    const marksStr = new
      TextDecoder().decode(markData.AudioStream);
    // load marks into page the same as with static
    doLoadMarks(marksStr);
  });
});

Carcasă bazată pe configurație

În browser, navigați la PRTPDynamic.html?dynOption=config. Redați audio. Redarea audio este similară cu cazul implicit, dar există diferențe minore. În special, o parte din conținut este omisă.

În culise, atunci când utilizați config opțiunea, pagina extrage conținutul diferit decât în ​​cazul implicit. În cazul implicit, pagina folosește buildSSMLFromDefault. În cazul bazat pe configurație, pagina specifică secțiunile pe care dorește să le includă și să le excludă:

const ssml = buildSSMLFromConfig({
	 "inclusions": [ 
	 	{"id": "title"}, 
	 	{"id": "main"}, 
	 	{"id": "maintable"}, 
	 	{"id": "phil-result"},
	 	{"id": "qbtable"}, 
	 ],
	 "exclusions": [
	 	{"id": "wrapup"}
	 ]
	});

buildSSMLFromConfig funcţie, definită în PRTP.js, parcurge arborele DOM în fiecare dintre secțiunile al căror ID este furnizat sub inclusions. Extrage conținut din fiecare și le combină împreună, în ordinea specificată, pentru a forma un document SSML. Exclude secțiunile specificate în exclusions. Extrage conținut din fiecare secțiune în același mod buildSSMLFromDefault extrage conținut din corpul paginii.

Carcasă de personalizare

În browser, navigați la PRTPDynamic.html?dynOption=custom. Redați audio. Există trei diferențe vizibile. Să notăm acestea și să luăm în considerare codul personalizat care rulează în culise:

  • Citește plăcile principale în ordinea NV, SW, NE, SE. Codul personalizat primește fiecare dintre aceste blocuri de celule de la maintable și le adaugă la SSML în ordinea NW, SW, NE, SE:
const nw = getElementByXpath("//*[@id='maintable']//tr[1]/td[1]");
const sw = getElementByXpath("//*[@id='maintable']//tr[2]/td[1]");
const ne = getElementByXpath("//*[@id='maintable']//tr[1]/td[2]");
const se = getElementByXpath("//*[@id='maintable']//tr[2]/td[2]");
[nw, sw, ne, se].forEach(dir => buildSSMLSection(dir, []));

  • „Tom Brady” este rostit cu voce tare. Codul personalizat pune textul „Tom Brady” într-un SSML prosody etichetă:
if (cellText == "Tom Brady") {
   addSSMLMark(getXpathOfNode( node.childNodes[tdi]));
   startSSMLParagraph();
   startSSMLTag("prosody", {"volume": "x-loud"});
   addSSMLText(cellText);
   endSSMLTag();
   endSSMLParagraph();
}

  • Citește doar primele trei rânduri ale tabelului de fundași. Citește anteturile coloanei pentru fiecare rând. Verificați codul din depozitul GitHub pentru a descoperi cum este implementat.

A curăța

Pentru a evita costurile viitoare, ștergeți stiva CloudFormation.

Concluzie

În această postare, am demonstrat o soluție tehnică la o problemă de afaceri de mare valoare: cum să folosiți Amazon Polly pentru a citi conținutul unei pagini web și a evidenția conținutul pe măsură ce este citită. Am arătat acest lucru folosind atât pagini statice, cât și dinamice. Pentru a extrage conținutul din pagină, am folosit traversarea DOM și XSLT. Pentru a facilita evidențierea, am folosit capacitatea de semne de vorbire din Amazon Polly.

Aflați mai multe despre Amazon Polly vizitând-o pagina de service.

Simțiți-vă liber să puneți întrebări în comentarii.


Despre autori

Citiți pagini web și evidențiați conținut folosind Amazon Polly PlatoBlockchain Data Intelligence. Căutare verticală. Ai.Mike Havey este un arhitect de soluții pentru AWS cu peste 25 de ani de experiență în construirea de aplicații pentru întreprinderi. Mike este autorul a două cărți și a numeroase articole. Vizitează-i Amazon autor pagina pentru a citi mai mult.

Citiți pagini web și evidențiați conținut folosind Amazon Polly PlatoBlockchain Data Intelligence. Căutare verticală. Ai.Vineet Kachhawaha este arhitect de soluții la AWS cu experiență în învățarea automată. El este responsabil pentru a ajuta clienții să proiecteze sarcini de lucru scalabile, sigure și rentabile pe AWS.

Timestamp-ul:

Mai mult de la Învățare automată AWS