7
Nov
by Chris
Here is a translet that will transform Timed Text (TT) Authoring Format 1.0 to Microsoft Synchronized Accessible Media Interchange (SAMI). This one is quite simple. All text is the same colour. Not much different from SRT format really.
function T-TtafToSmi{ param ($inxml) BEGIN { . pslib:\xml\invoke-transform.ps1 [xml]$xslt = @' <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:t="http://www.w3.org/2006/10/ttaf1"
xmlns="http://www.w3.org/2006/10/ttaf1"
xmlns:ttp="http://www.w3.org/2006/10/ttaf1#parameter"
xmlns:tts="http://www.w3.org/2006/10/ttaf1#style"
xmlns:ttm="http://www.w3.org/2006/10/ttaf1#metadata"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:cjb="http://www.bayes.co.uk/script"
version="1.0"
exclude-result-prefixes="#default t ttp tts ttm msxsl cjb">
<xsl:output encoding="utf-8" indent="yes" method="xml" omit-xml-declaration="yes" />
<msxsl:script language="C#" implements-prefix="cjb">
public string getMilliseconds(string time)
{
return (string.IsNullOrEmpty(time) ? "" : TimeSpan.Parse(time).TotalMilliseconds.ToString());
}
public string hyphenate(string str){
Text.StringBuilder sb = new Text.StringBuilder("", 100);
foreach (char c in str){
if (char.IsUpper(c)){sb.Append("-");sb.Append(char.ToLower(c));}
else{sb.Append(c);}}
return sb.ToString();
}
</msxsl:script>
<xsl:variable name="default-style">
<xsl:for-each select="/t:tt/t:head/t:styling/t:style[last()]">
<xsl:sort order="ascending" select="count(@tts:*)" />
<xsl:value-of select="@id" />
</xsl:for-each>
</xsl:variable>
<xsl:variable name="default-class">
<xsl:value-of select="/t:tt/@xml:lang" />cc
</xsl:variable>
<xsl:template match="t:tt">
<SAMI>
<HEAD>
<TITLE>
<xsl:value-of select="/t:tt/t:head/t:metadata/ttm:title" />
</TITLE>
<xsl:comment>
Copyright <xsl:value-of select="/t:tt/t:head/t:metadata/ttm:copyright" />
</xsl:comment>
<xsl:copy-of select="/t:tt/t:head/comment()" />
<STYLE>
<xsl:comment>
.<xsl:value-of select="$default-class" /> {
text-align: center;
font-family: arial, sans-serif;
font-weight: normal;
color: white;
font-size: 16pt;
Name: <xsl:value-of select="/t:tt/@xml:lang" /> Subtitles;
lang: <xsl:value-of select="/t:tt/@xml:lang" />;
SAMI_Type: CC;
/* anything below will override above */
<xsl:apply-templates select="/t:tt/t:head/t:styling/t:style[@id=$default-style]/@tts:*" />
}
</xsl:comment>
</STYLE>
</HEAD>
<xsl:apply-templates select="/t:tt/t:body" />
</SAMI>
</xsl:template>
<xsl:template match="t:body">
<BODY>
<xsl:apply-templates />
</BODY>
</xsl:template>
<xsl:template match="t:body/t:div">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="t:p">
<xsl:variable name="start" select="cjb:getMilliseconds(string(@begin))" />
<xsl:variable name="end" select="cjb:getMilliseconds(string(@end))" />
<xsl:variable name="following-start" select="cjb:getMilliseconds(string(following-sibling::t:p/@begin))" />
<Sync START="{$start}">
<p class="{$default-class}">
<xsl:if test="@style">
<xsl:attribute name="class">
<xsl:value-of select="$default-class" />
</xsl:attribute>
</xsl:if>
<div>
<xsl:if test="@style=$default-style and @tts:*">
<xsl:attribute name="style">
<xsl:apply-templates select="@tts:*" />
</xsl:attribute>
</xsl:if>
<xsl:if test="@style!=$default-style">
<xsl:attribute name="style">
<xsl:apply-templates select="/t:tt/t:head/t:styling/t:style[@id=current()/@style]/@tts:*|@tts:*" />
</xsl:attribute>
</xsl:if>
<xsl:apply-templates />
</div>
</p>
</Sync>
<xsl:if test="$end < ($following-start - 10)">
<xsl:text>
</xsl:text>
<Sync START="{$end}">
<p>
<nonbreakingspace />
</p>
</Sync>
</xsl:if>
</xsl:template>
<xsl:template match="@tts:*">
<xsl:value-of select="cjb:hyphenate(local-name())" />:<xsl:value-of select="." />;
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name(.)}">
<xsl:if test="@tts:*">
<xsl:attribute name="style">
<xsl:apply-templates select="@tts:*" />
</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="@*[namespace-uri()!='http://www.w3.org/2006/10/ttaf1#style']" />
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="text()">
<xsl:copy />
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
'@ } PROCESS{ if ($_ -is [xml]){ $result = (invoke-transform -inxml $_ -inxsl $xslt) $result = $result.replace(" xmlns=`"http://www.w3.org/2006/10/ttaf1`"", "") $result = $result.replace("<nonbreakingspace />", " ") $result } } END{ if ($inxml -is [xml]){ $result = (invoke-transform -inxml $inxml -inxsl $xslt) $result = $result.replace(" xmlns=`"http://www.w3.org/2006/10/ttaf1`"", "") $result = $result.replace("<nonbreakingspace />", " ") $result } }} The replaces on the $result string look like a bit of a hack but they do need to be there.
It can be used like this
PS> . .\T-TtafToSmiM1.ps1 # dot source this file
PS> T-TtafToSmi [xml](gc ttaf.xml) | sc -encoding ascii
or
PS> . .\T-TtafToSmiM1.ps1 # dot source this file
PS> [xml](gc .\ttaf.xml) | T-TtafToSmi | sc -encoding ascii
Here is the code
T-TtafToSmiM1.zip (2.39 kb)
