Skip to main content

  | मौसम…

411 समाचार
Public archive edition · Attributed source reporting with original dates · AI drafts are excluded

411 REFERENCE · Wikibooks

XQuery/XHTML + Voice

Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.

Motivation You want to have your browser read Twitter updates using a text-to-speech conversion extension that is built into your browser. Method XHTML + Voice is supported by the Opera Browser with the Voice extension installed. In this simple application it is used as a browser-based Text-to-Speech engine. Twitter Radio This script creates a simple text-to-speech version of Twitter Search. Obama Limitations Window has to be active for the T2S to play on refresh The cleaned text to speak is held in a div which is rendered as white on white text. Initially it was output as a block in the header but it did not seen possible to apply styles. Applying a style display:none hid the text from the T2S engine as well! Transforming the atom content to a a string suitable to speak needs more work. Retweets and similar tweets could be removed using levenstein Male and female voices are assigned randomly by tweet. I'd like to cache the voice assigned to a tweeter so that tweets are consistently spoken in the same voice The initial load doesn't seem to trigger playing, hence the play button, but this also re-fetches the page. This is an ideal situation to use AJAX instead of refresh The T2S engine is quite good at rendering the text but it needs be helped in places, for example by replacing texting abbreviations with their expanded form. declare namespace atom = "http://www.w3.org/2005/Atom"; declare variable $n := xs:integer( request:get-parameter("n",6)); declare variable $search := request:get-parameter("search",""); declare variable $timestamp := request:get-parameter("timestamp",()); declare variable $seconds := $n * 12; declare variable $noise := ( "<b>", "</b>", "<.+?>", "http://[^ ]+", "#\w+", "RT *@\w+", "@\w+", "[\[\]\\=«»:;()_?!~\|]", '"', "\.\.+" ); declare function local:clean ($talk as xs:string, $noise as xs:string*) as xs:string { if (empty($noise)) then $talk else local:clean(replace($talk,string($noise[1])," "),subsequence($noise,2)) }; declare function local:clean($talk as xs:string) as xs:string { local:clean($talk,$noise) }; declare option exist:serialize "method=xhtml media-type=application/xv+xml"; let $entries := doc(concat("http://search.twitter.com/search.atom?lang=en&q=",encode-for-uri($search)))//atom:entry let $entries := if (exists($timestamp)) then $entries[atom:published>$timestamp] else $entries let $entries := $entries[position() <= $n] let $newtimestamp := if (exists($entries)) then string($entries[1]/atom:published) else $timestamp let $entries := reverse($entries) return <html xmlns="http://www.w3.org/1999/xhtml" xmlns:vxml="http://www.w3.org/2001/vxml" xmlns:xv="http://www.voicexml.org/2002/xhtml+voice" xmlns:ev="http://www.w3.org/2001/xml-events" > <head> <meta http-equiv="refresh" content="{$seconds};url=?search={encode-for-uri($search)}&timestamp={$newtimestamp}&n={$n}"/> <title>Tweets matching {$search}</title> <vxml:form id="say"> <vxml:block> <vxml:prompt src="#news"/> </vxml:block> </vxml:form> <link rel="stylesheet" type="text/css" href="voice2.css" title="Normal"/> </head> <body ev:event="load" ev:handler="#say" > <h1>Twitter radio, listening to tweets matching {$search}</h1> <form method="get" > Listen for <input type="text" name="search" value="{$search}" /> Max items <input type="text" name="n" value="{$n}" size="4" /> <input type="submit" value="Tune"/> <button ev:event="click" ev:handler="#say">Play</button> </form> {for $entry in $entries return <div> <a href="{$entry/atom:author/atom:uri}">{substring-before($entry/atom:author/atom:name, "(")}</a>   {util:parse(concat("<span xmlns='http://www.w3.org/1999/xhtml' >",$entry/atom:content/(text(),*),"</span>"))} </div> } <div id="news"> {for $entry in $entries return <p class='{if (math:random ()< 0.5) then "male" else "female"}'> { local:clean($entry/atom:content/text())} </p> } </div> </body> </html> With the style sheet: .male { voice-family: male; pause-after:1.5s; } .female { voice-family:female; pause-after:1s } #news { color:white; background-color:white }