Shinai

Shinai is a standalone Java application that can connect Clamp with external scoring systems to provide accurate and real-time updated scores, lap or time information on your live stream in case of sports events. The diagram below shows how Shinai works conceptually:

shinai-sports-scoring

The External Scoring System's responsibility is to feed Shinai with score information. The format can vary and can be customized (e.g. )csv, xml. Shinai comes with a powerful XPath based expression system that can be set up to extract score, time, name, country, etc. information from arbitrary xml structures.

Shinai can be configured to listen for HTTP POST messages on a specified port or can be configured to watch for file changes in a specific directory on the file system, e.g. FTP dropsite. File system changes are immediately detected by an operating system level notification hook.

The input file is transformed into instructions to Clamp which are sent over via HTTP to the module installed into Wowza Streaming Engine. This allows you to run Shinai either on the same server where Wowza is running or even a remote computer.

Here is an example of an input file emitted by MyLaps scoring system:

<?xml version="1.0" encoding="utf-8" ?> 
<resultspage> 
 <label type="bestlapby">1 - Alois Helmuth</label> 
 <label type="bestlaptime">46.250</label>
 <label type="eventname">Random Rallycross Championship</label>
 <label type="flag">none</label>
 <label type="groupname">SuperCars</label>
 <label type="laps">6</label>
 <label type="lapstogo"/>
 <label type="leader">1 - Alois Helmuth</label>
 <label type="leaderavgspeed">87,941</label>
 <label type="leadermargin">0.869</label>
 <label type="racetime">6:15</label>
 <label type="runname">Final</label>
 <label type="runtype">R</label>
 <label type="timeofday">17:41:09</label>
 <label type="timetogo"/>
 <label type="tracklength">1,266</label>
 <label type="trackname">Big Bang Track</label> 
 <results>
  <!-- some irrelevant parts omitted -->

  <result position="1" no="81" fullname="Kovacs John" additional1="HUN" additional3="Ford Focus" averagespeed="87,941" averagetime="51.825" bestinlap="1" bestspeed="98,543" besttime="46.250"  lastpitstop="0" lastspeed="90,094" lasttime="50.587" lasttimeline="Start/Finish" lasttimeofday="16:57:39.410"  positioninclas ="1" regnumber="Db9adaa7" secondbestinlap="6" secondbestspeed="90,094" secondbesttime="50.587" secondlasttime="59.013" totaltime="5:10.954" transponder="404" />

<result position="2" no="42" fullname="Simon Gartner" additional1="GER" additional3="Ford Fiesta" averagespeed="89,942" averagetime="53.825" bestinlap="2" bestspeed="100,021" besttime="48.250" lastpitstop="0" lastspeed="93,094" lasttime="52.587" lasttimeline="Start/Finish" lasttimeofday="16:57:40.410"  positioninclass="1" regnumber="Db9adaa8" secondbestinlap="6" secondbestspeed="91,094" secondbesttime="51.587" secondlasttime="57.013" totaltime="5:12.954" transponder="405" />

 </results>
</resultspage>

Shinai needs to know how to transform information from this xml file into Clamp instructions that describe the style, position, content, etc. of the overlay that needs to be shown. The below template is using XPath expressions to turn the xml into Clamp instructions:

xpath('concat("1. ", //result[@position="1"]/@fullname, " #", //result[@position="1"]/@no)')={ position: {"x":50, "y":0.8, "z":1}, "style": {"font":"SansSerif","color":"white","style":"bold","size": 26}}

xpath('//result[@position="1"]/@totaltime')={ position: {"x":50, "y":0.85, "z":1}, "style": {"font":"SansSerif","color":"white","style":"bold","size": 26}}

xpath('//result[@position="1"]/@fullname')={position: {"x":30, "y":0.78, "z":0}, "image": "result-background.png"}

xpath('concat("2. ", //result[@position="2"]/@fullname, " #", //result[@position="2"]/@no)')={ position: {"x":300, "y":0.8, "z":1}, "style": {"font":"SansSerif","color":"white","style":"bold","size": 26}}

xpath('//result[@position="2"]/@totaltime')={ position: {"x":300, "y":0.85, "z":1}, "style": {"font":"SansSerif","color":"white","style":"bold","size": 26}}

xpath('//result[@position="2"]/@fullname')={position: {"x":280, "y":0.78, "z":0}, "image": "result-background.png"}

background={ "position": {"x": 0, "y": 60, "z": 0}, "image": "rally-background.png"}

Shinai evaluates each XPath expression from the template against the input XML file. The result of each expression is a piece of text which is substituted into the Clamp expression on the right hand side of the equal sign in the template file.

An example:

xpath('concat("1. ", //result[@position="1"]/@fullname, " #", //result[@position="1"]/@no)') against the above example data gives back the fullname and the racer number of the xml tag that has position attribute set to "1". These are all concatenated together with some static pieces of text, "1. " and "#" yielding:

1. Kovacs John #81

This is then added into the template as "text":

{ text: "1. Kovacs John #81", position: {"x":50, "y":0.8, "z":1}, "style": {"font":"SansSerif","color":"white","style":"bold","size": 26}}

Which is sent over to Clamp who will know where and how to display this information on the live video stream.