JSTV suite 0.1 BETA

The internet player

JSTV is not your classic video player. In fact, JSTV is an internet player: instead of a stream of images, JSTV plays a sequence of scenes rendered by Javascript code/CSS3 animations defined in a channel contents JSON descriptor.

Yeah, right: since the scenes are DHTML, your video is smaller in size, can have HTML5/vector quality graphics, can be interactive, can embed what you want, can use any JS framework, can show realtime data and can be built by your server without any particular transcoding phase.

Not enough? JSTV can be used together with its brother JSTVC: starting from a channel definition JSON which describes how your TV shows have to work, it merges multiple data feeds and generates a working channel contents file for JSTV - everything client side.

Your favourite feeds aren't served by yourself? No problem. Aggro is a simple PHP server that gently aggregates your JSTVC served feeds without any background process. It is bundled with the other two guys.

Confused? Gamecora TV is a neverending TV channel about videogames powered by the entire suite. Wondering how it works? Just download the sources and use your nerdy superpowers. All of this is Open Sourced.

Nobody in the middle.

Everything started after me, KesieV, and my girlfriend Bianca, both passionate gamers, read this pretty famous post on NeoGAF about the role of Nintendo Direct in gaming journalism.

That article, despite its focus is on gaming, depicts an idea I've always had about internet: it has the capabilities to give information from the original source but this practice is not as common as it should. Having first hand information is crucial for making your own opinion about facts instead of making your own opinion about opinions: you'll discover what's right, wrong, fair and unfair by yourself.

Keeping this idea in mind, we started the opensourced project JSTV that, thanks to some code and magic, can aggregate information from various sources and show them in video/reel form, that sometime looks like a train station display or a thematic TV channel, mainly picking the idea of Nintendo Direct and extending that to any topic and source.

Infrastructure.

While its scheme is quite a knot of arrows, the JSTV infrastructure is nothing exotic.

Download this scheme as PDF here.

How to use

Add these two lines in your page header:

<head>
  <script type="text/javascript" src="jstv/jstvt.js"></script>
  <script type="text/javascript" src="jstv/jstv.js"></script>
</head>

Make a DIV object as placeholder for your player, give it the right size and an ID...

<body>
  <div id="yourplayerid" style="width:640px;height:390px"></div>
</body>

...and, when the page is loaded, embed your video like this:

window.onload=function() { JSTV.embed( "yourplayerid", Your channel contents descriptor, [onload callback])}

The channel contents descriptor can be specified inline as a Javascript object or loaded externally as a file. The onload callback function is optional and is triggered when the player is ready for playing.

During the onload callback the player can be queried for different data:

If you're going to specify a channel structure descriptor, and then you're going to use the JSTVC/Aggro combo for making merging data with programs client-side in order to make your channel, you have to load one more Javascript file...

<head>
  <script type="text/javascript" src="jstv/jstvt.js"></script>
  <script type="text/javascript" src="jstv/jstv.js"></script>
  <script type="text/javascript" src="jstv/jstc.js"></script>
</head>

...and specify a channel structure descriptor instead of a channel contents descriptor but in the same way: defined inline or as a filename.

The channels contents descriptor

If you're going to produce your scene sequences by yourself, you just need a channel contents descriptor and JSTV player. The channel contents descriptor contains metadata of your channel, such like its name and description and the scene sequence to be played. Since it can be directly passed to the JSTV.embed command or loaded from a file, it can be statically defined in your Javascript, procedurally generated client-side by a Javascript function, statically saved on a file or dynamically generated by your server. (no particular flavour of server is required).

Your channel contents descriptors have to be structured in this way:

{
  "name": "Gamecora TV",
  "description": "Gaming info from their sources. Nobody in the middle.",
  "logo": "GTV",
You can define your channel name and description here. They will be shown in channel schedule, that's available for rendering when your channel is loaded by JSTV. The logo is ever shown on the lower right of the screen during video playback.
Notice that it can be hidden by the browser when embedding external objects, like Flash video players)
  "width": 640,
  "height": 390,
The native size of your video, that is the size of each scene layer in which jour Javascript/CSS renderer will work. JSTV will proportionally stretch the video when embedded on the page or in fullscreen mode via HTML5 transformations, so vector graphics and native DOM object will zoom without quality loss.
  "path": "gamecora/",
Any of the resources referenced with relative paths in this file will be searched from this root path (except for absolute links). If not specified, the descriptor path will be used. If the descriptor path is not available, the current page path is used.
  "poster": "poster.png",
  "posterButton": "posterbutton.png",
As classic video players, JSTV supports a trasparent poster image and an opaque play button to be shown when idle. If not specified, a black background is used.
  "sources": [
You can specify here the sources from which the channel information were picked up. While is optional here, we always suggest to cite sources whenever is needed. This information will be shown into the channel schedule.
    {
      "url": "http://gdata.youtube.com/feeds/base/users/gearboxsoftware/uploads?alt=rss&v=2",
      "tag": [ "gearbox",;"studio","america","generic" ],
      "description": "Official Youtube Channel of Gearbox",
      "about": "http://www.gearboxsoftware.com/about",
      "notes": "Borderlands series"
    },
    {
      "url": "https://www.facebook.com/feeds/page.php?id=298652701947&format=rss20",
      "tag": [ "gearbox", "thirdparty", "studio", "america", "generic" ],
      "description": "Official Facebook Page of Gearbox"
      "about": "http://www.gearboxsoftware.com/about",
      "notes": "Borderlands series"
    }, ...
Each source has an url pointing to the original source, a set of tag that classifies the news feed, a description field and two optional about and notes fields to link the about page of the original source and some textual notes about. You can specify multiple sources for your channel.
If you need some in-depth explanation about the sources descriptor, have a look to the sources descriptor section for more details.
  ],
  "sourcesAvailable": 553,
You can specify the number of feeds that your channel uses. While only the specified subset was used for making your channel, the total amount of information sources is described by this number. It is just displayed in the channel schedule.
  "scenes": [
A JSTV video is mainly a sequence of Javascript/CSS rendered scenes. This sequence is descripted by this array.
    {
      "resources": [
        {
          "type": "stylesheet",
          "url": "programs/independentsday/stylesheet.programindependentsday.css"
        },
        {
          "type": "stylesheet",
          "url": "programs/independentsday/font/stylesheet.fontindependentsday.css"
        }
      ],
      "musicIntro": {
        "name": "intro",
        "files": {
          "audio/mp3": "music.mp3",
          "audio/ogg": "music.ogg"
        }
      },
      "renderer": "simpleintro",
      "type": "programintro program-independentsday",
      "program": "Independents Day",
      "description": "Random gaming news from independent studios",
      "logo": "programs/independentsday/logo.png"
    },
    {
      "renderer": "youtube",
      "tag": [ "feed-video", "gearboxsoftware", "type-video", ;"gearbox", "thirdparty", "studio", "america", "generic" ],
      "title": "Borderlands 2 - Sir Hammerlock's Big Game Hunt Launch Trailer",
      "videoId": "2mSRW_Yscb8",
      "link": [
        "http://www.youtube.com/watch?v=2mSRW_Yscb8&feature=youtube_gdata"
      ]
    }, ...
Each scene is composed by:
  • some resources: (optional) it is an array that lists a series of external files needed for rendering this particular scene. type can be stylesheet or javascript and the related source address is described by the url attribute. It can be both an absolute or relative address. If a resource is referred multiple times is loaded just once. Since CSS file onload event is not available, a timer is used. It's possible to check when your stylesheet was loaded with best accuracy naming your files yourcssname.youruniquefilekey.css and adding a .onload-youruniquefilekey { z-index: 123321; } line on the bottom.
  • a renderer: it describes the Javascript and CSS files needed for shaping this specific scene. It will load a pair of files located at [JSTV path]/renderers/[renderer name].js and [JSTV path]/renderers/[renderer name].css. The Javascript must be structured as JSTV scene renderers: documentation about JSTV renderers is within the sample renderers code.
The other keys will be passed to the specified renderer as arguments in order to render your scene so its syntax may vary. You can find each renderer documentation within their code. You can use the same renderer for multiple scenes: it will be loaded just once and called with different arguments.
Channel schedule is generated by renderers too, starting from the scene data and most of them uses the tag, title or program keys.
  ],
  "programs": [
Scenes have to be indicized by the programs section, which mainly lists from which scene each program starts.
    {
      "title": "Independents Day",
      "description": "Random gaming news from independent studios",
      "startAt": 0
    },
    {
      "title": "Turtle Island",
      "description": "Random news from American Studios",
      "startAt": 15
    }, ...
Each program is defined by its title, description and an index to the scenes structure from which the program starts. These data are used for building the channel schedule and can be selectable in order to jump from a particular scene of your sequence.
  ]
}

The channels structure descriptor

If you want to generate your scenes sequence client side starting from a particular dataset, you can use JSTVC/Aggro together with JSTV. JSTVC channel structure descriptor is quite similar to the JSTV channel contents descriptor - the main difference is that you're going to define how your programs are going to be composed instead of directly defining its scenes.

Client side channel definition is as fun as experimental: while it doesn't ensure the same resulting scene sequence on all of the clients, it removes the need of server side batch-production of the scene sequence distributing the data parsing process to all the clients and making them updating just the needed sources on-demand, reducing remarkably your server-to-server data transfer, since a full update of cached data will just be a worst case that can be handled without a running daemon - That's the Aggro job, which will avoid this, checking the creation date of each file before running an update.

Channel structure descriptor are directly passed to JSTV as for channel contents descriptor but it has to be structured in this way:

{
  "name": "Gamecora TV",
  "description": "Gaming info from their sources. Nobody in the middle.",
  "logo": "GTV",
  "width": 640,
  "height": 390,
  "path": "gamecora/",
  "poster": "poster.png",
  "posterButton": "posterbutton.png",
These channels metadata are the same of the channel contents descriptor: the channel name, its description, the textual logo, the screen width and height, the resources relative path and the channel poster are defined here.
  "sources": "sources/all.json",
Unlike for the channel contents descriptor, the sources section is mandatory here. It will be used as list of feeds from which the data will be picked. It can be an inline list like for the channel contents descriptor or an external file.
There are some differences between channel contents descriptor version of sources and this one - please, have a look to the sources descriptor section for more details.
  "sourcesProcessor": {
    "shuffle": true,
    "count": 50,
    "tag": [ "gearbox" ]
  },
After the feeds database specified into the previous sources is loaded, a subset of them can be selected from the whole bunch before starting downloading and parsing them.
It's possible to shuffle the feeds list, in order to randomize feed distribution in your programs, pick a subset of the sources database with a specified count or filter them by tag.
The sourcesProcessor key is not mandatory, like all of its subkeys.
Notice that the random seed of feeds shuffle is based on the current UTC date and hour that ensures that, in the same hour, all of your users are watching the same data sources.
  "materialProcessor": {
    "shuffle": true
  },
When the feeds are selected and downloaded, JTVC starts crawling data for contents, producing more data items. Once extracted and listed, they can be shuffled in order to mix feeds contents before creating programs. Notice that this way of shuffling is different from the one of sourcesProcessor since the first one shuffles feeds but keeps feed data in their original order when distributed in channels.
  "programProcessor": {
    "shuffle": false
  },
Your programs can be shuffled before being filled in order to generate different sequences of shows.
  "channelIntro": [
    {
      "resources": [
        {
          "type": "stylesheet",
          "url": "programs/gamecora/stylesheet.programgamecora.css"
        },
        {
          "type": "stylesheet",
          "url": "programs/gamecora/font/stylesheet.fontgamecora.css"
        }
      ],
      "renderer": "simpleintro",
      "type": "programintro program-gamecora",
      "text1": "Game",
      "text2": "Cora",
      "text3": "TV",
      "title": "Gamecora TV",
      "description": "Gaming info from their sources. Nobody in the middle."
    }
  ],
The channel intro list is a sequence of scenes described like in the scenes key of the channel contents descriptor. It will be played first before the generated programs, so you can use it for specifying a particular channel introduction.
  "programModels": [
Using a channel structure instead of a channel contents descriptor, you have to define how your programs will work instead of define statically your scenes sequence. The data items picked by the sources key will be used by JSTVC to fill them matching their tags and generating a scenes sequence.
Remember that JSTVC just converts a channel structure descriptor to a channel contents descriptor so you can store JSTVC output to a file and use it statically with JSTV only.
    {
      "title": "Independents Day",
      "description": "Random gaming news from independent studios",
First of all you have to define your program title and its description
      "times": 3,
Every program is aired multiple times until there aren't enough data items to fill it. If you want that a program episode is aired a particular number of times, you can specify the amount here.
      "scheme": [
The scheme section explains to JSTVC how your program is structured. Each element of the scheme key defines a segment of your program. Each segment can contain one or more scenes (the same we defined into the channel contents descriptor) and these scenes can be merged with one or more data items, extracted from the specified sources and with the rules defined by the sourcesProcessor.
        {
          "scene": {
            "resources": [
              {
                "type": "stylesheet",
                "url": "programs/independentsday/stylesheet.programindependentsday.css"
              },
              {
                "type": "stylesheet",
                "url": "programs/independentsday/font/stylesheet.fontindependentsday.css"
              }
            ],
            "musicIntro": {
              "pick": "randomly",
              "fromSet": "intros",
              "oneOf": [
                { "name": "intro", "files": {"audio/mp3":"music1.mp3"},{"audio/ogg":"music1.ogg"}},
                { "name": "intro", "files": {"audio/mp3":"music2.mp3"},{"audio/ogg":"music2.ogg"}},
                { "name": "intro", "files": {"audio/mp3":"music3.mp3"},{"audio/ogg":"music3.ogg"}},
                { "name": "intro", "files": {"audio/mp3":"music4.mp3"},{"audio/ogg":"music4.ogg"}}
              ]
            },
            "renderer": "simpleintro",
            "type": "programintro program-independentsday",
            "program": "Independents Day",
            "description": "Random gaming news from independent studios",
            "logo": "programs/independentsday/logo.png"
          }
        },
This is our first scene generator. A scene generator will produce a set of scenes for a segment of your program.
This first segment of the program is composed by a single scene rendered by simpleintro renderer - as you can see the scene is defined in the same way of the channel contents scene descriptor. Since the tag key is not defined, the scene generator will not merge any data items to this scene, keeping it as it is. (That's ok for us since is our program intro)
During a scene definition into a program segment you can use the {pick:"randomly"} object instead of any of the values. The pick object allows some simple logic applied on scene data values. In this case the {pick:"randomly"} object will randomly pick oneOf the specified entries and will use it as musicIntro scene value. (simpleintro renderer will play the music specified in the musicIntro key when the scene starts, so we are telling him to play a random music chosen from the oneOf set).
The fromSet key ensures that the next time we will choose a random music for another scene, the previous one will not be repeated. The fromSet key indicates a not-repeating sequence of elements, so you can specify multiple sequences using different values (in this case, we labeled the intro music sequences as intros)
Notice that you can assign multiple scene to a scene generator using an array instead of a single object, as in this example.
        {
          "tag": [ "gearbox", "type-video" ],
          "times": [ 1, 3 ],
          "allowNoItems": true,
This second segment will be generated starting from the data get from the specified sources. The scene generator will pick data items with both the gearbox and type-video tag from 1 to 3 times. That means that this segment will be added to the program only if at least one data item tagged as "gearbox" and "type-video" is available.
The entire program will not be aired if this scene hasn't enough material to be filled for its lower quota, unless you set the allowNoItem key true.
Notice that the lower quota for each program needs to be satisfied before picking more data for reaching the higher one.
          "scene": [
            {
              "renderer": "youtube",
              "tag": { "pick": "tag" },
              "title": { "pick": "title" },
              "videoId": { "pick": "video.id" },
              "link": { "pick": "link" }
            },
            {
              "renderer": "simpleintro",
              "type": "videooutro program-independentsday",
              "program": "Independents Day",
              "source": { "pick": "source" },
              "logo": "programs/independentsday/logo.png",
              "title": { "pick": "title" },
              "link": { "pick": "link" },
              "date": { "pick": "date" }
            }
          ]
        },
This is a scene generator quite like the previous one but, since we've used an array, we've defined a multiple scenes instead of a single one for this segment.
The biggest difference is given by the fact that this segment is related to some data items (remember the previous marker? We've used the tag key this time) so each scene will be copied to the program segment for every data item that was chosen. That means that if we've picked 3 type-video about gearbox data items, this set of scenes will be copied 3 times, giving 6 scenes in total for this section.
What will make each copy different to the other one? You surely noticed the {pick:"keyname"} spreaded into the scene definitions: unlike {pick:"randomly"}, the value for the specified key of each scene will not be picked randomly but picked from the selected data items instead, so title:{pick:"title"} will set the title value for the current data element to the title key of each copy of the scene data.
More information about data items keys are available to its section of this documentation.
The sequence described by this example will produce 3 pairs of scenes: the first one will be rendered by the youtube renderer (that will show a YouTube video) picking the videoId from the extracted data element (which will have the gearbox and type-video tags applied as defined into the tag key before) and the second one will be rendered by the simpleintro renderer (that will show a short animation) which will use the video {pick:"title"} as its displayed title.
Et voilà. A sequence of 3 YouTube videos with its nice outro.
          "beforeScene": {
            "musicIntro": {
              "pick": "randomly",
              "fromSet": "intros",
              "oneOf": [
                { "name": "intro", "files": {"audio/mp3":"music1.mp3"},{"audio/ogg":"music1.ogg"}},
                { "name": "intro", "files": {"audio/mp3":"music2.mp3"},{"audio/ogg":"music2.ogg"}},
                { "name": "intro", "files": {"audio/mp3":"music3.mp3"},{"audio/ogg":"music3.ogg"}},
                { "name": "intro", "files": {"audio/mp3":"music4.mp3"},{"audio/ogg":"music4.ogg"}}
              ]
            },
            "musicOutro": { "stop": true },
            "renderer": "simpleintro",
            "type": "sectionintro program-independentsday",
            "showInSchedule": 1,
            "backgroundImage": { pick": "image" },
            "program": "Independents Day",
            "title": "Cinema",
            "subtitle": "Videos",
            "image": "programs-common/sprites/video.png",
            "logo": "programs/independentsday/logo.png"
          },
Each segment can have two more scene generator other than scene: beforeScene and afterScene. They operate in the same way of scene generator - the only difference between them is the fact that the scene copies defined in the beforeScene will happen before the one defined in scene and then the afterScene will be appended at the end of the segment.
Long story short, if you need to make an intro to a particular segment of your program, put the intro scene into beforeScene. You have to put your contents into scene. Outros will be added to the afterScene.
          "afterScene": { ... }
        }, ...
      ]
    }
  ]
}

The sources descriptor

Both JSTV channel contents and JSTVC channel structure descriptor have to specify a set of sources from which your channel is built (or will be built) in their sources key. This set has to be specified inline for channel contents files - in channel structure you can also specify an external file as reference.

While this section is display-only for JSTV, it is more meaningful for JSTVC: it contains the full feeds database and will be used first by the sourcesProcessor in order to eventually pick a subset of them and then will be fetched in order to extract the data items used for filling the programs defined by the channel structure.

sourcesProcessor can decide client side a subset of feeds by its own but if you prefer a safer server side approach you can point to a server side produced sub-list in the channel structure descriptor instead of a static full database.

[
  {
    "url":"http://www.2kgames.com/news/list?format=rss",
This is your feed URL. While you have to provide a valid URL when specified in JSTV, you can use three different pseudo-url in JSTVC.
  • plain URL: http://www.2kgames.com/news/list?format=rss
    A plain url is a classic RSS feed resource URL.
  • meta URL: youtube://2KGames, facebook://197404747597 or flickr://51277380@N08
    JSTVC supports simple URL converters called metaProtocol which works replacing the specified resource location to an RSS resource template URL. The YouTube metaprotocol just converts youtube://2KGames using the http://gdata.youtube.com/feeds/base/users/**/uploads?alt=rss&v=2 template before getting its resources - so will point to http://gdata.youtube.com/feeds/base/users/YouTube/uploads?alt=rss&v=2. You can find all of the supported metaprotocols in the JSTVC configuration section.
  • Aggro URL: twitter://CAPYGAMES
    Some protocols are understood by Aggro specific bridges, like the Twitter one that's built in. Data bridges can standardize to the RSS feed JSON format used by JSTVC different sources: in this case, the CAPYGAMES Twitter user timeline will be converted by Aggro to JSON and served to JSTVC.
    Notice that Aggro URL will be available by Aggro only and ignored when the Google RSS/JSON proxy is used. More information is available at the Aggro configuration section.
Notice that, if it is not using the http or https protocols, JSTVC will show the feedUrl attribute from original RSS feed - that happens mostly for Aggro URL.
    "description":"Official News Feed of 2K Games"
This is your feed name. Just make it meaningful :)
    "queue":"rss",
While this key is ignored in a channel contents descriptor, this is mandatory in a channel structure descriptor.
JSTVC uses multiple parsing queues in order to convert feed raw data to data items, that are used for filling your programs and for converting an channel structure descriptor to a channel contents descriptor. Each feed can be routed to a different queue depending on the feed genre: RSS feeds are usually parsed by the rss queue, the flickr queue can be used for... well... Flickr and image-based feeds, the youtube queue is optimal for YouTube-rich feeds and the twitter queue is for microblogging services that provides RSS feeds - or can be proxied by Aggro.
A full list of the supported queues is available in the JSTVC configuration section.
    "tag":["2kgames","thirdparty","publisher","worldwide","pr","generic"],
In both channel contents and channel structure descriptor you have to assign a set of tags to your feeds - but it will be used in different ways. While it is used just for creating a tag cloud of your channel by JSTV, JSTVC will assign these tags to all of the data items extracted by the referred feed.
It's a convenient way to organize your feeds and ensure their assignment to one or multiple programs of your channel.
Notice that these aren't the only tags assigned to the derived data items: a number of tags is added by processing queues reading them from the original source, like per-news RSS tags, Twitter cited users and so on - these tags can be referred too in your channel structure.
    "about":"http://www.2kgames.com/#/about-2k/",
    "notes":"Bioshock series",
These attributes have the same meaning for JSTV and JSTVC:
  • about is a link to the source information page.
  • notes is a text-only descriptive text that can give some hints about the cited source - just for avoiding the classic TL;DR of about pages.
Notice that JSTVC will show the link attribute from original RSS feed if about link is not specified.
  }, ...

The data item

Data items are extracted by JSTVC from the specified sources defined into its channel structure file. Each feed passes through a processing queue defined for each feed and crawled for information.

Data items can be referenced by program segments of the channel structure descriptor via tags - the data items tags are both picked from the sources descriptor and the specific resource. You have to use the {pick:"keyname"} object in order to link scene data to data items.

{
  title: "Item title",
  content: "Original item content (tags stripped)",
  simpleContent: "Original content strippe...",
Textual data of the data item are stored here.
  • title contains the data item title. It can be a video name, a news heading etc.
  • content is a text-only version of the data item, that can be a tweet or body news, a video description etc.
  • simpleContent contains a shortened version of the content
  sourceurl: "http://source.com",
  source: "Your source description",
These are copied from original source: sourceurl is the source url and source is its description, as defined in source descriptor.
  tag: ["type-video", "tagFromSource","tagFromFeed" ...],
These tags are both picked from the tag key of the feed, applied by the processing queues and extracted from source metadata. The type-video tag is applied by the queue once is detected as suitable for video, image, news or tweet. A tweet is meant as short news - and extracted from Twitter too.
  link: "http://relatedlink.com",
This contains a specific URL if referenced by the extracted data item. For type-video usually contains the original YouTube page of the video, for type-tweet points to the related Twitter page and so on.
  video: { id: "YouTube video id"},
For type-video items you can find the video id here.
Notice that for now just YouTube videos are supported and can be referenced with the {pick:"video.id"} in your channel structure descriptor.
  image: "http://relatedImage.jpg",
While this key is quite crucial (and obvious) for type-image data items, can be valued for other types of items, like type-news and, more frequently, type-video.
  author: "Content author",
A textual reference to the original author of the data item.
  date: "13 Feb 2013"
A human readable shortened version of the publication date of the data item.
}

The JSTV configuration

JSTV is the main player. It reads a channel contents descriptor, loads its resources and starts playback. Since its limited functionality, its configuration is quite straightforward and - mostly - doesn't need any customization - user can configure the player from the menu button from the popup status bar showed, hovering or tapping on the lower part of the player.

var JSTV={
  configuration: {
    /* Project name - shown on menu screen */
    name: "JSTV",
The project name is displayed on the bottom right of the menu screen as link.
    /* Project version - shown on menu screen */
    version: "0.1b",
The project version - as string.
    /* Project URL - shown on menu screen */
    url: "http://www.kesiev.com/gamecoratv/index-jstv.html",
This link is available at the menu screen, on the bottom right, clicking on the project name.
    /* Disclaimer - is shown in every JSTV screen */
    disclaimer: "JSTV is still in beta. Video playback could be limited by your browser vendor and/or video publisher. Medias are owned by their original publisher and not endorsed with this site."
  },
A disclaimer text that's displayed both in loading screens, idle screen and menus.
  ...

The JSTVC configuration

JSTVC can fetch multiple feeds, extract data and merge them in programs, starting from a channel structure descriptor. Since it is a quite complex channel structure to channel contents descriptor converter, you don't have to use it for your channel - but you have to define your scene sequences by yourself.

JSTVC configuration is splitted in two: the reporter configuration defines the collecting phase behaviour and the finalizer configuration defines the data item merging phase. Luckly, the finalizer configuration is quite simple. :)

The reporter phase configuration:

reporter: {
  configuration: {
    /* Enables logging. Produced channels will have additional data of unused data/sources */
    logging: false,
The reporer module will fetch data sources in order to extract data items. It's possible to enable logging: it will report empty or dead sources, unused URLs and other relevant notices triggered by the extraction phase.
All of the logs will be reported into the generated channel contents descriptor under the logs key and parsed by the getStats and getStatsData of the player object.
    /* Number of feeds requested for bundle calls - only for URL managers that can handle URL bundles */
    maxBundleSize: 10, //-1 for unlimited
Aggro supports multiple feeds download in a single calls. This attribute decides how many feeds can be requested by JSTVC in a single call.
For more information about bundles, have a look to Aggro configuration section.
    /* A list of servers that can handle sources data */
    urlManagers: [
    /* Aggro histances can be used for retriving data - Remove this block if you don't want to host an Aggro server */
    {
      label: "Local Aggro Server",
      protocols: ["http", "https", "twitter"],
      contacts: {
        "bundle": "aggro/?mode=bundle&%RANDOM%",
        "ajax": "aggro/?q=%FEED%&%RANDOM%",
        "jsonp": "aggro/?q=%FEED%&v=1.0&callback=**&%RANDOM%"
      }
    },
    /* JSTVC is also compatible with the Google's feed-to-JSONP service. Can be used instead of Aggro for some protocols */
    {
      label: "Google RSS Proxy",
      protocols: ["http", "https"],
      contacts: {
        "jsonp": "http://ajax.googleapis.com/ajax/services/feed/load?&q=%FEED%&v=1.0&callback=**"
      }
    }],
JSTVC supports multiple servers and protocols during its reporting phase - each server is called URL manager. Each URL manager can be defined by:
  • label: A textual label defining the URL manager
  • protocols: A list of Aggro protocols and standard protocols supported by the specified manager
  • contacts: A list of contacting methods and URLs linked to the specified manager.
    The key can be bundle (for Aggro bundles), ajax (for single calls per feed via AJAX post calls) or jsonp (for single calls per feed via JSONP calls). Each protocol has its pros and cons: bundle works with Aggro only and can process multiple feeds at once, speeding up the downloading process, ajax is more compatible, generates less traffic and is more secure than JSONP calls but doesn't work cross-domain out-of-the-box and JSONP works well cross-domain but are less secure. Aggro supports all of them and Google RSS/JSONP service supports JSONP only.
    The value is the related URL, that can use two placeholders: %FEED% that's the feed URL JSTVC wants to download and %RANDOM% that is a random number that can be used for breaking cache.
    For each feed to download, JSTVC will pick the first URL manager that handles the current protocol. If available, it will find the best method for contacting it - starting from from bundle, then ajax and jsonp at last. If no combination of protocol/method is available, the feed is skipped.
    /* A list of meta-protocols. Will be converted to other URLs pointing standardad RSS */
    metaProtocols: {
      facebook: "https://www.facebook.com/feeds/page.php?id=**&format=rss20",
      youtube: "http://gdata.youtube.com/feeds/base/users/**/uploads?alt=rss&v=2",
      flickr: "http://api.flickr.com/services/feeds/photos_public.gne?id=**&lang=it-it&format=rss_200",
      tumblr: "http://**.tumblr.com/rss"
    },
metaProtocols are simple URL converters: if the youtube://capybaragames feed is requested, the related http://gdata.youtube.com/feeds/base/users/capybaragames/uploads?alt=rss&v=2 is downloaded instead.
Notice that you can add your own metaProtocols but remember to mirror them into the Aggro configuration in order to make them working.
    /* Used for breaking cached data */
    random: Math.floor(Math.random() * 10000)
A random number, used as value for the %RANDOM% placeholder used in urlManagers definitions.
  },
  /* Available processing queues usable for sources */
  queues: {
    tweets: ["getFeed", "parseTweets", "crawl", "finalize"],
    rss: ["getFeed", "parseNews", "crawl", "finalize"],
    youtube: ["getFeed", "parseYoutube", "uniquize", "findImage", "finalize"],
    flickr: ["getFeed", "parseNews", "labelAsImage", "findImage", "finalize"]
  },
queues are used in source descriptor in order to define which series of parsing procedures the feed has to pass for extracting its data items.
These queues are pointing to functions defined in JSTVC.reporter.fetchers.

The finalizer phase configuration:

finalizer: {
    configuration: {
      /* Enables logging. Produced channels will have additional data of unused programs/assets */
      logging: false
    },
After extracting data items from the specified feeds, JSTVC will merge them in programs during the finalizer phase.
Finalization phase can happen via HTML5 Web Workers where available, detect unused data items and check for repeated material, in order to help you filtering similar feeds in your database.
This information can be enabled via this flag: all of the logs will be reported into the generated channel contents descriptor under the logs key and parsed by the getStats and getStatsData of the player object.

The Aggro configuration

Aggro is an RSS proxy and standardizator inspired by the Google RSS/JSONP proxy. It acts as an URL Handler and features all of the protocols supported by JSTVC.

Aggro was built just for doing its work and is not meant for offering always up-to-date data - typical of RSS reader aggregators. It was designed for working in limited server configurability and low resources consumption - its story is long and sad: it was built after Google shocking decision to close Reader and Twitter decision to kill User Timeline RSS feeds, both happened during JSTV development. That's why is called Aggro - it aggregates due to rage.

Since is quite minimal, Aggro configuration is contained in his index.php file as a sequence of setters calls.

AggroVerifier::setCheckReferrer(false); // Check referrer at start
Aggro can check referrer before answering to calls. It will check if referrer domain and local are matching.
AggroOut::setGZip(true); // Enables/disables GZIP compression of any output.
AggroOut::setGZipThreshold(2048); // Don't compress data smaller than this threshold
Aggro answers can be gZipped when client is supporting them. GZip can be enabled depending on the answer size, in order to avoid meaningless compressions.
AggroCache::setCachePath("cache/"); // Cache folder
AggroCache::setSalt("aggrocache"); // URL hashes used for caching will be salted with this string
AggroCache::setUserAgent("Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6"); // Downloader user agent
AggroCache::setPersistentCache(false); // Never refresh the cached data
AggroCache::setCacheLife(60*60*24); // Life of cached data
AggroCache::setDownloadedItemsLimitPerSession(3); // Maximum number of external calls for session. -1 for no limit, 0 for no downloads
AggroCache::setSessionDuration(60*60); // Duration of a user download session.
Most of the files handled by Aggro are cached into the setCachePath defined directory.
Resources are referenced via hashes that can be salted with the setSalt value avoiding direct linking.
AggroCache can also download files in cache directly, defining a user agent in order to get the right answers. setUserAgent can change it.
Resources in cache can expire, checking their last modified date. If you want to disable this behaviour, setPersistentCache to true.
A resource is considered expired when is setCacheLife seconds old. An expired resource will be updated the next time is requested.
It's possible to limit the number of resources updated by each user with setDownloadedItemsLimitPerSession. Users are verified via PHP session.
Downloadable items are resetted when the session expires. It's also possible to reduce session life with setSessionDuration.
AggroRSS::setEntryCount(4); // Number of extracted entries
RSS feeds are downloaded and cache by Aggro depending on AggroCache settings. Once downloaded, it's possible to send to JSTV clients a limited amount of items via setEntryCount.
AggroTwitter::setEntryCount(4); // Number of extracted entries
In the same way of RSS, Twitter timelines can be limited to a defined amount of posts via setEntryCount
// Comment these lines in order to disable Twitter support
AggroTwitter::setOAuthAccessToken("123456789-a1b2c3d4e5a1b2c3d4e5a1b2c3d4e5a1b2c3d4e5");
AggroTwitter::setOAuthAccessTokenSecret("a1b2c3d4e5a1b2c3d4e5a1b2c3d4e5a1b2c3d4e5");
AggroTwitter::setConsumerKey("a1b2c3d4e5a1b2c3d4e5a1b2c3d4e5a1b2c3d4e5");
AggroTwitter::setConsumerSecret("a1b2c3d4e5a1b2c3d4e5a1b2c3d4e5a1b2c3d4e5");
In order to make Twitter proxy to work, you have to get your personal OAuthAccessToken, OAuthAccessTokenSecret, ConsumerKey and ConsumerSecret from Twitter.
AggroJSTV::setVerifySources(true); // Check the sources listed into the specified sources path
AggroJSTV::addSourcesPath("../../gamecora/sources/"); // Folder with authorized feeds (JSON)
AggroJSTV::setMaxBundleSize(15); // Maximum items per bundle (-1 for unlimited)
AggroJSTV::setMaxRequestSize(256*15); // Maximum request allowed to call JSTV - if you can't configure it from php.ini (-1 for unlimited)
Aggro can validate JSTVC requests in different ways.
It's possible to check that the requested feeds are coming from your sources descriptors and return only authorized contents - this can be enabled via setVeryfySources.
Trusted sources descriptors have to be gathered in a single folder set by addSourcesPath.
Aggro bundle support can be limited server side in size via setMaxBundleSize - just remember to set your JSTVC configuration key maxBundleSize accordingly.
It's also possible to answer to requests - both bundles and single JSON calls - that are sending a certain amount of data. Maximum threshold is both set in PHP.ini and checkable via setMaxRequestSize.
// Metaprotocols just convert URLs to standard RSS feeds, like in JSTVC.
AggroJSTV::addMetaProtocol("facebook","https://www.facebook.com/feeds/page.php?id=**&format=rss20");
AggroJSTV::addMetaProtocol("youtube","http://gdata.youtube.com/feeds/base/users/**/uploads?alt=rss&v=2");
AggroJSTV::addMetaProtocol("flickr","http://api.flickr.com/services/feeds/photos_public.gne?id=**&lang=it-it&format=rss_200");
AggroJSTV::addMetaProtocol("tumblr","http://**.tumblr.com/rss");
You have to specify the same metaprotocols you've set on JSTVC configuration in the related Aggro server too in order to correctly check their presence in your sources descriptors.
// These are real protocols and must be linked to their handlers
AggroJSTV::setProtocol("twitter","AggroTwitter");
AggroJSTV::setProtocol("http","AggroRSS");
AggroJSTV::setProtocol("https","AggroRSS");
You have to link supported protocols to Aggro parsers here. Mainly you have to specify the same protocols you've set in JSTVC configuration protocols key of the related URL handler.
// Rename these two lines to disable AggroAdmin
AggroAdmin::setUsername("admin"); // Username for admin
AggroAdmin::setPassword("1a1dc91c907325c69271ddf0c944bc72"); // md5("pass") - replace with your own!
Aggro also offers a little backend that can help you checking how your cache is going and update it manually. Just specify your Usernme and MD5 Password to enable it. If you want to play it safe, comment both and the backend will be disabled.

Download

JSTV, JSTVC and Aggro are MIT/GPL2 licensed and its code is opensource - as its demo channel Gamecora TV and its assets. Sources are available on GitHub.

Download JSTV, JSTVC, Aggro and Gamecora TV 0.1b here

Looking for original assets (full lenght musics, vectors, scripts etc.) for better contributing on Gamecora TV? Download Gamecora TV 0.1 original assets here.

Suggestions? Comments? Rage? I'm KesieV and you can contact me here (strip the numbers) or on Twitter.

Credits and Kudos

JSTV, the core of Gamecora TV was coded by me, KesieV, with the valuable help of Sublime Text, but it's quite obvious that it's just a square with some knobs without its database, intro and outro creativity, logos and site review. Well, everything that's not coding was made by Bianca, my girlfriend, with the help of Inkscape, Gimp, LibreOffice and a huge amount of effort and time. And, whenever we could work as a duo, everything should have some creepy Daffy-Duck-Style beatbox as background music without...