XQuery/XHTML + 語音
外觀
< XQuery
您希望使用瀏覽器內建的文字到語音轉換擴充套件來讓瀏覽器朗讀推特更新。
Opera 瀏覽器支援 XHTML + Voice,安裝了 Voice 擴充套件。在這個簡單的應用程式中,它用作基於瀏覽器的文字到語音引擎。
此指令碼建立了推特搜尋的簡單文字到語音版本。
- 視窗必須處於活動狀態才能在重新整理時播放 T2S。
- 要朗讀的清理後的文字儲存在一個 div 中,該 div 呈現為白色文字。最初它在標題中作為一個塊輸出,但似乎無法應用樣式。應用樣式 display:none 也隱藏了 T2S 引擎的文字!
- 將原子內容轉換為適合朗讀的字串需要更多工作。
- 可以使用 levenstein 刪除轉發和類似的推文。
- 男性和女性聲音由推文隨機分配。我希望快取分配給推文者的聲音,以便推文始終以相同的聲音朗讀。
- 初始載入似乎沒有觸發播放,因此有了播放按鈕,但這也重新獲取了頁面。
- 這是使用 AJAX 而不是重新整理的理想情況。
- T2S 引擎在渲染文字方面相當不錯,但它需要在某些地方得到幫助,例如用擴充套件形式替換簡訊縮寫。
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>
使用樣式表
.male {
voice-family: male;
pause-after:1.5s;
}
.female {
voice-family:female;
pause-after:1s
}
#news {
color:white;
background-color:white
}