<
p:declare-step xmlns:p=
"http://www.w3.org/ns/xproc" xmlns:px=
"http://www.daisy.org/ns/pipeline/xproc" xmlns:cx=
"http://xmlcalabash.com/ns/extensions" xmlns:xs=
"http://www.w3.org/2001/XMLSchema" xmlns:d=
"http://www.daisy.org/ns/pipeline/data" xmlns:dtb=
"http://www.daisy.org/z3986/2005/dtbook/" xmlns:math=
"http://www.w3.org/1998/Math/MathML" xmlns:ssml=
"http://www.w3.org/2001/10/synthesis" xmlns:tts=
"http://www.daisy.org/ns/pipeline/tts" version=
"1.0" type=
"px:tts-for-dtbook" name=
"main" exclude-inline-prefixes=
"#all">
<
p:documentation xmlns=
"http://www.w3.org/1999/xhtml">
<
p>Enriches a DTBook document with break detection and generates audio clips with TTS.</
p>
</
p:documentation>
<
p:input port=
"source.fileset" primary=
"true">
<
p:documentation xmlns=
"http://www.w3.org/1999/xhtml">
<
p>The source fileset with DTBook documents, lexicons and CSS style sheets.</
p>
</
p:documentation>
</
p:input>
<
p:input port=
"source.in-memory" sequence=
"true"/>
<
p:input port=
"config">
<
p:documentation xmlns=
"http://www.w3.org/1999/xhtml">
<
p>Configuration file with voice mappings, PLS lexicons and annotations.</
p>
</
p:documentation>
</
p:input>
<
p:output port=
"audio-map">
<
p:pipe step=
"synthesize" port=
"audio-map"/>
<
p:documentation xmlns=
"http://www.w3.org/1999/xhtml">
<
p>List of audio clips mapped to fragments in the DTBook document set.</
p>
</
p:documentation>
</
p:output>
<
p:output port=
"result.fileset" primary=
"true"/>
<
p:output port=
"result.in-memory" sequence=
"true">
<
p:pipe step=
"update-fileset" port=
"result.in-memory"/>
<
p:documentation xmlns=
"http://www.w3.org/1999/xhtml">
<
p>The result fileset.</
p>
<
p>DTBook documents are enriched with IDs, words and sentences. Inlined aural CSS is
removed.</
p>
</
p:documentation>
</
p:output>
<
p:output port=
"status">
<
p:pipe step=
"synthesize" port=
"status"/>
</
p:output>
<
p:option name=
"include-log" select=
"'false'">
<
p:documentation xmlns=
"http://www.w3.org/1999/xhtml">
<
p>Whether or not to make the TTS log available on the "log" port.</
p>
</
p:documentation>
</
p:option>
<
p:output port=
"log" sequence=
"true">
<
p:pipe step=
"synthesize" port=
"log"/>
</
p:output>
<
p:option name=
"audio" required=
"false" cx:type=
"xs:boolean" select=
"'true'" cx:as=
"xs:string">
<
p:documentation xmlns=
"http://www.w3.org/1999/xhtml">
<
h2>Enable Text-To-Speech</
h2>
<
p>Whether to use a speech synthesizer to produce audio files.</
p>
</
p:documentation>
</
p:option>
<
p:option name=
"audio-file-type" select=
"'audio/mpeg'">
<
p:documentation xmlns=
"http://www.w3.org/1999/xhtml">
<
p>The desired file type of the generated audio files, specified as a MIME type.</
p>
<
p>Examples:</
p>
<
ul>
<
li>"audio/mpeg"</
li>
<
li>"audio/x-wav"</
li>
</
ul>
</
p:documentation>
</
p:option>
<
p:option name=
"process-css" required=
"false" select=
"'true'" cx:as=
"xs:string">
<
p:documentation xmlns=
"http://www.w3.org/1999/xhtml">
<
p>Set to false to bypass aural CSS processing.</
p>
</
p:documentation>
</
p:option>
<
p:option name=
"stylesheet" select=
"''">
<
p:documentation xmlns=
"http://www.w3.org/1999/xhtml">
<
p>CSS style sheets as space separated list of absolute URIs.</
p>
</
p:documentation>
</
p:option>
<
p:option name=
"stylesheet-parameters" cx:as=
"xs:string*" select=
"'()'">
<
p:documentation xmlns=
"http://www.w3.org/1999/xhtml">
<
p>Parameters that are passed to SCSS style sheets.</
p>
</
p:documentation>
</
p:option>
<
p:option name=
"lexicon" cx:as=
"xs:anyURI*" select=
"()">
<
p:documentation xmlns=
"http://www.w3.org/1999/xhtml">
<
p>PLS lexicons as list of absolute URIs.</
p>
</
p:documentation>
</
p:option>
<
p:option name=
"word-detection" required=
"false" select=
"'true'" cx:as=
"xs:string">
<
p:documentation xmlns=
"http://www.w3.org/1999/xhtml">
<
p>Whether to detect and mark up words with <
code><w></
code> tags.</
p>
</
p:documentation>
</
p:option>
<
p:option name=
"temp-dir" select=
"''">
<
p:documentation xmlns=
"http://www.w3.org/1999/xhtml">
<
p>Empty directory dedicated to this conversion. May be left empty in which case a temporary
directory will be automatically created.</
p>
</
p:documentation>
</
p:option>
<
p:import href=
"dtbook-to-ssml.xpl">
<
p:documentation>
px:dtbook-to-ssml
</
p:documentation>
</
p:import>
<
p:import href=
"http://www.daisy.org/pipeline/modules/dtbook-utils/library.xpl">
<
p:documentation>
px:dtbook-break-detect
px:dtbook-unwrap-words
</
p:documentation>
</
p:import>
<
p:import href=
"http://www.daisy.org/pipeline/modules/tts-common/library.xpl">
<
p:documentation>
px:ssml-to-audio
px:isolate-skippable
</
p:documentation>
</
p:import>
<
p:import href=
"http://www.daisy.org/pipeline/modules/css-utils/library.xpl">
<
p:documentation>
px:css-speech-cascade
px:css-speech-clean
</
p:documentation>
</
p:import>
<
p:import href=
"http://www.daisy.org/pipeline/modules/fileset-utils/library.xpl">
<
p:documentation>
px:fileset-load
px:fileset-update
</
p:documentation>
</
p:import>
<
p:import href=
"http://www.daisy.org/pipeline/modules/common-utils/library.xpl">
<
p:documentation>
px:add-ids
</
p:documentation>
</
p:import>
<
p:choose name=
"process-css" px:progress=
"1/10">
<
p:when test=
"$audio='true' and $process-css='true'">
<
p:output port=
"fileset" primary=
"true"/>
<
p:output port=
"in-memory" sequence=
"true">
<
p:pipe step=
"cascade" port=
"result.in-memory"/>
</
p:output>
<
px:css-speech-cascade include-user-agent-stylesheet=
"true" content-type=
"application/x-dtbook+xml" name=
"cascade">
<
p:input port=
"source.in-memory">
<
p:pipe step=
"main" port=
"source.in-memory"/>
</
p:input>
<
p:with-option name=
"user-stylesheet" select=
"$stylesheet"/>
<
p:with-option name=
"parameters" select=
"$stylesheet-parameters"/>
</
px:css-speech-cascade>
</
p:when>
<
p:otherwise>
<
p:output port=
"fileset" primary=
"true"/>
<
p:output port=
"in-memory" sequence=
"true">
<
p:pipe step=
"main" port=
"source.in-memory"/>
</
p:output>
<
p:identity/>
</
p:otherwise>
</
p:choose>
<
px:fileset-load media-types=
"application/x-dtbook+xml" name=
"dtbook">
<
p:input port=
"in-memory">
<
p:pipe step=
"process-css" port=
"in-memory"/>
</
p:input>
</
px:fileset-load>
<
p:choose name=
"synthesize" px:progress=
"9/10">
<
p:when test=
"$audio = 'false'">
<
p:xpath-context>
<
p:empty/>
</
p:xpath-context>
<
p:output port=
"dtbook" primary=
"true" sequence=
"true"/>
<
p:output port=
"audio-map">
<
p:inline>
<
d:audio-clips/>
</
p:inline>
</
p:output>
<
p:output port=
"status">
<
p:inline>
<
d:status result=
"ok"/>
</
p:inline>
</
p:output>
<
p:output port=
"log" sequence=
"true">
<
p:empty/>
</
p:output>
<
p:for-each px:progress=
"1">
<
px:dtbook-break-detect name=
"break" px:progress=
"1/3"/>
<
px:isolate-skippable match=
"dtb:pagenum|dtb:noteref|dtb:annoref|dtb:linenum|math:math" px:progress=
"1/3">
<
p:input port=
"sentence-ids">
<
p:pipe step=
"break" port=
"sentence-ids"/>
</
p:input>
</
px:isolate-skippable>
<
p:choose px:progress=
"1/3">
<
p:when test=
"$word-detection='false'">
<
px:dtbook-unwrap-words px:progress=
"1"/>
</
p:when>
<
p:otherwise>
<
p:identity/>
</
p:otherwise>
</
p:choose>
</
p:for-each>
</
p:when>
<
p:otherwise>
<
p:output port=
"dtbook" primary=
"true" sequence=
"true">
<
p:pipe step=
"for-each" port=
"dtbook"/>
</
p:output>
<
p:output port=
"audio-map">
<
p:pipe step=
"to-audio" port=
"result"/>
</
p:output>
<
p:output port=
"status">
<
p:pipe step=
"to-audio" port=
"status"/>
</
p:output>
<
p:output port=
"log" sequence=
"true">
<
p:pipe step=
"to-audio" port=
"log"/>
</
p:output>
<
p:for-each name=
"for-each" px:progress=
"0.2">
<
p:output port=
"ssml" primary=
"true" sequence=
"true">
<
p:pipe step=
"ssml" port=
"result"/>
</
p:output>
<
p:output port=
"dtbook">
<
p:pipe step=
"clean-dtbook" port=
"result"/>
</
p:output>
<
p:group>
<
p:documentation>
Insert "speech-only" spans from @tts:before and @tts:after attributes
</
p:documentation>
<
p:insert match=
"*[@tts:before]" position=
"first-child">
<
p:input port=
"insertion">
<
p:inline><
tts:before>[CONTENT]</
tts:before></
p:inline>
</
p:input>
</
p:insert>
<
p:string-replace match=
"tts:before/text()" replace=
"parent::*/parent::*/@tts:before"/>
<
p:insert match=
"*[@tts:after]" position=
"last-child">
<
p:input port=
"insertion">
<
p:inline><
tts:after>[CONTENT]</
tts:after></
p:inline>
</
p:input>
</
p:insert>
<
p:string-replace match=
"tts:after/text()" replace=
"parent::*/parent::*/@tts:after"/>
<
p:add-attribute match=
"tts:before|tts:after" attribute-name=
"tts:speech-only" attribute-value=
""/>
<
p:rename match=
"tts:before|tts:after" new-name=
"span" new-namespace=
"http://www.daisy.org/z3986/2005/dtbook/"/>
</
p:group>
<
px:dtbook-break-detect name=
"break" px:progress=
"1/5"/>
<
px:isolate-skippable name=
"isolate-skippable" match=
"dtb:pagenum|dtb:noteref|dtb:annoref|dtb:linenum|math:math" px:progress=
"1/5">
<
p:input port=
"sentence-ids">
<
p:pipe step=
"break" port=
"sentence-ids"/>
</
p:input>
</
px:isolate-skippable>
<
px:dtbook-to-ssml px:message=
"SSML generation for DTBook" px:progress=
"1/5">
<
p:input port=
"sentence-ids">
<
p:pipe step=
"break" port=
"sentence-ids"/>
</
p:input>
<
p:input port=
"skippable-ids">
<
p:pipe step=
"isolate-skippable" port=
"skippable-ids"/>
</
p:input>
<
p:input port=
"fileset.in">
<
p:pipe step=
"process-css" port=
"fileset"/>
</
p:input>
<
p:input port=
"config">
<
p:pipe port=
"config" step=
"main"/>
</
p:input>
<
p:with-option name=
"user-lexicons" select=
"$lexicon"/>
</
px:dtbook-to-ssml>
<
px:add-ids match=
"ssml:s" name=
"ssml">
<
p:documentation>px:ssml-to-audio requires that all sentences have an id attribute</
p:documentation>
</
px:add-ids>
<
p:sink/>
<
p:group px:progress=
"1/5">
<
p:documentation>
Unwrap elements with @tts:speech-only attribute and remove text content.
</
p:documentation>
<
p:delete match=
"*[@tts:speech-only]//text()">
<
p:input port=
"source">
<
p:pipe step=
"isolate-skippable" port=
"result"/>
</
p:input>
</
p:delete>
<
p:unwrap match=
"*[@tts:speech-only][not(@id)]"/>
<
p:documentation>Remove @tts:* attributes and tts namespace nodes</
p:documentation>
<
px:css-speech-clean px:progress=
"1"/>
</
p:group>
<
p:choose px:progress=
"1/5">
<
p:when test=
"$word-detection='false'">
<
px:dtbook-unwrap-words px:progress=
"1"/>
</
p:when>
<
p:otherwise>
<
p:identity/>
</
p:otherwise>
</
p:choose>
<
p:identity name=
"clean-dtbook"/>
<
p:sink/>
</
p:for-each>
<
px:ssml-to-audio name=
"to-audio" px:progress=
"0.8">
<
p:with-option name=
"audio-file-type" select=
"$audio-file-type">
<
p:empty/>
</
p:with-option>
<
p:with-option name=
"include-log" select=
"$include-log">
<
p:empty/>
</
p:with-option>
<
p:input port=
"config">
<
p:pipe port=
"config" step=
"main"/>
</
p:input>
<
p:with-option name=
"temp-dir" select=
"if ($temp-dir!='') then concat($temp-dir,'audio/') else ''">
<
p:empty/>
</
p:with-option>
</
px:ssml-to-audio>
</
p:otherwise>
</
p:choose>
<
p:sink/>
<
px:fileset-update name=
"update-fileset">
<
p:input port=
"source.fileset">
<
p:pipe step=
"process-css" port=
"fileset"/>
</
p:input>
<
p:input port=
"source.in-memory">
<
p:pipe step=
"process-css" port=
"in-memory"/>
</
p:input>
<
p:input port=
"update.fileset">
<
p:pipe step=
"dtbook" port=
"result.fileset"/>
</
p:input>
<
p:input port=
"update.in-memory">
<
p:pipe step=
"synthesize" port=
"dtbook"/>
</
p:input>
</
px:fileset-update>
</
p:declare-step>