Getting started

Before using any of our products you need to sign up to create a Vilynx account and upload some videos to your Dashboard.
If you are already a user skip this.

  • CREATE YOUR ACCOUNT

    The first thing you need to do to get started with Vilynx Gallery is sign up for a free account: Register your account now
    Are you already a user? Sign in

  • UPLOAD YOUR VIDEOS

    Upload your videos to your Vilynx account: either automatically (MRSS) or manually from your computer or your cloud accounts.

    a. Media RSS Feed

    Using a Media RSS (MRSS) feed is the easiest way to automatically ingest and process your data.
    Go to your Vilynx Dashboard and paste the URL of your MRSS feed at "Uploads > MRSS"

    As new items are published to the MRSS feed, Vilynx will automatically extract the values in the different fields of such items. Vilynx will automatically download the video from the URL in the <media:content url> parameter, automatically creating a video preview. The <link> element's value will be used as the external video ID that the Vilynx Gallery library uses to place the video preview on the page.

    The table below lists the MRSS XML specs for all of the fields that Vilynx expects in your feed. Only the elements listed here are recognized.
    Please note that any video that appears in the feed will be ingested and therefore will be used within our recommendation or trending plugins, unless it has a dcterms:valid value which includes an end date in the past (see more info below).

    Tag Name Required Description
    <title> or <media:title> Yes Name of video asset
    <link> Yes The URL where the video can be viewed
    <media:content> Yes The URL to the video file, has to be type=video
    <description> or <summary> No Prioritizing <description> if both are present. Description of the video asset. If present, the description will be parsed and added to the videos
    <media:thumbnail> No Prioritizing the ones with isDefault="true" if several media-thumbnail urls are present. The URL of the video thumbnail.
    <media: defaultThumbnailUrl> No If several media-thumbnails urls are present, we prioritize the ones with `defaultThumbnailUrl`
    <guid> or <id> No Prioritizing <guid> if both are present. The video’s unique identifier. If present, the guid will be associated with the video in our system.
    <pubdate> or <published> No Prioritizing <pubdate> if both are present. The video’s publish date. If present, it will override the auto assigned system date.
    <dcterms:valid> No The video’s start and end dates.If present, the content will be marked as private after the end date, and will not be recommended to the user.
    <keywords> or <media:keywords> No Publisher-generated video keywords. If present, the keywords will be parsed and added to the videos
    <link rel="next"> or <atom:link rel="next"> No URL to the next set of results. If present, the 'next_page' property will be used to retrieve the next page if the feed contains too many videos to fit on a single page.
    <lastModifiedDate> or <atom:updated> or <updated> No The date and time at which the item was last updated/modified.
    <subtitle> or <media:subtitle> No The URL to the subtitles file.

    Examples:

    Basic MRSS feed

    <?xml version="1.0" encoding="UTF-8"?>
    <rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
        <channel>
            <title>Vilynx Sample MRSS Feed</title>
            <link>https://vilynx.com</link>
            <item>
                <guid>123456789</guid>
                <title>The Technology Behind a Vilynx Tag</title>
                <link>https://blog.vilynx.com/the-technology-behind-a-vilynx-tag-a7a8753aea1d</link>
                <media:content url="https://vilynx.com/sample.mp4" type="video/mp4" bitrate="764000" height="360" width="640" medium="video" duration="10" lang="en"/>
            </item>
        </channel>
    </rss>
    

    MRSS Feed with extra fields

    <?xml version="1.0" encoding="UTF-8"?>
    <rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:dcterms="http://purl.org/dc/terms/">
        <channel>
            <title>Vilynx Sample MRSS Feed</title>
            <link rel="current">https://www.vilynx.com/examples/feed</link>
            <link rel="next">https://www.vilynx.com/examples/feed?page=2</link>
            <description/>
            <item>
                <guid>123456789</guid>
                <title>The Technology Behind a Vilynx Tag</title>
                <link>https://blog.vilynx.com/the-technology-behind-a-vilynx-tag-a7a8753aea1d</link>
                <description>Tagging a video based on its contents is easy for the human brain, but can be very time consuming.</description>
                <pubDate>2017-09-06T09:57:33-04:00</pubDate>
                <keywords>Vilynx</keywords>
                <keywords>Machine Learning</keywords>
                <keywords>Deep Learning</keywords>
                <keywords>Artificial Intelligence</keywords>
                <keywords>Digital Media</keywords>
                <keywords>Brain</keywords>
                <media:category>News</media:category>
                <media:category>News/Sports</media:category>
                <media:thumbnail url="https://www.vilynx.com/sample.jpg" width="384" height="288"/>
                <media:content url="https://www.vilynx.com/sample.mp4" type="video/mp4" bitrate="764000" height="360" width="640" medium="video" duration="10" lang="en"/>
                <subtitle>https://www.vilynx.com/sample.srt</subtitle>
                <lastModifiedDate>2017-09-06T10:05:27-04:00</lastModifiedDate>
                <dcterms:valid>start=2017-09-06T14:00:00-07:00;end=2017-09-18T00:01:00-07:00;</dcterms:valid>
            </item>
        </channel>
    </rss>
    

    Do you have a Youtube Channel? Go to your Vilynx Dashboard and paste your Channel ID here:

    To find your channel_id, copy the string from your YouTube channel’s URL http://www.youtube.com/feeds/videos.xml?channel_id=XXXX

    If you need help obtaining this, please visit: http://support.google.com/youtube/answer/3250431?hl=en

    b. Upload videos manually

    You can also easily add videos to your Vilynx account manually to create a Vilynx video preview. Go to your Vilynx Dashboard and click the Import Videos button.

    • If the videos are stored on your computer click Import videos from PC and select the videos on your computer.

    Once the videos have been processed and a preview is available, you will need to assign the external video ID to each video so the Vilynx Gallery library can locate the videos on the page. Select each new video from the home page of the Vilynx Dashboard and then click Assign ID. Make sure to use the value from the href parameter in the <a> tag associated with this video or the Vilynx Gallery library will not be able to automatically discover the video on the page.

    c. Let us do the job for you

    If you want us to crawl your site and upload your videos for you, send us a message with your username and site URL:

    Do it for me!

The Vilynx Gallery

Replace your static video thumbnail with the best 5 seconds of your video using only one line of code.

Discover our brand new version of the Vilynx Gallery plugin. This new release is coded in ECMAscript 6 and comes together with a bunch of other improvements in terms of efficiency, DOM changes and smaller library size.

Create your gallery

Do you already have a user account and some videos uploaded? If you do, your videos are ready so it's time to add the Vilynx Gallery to your page, it's only one line of code! If not, read first the quick setup guide here.

In your Vilynx Dashboard, click your profile pic and choose “Get the Vilynx Code” from the dropdown. Paste the line of code in the page(s) where you want the gallery to show. You must place it at the end of the page's <body> section:

<script src="//static.vilynx.com/gallery/vpg.{{galleryVersion}}.min.js" data-publickey="youruserhash" data-redirect="true"></script>
  • publickey="youruserhash" This is your user ID.

  • redirect="true" Shows a countdown while user is hovering the video. Once the countdown is finished, the user will get redirected to the parent link.

Remember that the Vilynx Gallery plugin will automatically detect videos on the page that match an external video ID identified in the Vilynx database and replace the thumbnail with the video preview. Note that this external video ID must exactly match the value of the href parameter in the <a> tag of your web page for the Vilynx video preview to be included on the web page.

Other configuration options are available here.

Release notes

Current version

Here is a list of the changes and improvements included in this new version:

  • jQuery-less. Have you ever thought it is time to drop jQuery? In this release the Vilynx Gallery plugin doesn’t use it anymore.

  • Native Browser Support for Video. All our video previews now run natively across any browser for improved speed.

  • CSS Rendering. Improved flexibility and better browser efficiency with CSS rendering

  • Improved Video Play times! Video starts playing 3–5x faster than with previous gallery versions.

  • No External Libraries. Tired of scripts that load other libraries? the Vilynx Gallery plugin uses no external libraries.

  • Small is the new smart. Compressed, minified, condensed: the updated Vilynx Gallery plugin with ES6 support only weights 41.3kB (4x smaller than before)

  • Tap to play. In addition to autoplaying when in view, video previews can now be activated with a tap and swipe action on mobile devices

NEW REPOSITORY

This new code is beautifully packed in a repository so devops and JS ninjas can contribute and build their own solutions. This release is bundled using ES6 modules, has built-in gulp support and comes with its own server to test your code right away!
Are you interested in? Request access to our repository now by contacting us: info@vilynx.com

Usage & Options

Web page requirements

The Vilynx Gallery library looks for certain tag patterns in the web page containing the video gallery. The inner tag is always an image <img> tag and the outer tag is always an anchor <a> tag. There may also be <span>, <p> or <div> tags, though these are optional:

<a href="external_video_id">
    { <span> | <p> | <div> }
    <img />
</a>

Remember that the Vilynx Gallery library will search for the external_video_id in your uploaded video database in order to match every <a> with its video preview.


If you want to set an external_id that doesn't match your href value you can use the vilynx-id attribute. You can also use this attribute to mark your DOM objects up like this:

<a href="link_url" data-vilynx-id="your_video_external_id">
    <img />
</a>
<div class="vilynx_enabled" data-vilynx-id="your_video_external_id">
    <img />
</div>

With this attribute the Vilynx Gallery library will search for the your_ideo_external_id in your uploaded video database in order to match every <a> or <div> with its video preview.

Another option would be use a custom attribute instead of vilynx-id. When using this scheme please use idattribute configuration attribute in your Gallery definition.

<div class="vilynx_enabled" data-custom-attr-id="your_video_external_id">
    <img />
</div>

As of version 3.3.5 it's possible to use another HTML scheme that allows The Gallery to discover elements with backgroung images. This is an example:

<div class="vilynx_enabled" data-vilynx-id="your_video_external_id" style="background-image: url('img/bg01.png')">
</div>
Options

Several options can be passed through the script:

Name type default description
aggressivelazy integer (px) 200 Pixel distance between the element and the bottom of the viewport. Default value ensures the Gallery object is created before the user reaches it. A major value could be useful for faster than normal scrolling situations
allautoplay boolean false Autoplay all videos + gif fallback on iOS
audio boolean false Activates audio
audioonce boolean false Summary plays first time with audio
autoplay boolean false Show the Summary playing without user interaction
debug boolean false Print debug console logs
disablestorage boolean false If set to true, prevents the Gallery from storing any cookies on your site. Check the Cookie Storage Policies section for more information
divignore string Query selector none Ignore the element defined by the CSS selector when mousing over it
divignorelevels integer 0 Ignores all pointer events descendent from the (N+1)-th ancestor. CSS Selector
idattribute string vilynx-id Use this param in order to set the external-id in other attribute rather than href or vilynx-id
imgignore string Query selector none Ignore this images as Gallery item's reference inside anchor
nocache boolean false Prevent browser from caching summaries adding a random param to the mp4 source url
noimage boolean false Removes the original thumbnail (displays the summary right away)
nomobile boolean false Deactivates the plugin in Mobile devices
notablet boolean false Deactivates the plugin in Tablet devices
ongalleryload function none Function name to execute when the gallery loads. Check the Other analytics tools integration section
optimizely boolean false Sends optimizely events to optimizely (note: it'll use the account registered in your domain). Check the Optimizely integration section
optimizelyoff boolean false Disable Vilynx summaries but keep tracking clicks for Optimizely. Check the Optimizely integration section
publickey string none Unique id to identify your Vilynx account
redirect boolean false It shows a countdown while user is hovering the video, once the countdown is finished user get redirected to the parent link
redirecttext string Redirecting in Message shown along with the redirect countdown
sharewidget boolean false Show the social share links
smallgif boolean false Show small resolution gifs in mobile devices, default option shows big resolution gifs
socialtext string none Message attached to the social network post when sharing the video preview
taptoplay boolean false (true for tablets) When no value is set, or when it's set to false, the preview centered inside the viewport will autoplay on mobile devices. When the value is set to true, a touch and swipe action will activate the previews. Taptoplay is always set to true on tablets.

Here's an example:

<script src="//static.vilynx.com/gallery/vpg.{{galleryVersion}}.min.js" data-publickey="userhash" data-audio="true" data-redirect="true" data-divignore=".playIcon"></script>
Configuration classes

Some of the previous options can also be set only for selected elements using configuration classes. This is specially useful to customize your Gallery experience for each element or section across your site. Note that script options override this classes.

<a href="external_video_id" class="vilynx_autoplay">
    { < span > | < p > | < div > }
    <img/>
</a>
<a href="external_video_id" class="vilynx_audio">
    { < span > | < p > | < div > }
    <img/>
</a>
                        
Class description
vilynx_disable Disable this element
vilynx_autoplay Show the Summary playing without user interaction
vilynx_pauseonhover When using autoplay this option stops the Summary play when hovering
vilynx_noimage Hide the element image and show the Summary first frame instead
vilynx_audio Play Summary with audio on
vilynx_redirectwithclick Use onclick callback attached to element instead of href location

Third Party Integration

Optimizely

To add a Vilynx variation to your Optimizely account, open your Optimizely Console, create a new variation and add the optimizely param to your Gallery script. This is an example:

function () {
    var fileRef = document.createElement('script');
        fileRef.setAttribute("type", "text/javascript");
        fileRef.setAttribute("src", "//static.vilynx.com/gallery/vpg.{{galleryVersion}}.min.js");
        fileRef.setAttribute("data-publickey", "YOUR_USER_ID");
        fileRef.setAttribute("data-optimizely", "true");
    document.body.appendChild(fileRef);
};

In order to compare the same events in the original page (A) and the variation (B) it’s necessary to include the Vilynx Gallery library also in the original page but remember to add the optimizelyoff param to the setup. The previous example will look like this in the original page:

function () {
    var fileRef = document.createElement('script');
        fileRef.setAttribute("type", "text/javascript");
        fileRef.setAttribute("src", "//static.vilynx.com/gallery/vpg.{{galleryVersion}}.min.js");
        fileRef.setAttribute("data-publickey", "YOUR_USER_ID");
        fileRef.setAttribute("data-optimizely", "true");
        fileRef.setAttribute("data-optimizelyoff", "true");
    document.body.appendChild(fileRef);
};

Once this is done, you only need to register the events that you want to track:

  • Summary Play: register a new goal as usual and under events, select Custom Event, with this event to track: 'summary_play'.

  • Summary Click: register a new goal as usual and under events, select Custom Event, with this event to track: 'summary_click'.

  • Clicks: register a new click event. Make sure that the click event is assigned to the <a> element, no to the <img>. To verify this, please click on Advanced and make sure you're tracking the 'a', or 'a#yourlinkid'.

Other analytics tools

You can use the hooks system to integrate any other analytics tool that provides a JS API. To track the Gallery events you should follow the next two steps:

  • Add the ongalleryload param:

    On your Gallery script configuration add the ongalleryload attribute to set the name of the custom function that you wish to execute before the script starts to scan your page.

    This is an example:

    function () {
        var fileRef = document.createElement('script');
            fileRef.setAttribute("type", "text/javascript");
            fileRef.setAttribute("src", "//static.vilynx.com/gallery/vpg.{{galleryVersion}}.min.js");
            fileRef.setAttribute("data-publickey", "YOUR_USER_ID");
            fileRef.setAttribute("data-ongalleryload", "window.galleryTracking.customFunctionOnLoad");
        document.body.appendChild(fileRef);
    };

    The function that you passed as a parameter will be executed. In the example above is window.galleryTracking.customFunctionOnLoad.

  • Tracking events:

    The Vilynx Gallery has a hooks system that allows you to execute a list of callbacks to track 3 key events: video_play, summary_play and thumbnail_shown. These callbacks are set inside window.galleryTracking.customFunctionOnLoad as follows:

    window.galleryTracking = {
         customFunctionOnLoad: function () {
            // You need to pass your function (window.myAnalytics.track() in this example) as first argument for any event you want to track:
    
            // video_play: To register every click on a preview
            window.vilynxGallery.addOnTrackVideoPlay(
                function () {
                    window.myAnalytics.track('full_video_play');
                }
            );
    
            // summary_play: To track videos viewed for 500ms or more
            window.vilynxGallery.addOnTrackSummaryPlay(
                function () {
                    window.myAnalytics.track('preview_play');
                }
            );
    
            // thumbnail_shown: For all the thumbnail events
            window.vilynxGallery.addOnTrackThumbnailShown(
                function () {
                    window.myAnalytics.track('thumbnail_is_shown');
                }
            );
         }
     };
Example

The following example should help you understand the complete integration of the two steps described above.

window.myAnalytics = {
     // Your custom function must contain the code that will be executed when the event is triggered
     track: function (eventTrack) {
        // As a simple example: let's get some feedback
        console.info('Tracking event: ' + eventTrack);
     }
 };

 window.galleryTracking = {
     // customFunctionOnLoad will be passed to Vilynx gallery script tag, and will be called once the gallery plugin is ready
     customFunctionOnLoad: function () {
        // You need to pass your function (window.myAnalytics.track() in this example) as first argument for any event you want to track:

        // video_play: To register every click on a preview
        window.vilynxGallery.addOnTrackVideoPlay(
            function () {
                window.myAnalytics.track('full_video_play');
            }
        );

        // summary_play: To track videos viewed for 500ms or more
        window.vilynxGallery.addOnTrackSummaryPlay(
            function () {
                window.myAnalytics.track('preview_play');
            }
        );

        // thumbnail_shown: For all the thumbnail events
        window.vilynxGallery.addOnTrackThumbnailShown(
            function () {
                window.myAnalytics.track('thumbnail_is_shown');
            }
        );
     }
 };

 // The vilynx gallery plugin can be inserted with JS or can be in the DOM when the document load. But the customFunctionOnLoad function must exist when the gallery is loaded
 var galleryScript = document.createElement("script");

 // ongalleryload will be called when the gallery plugin is successfully loaded.
 galleryScript.setAttribute("data-ongalleryload", "window.galleryTracking.customFunctionOnLoad");

 // publickey is required to identify you as a vilynx user.
 galleryScript.setAttribute("data-publickey", "YOUR_USER_ID");

 galleryScript.setAttribute("src", "//static.vilynx.com/gallery/vpg.{{galleryVersion}}.min.js");

 document.body.appendChild(galleryScript);
ComScore

A tracking pixel is a little piece of code containing a 1x1 pixel image that you can use to track any important activity on your website. This is done by making a server call to a third party like comScore in the form of a URL.

The endpoint URL requested by comScore includes a querystring with a variety of parameters. Most common are the “c-parameters” which represent different pieces of information, for example:

<!-- Begin comScore Tag -->
<noscript>
    <div>
        <img src="https://sb.scorecardresearch.com/p?c1=2&c2={{Client ID}}&c4={{Page URL}}" height="1" width="1" alt="*">
    </div>
</noscript>
<!-- End comScore Tag -->
                        
Some of these fields are required, so you should make sure to pass all the mandatory labels. Don't forget to include your C2 Value provided by comScore, also known as the client ID, as well as the timestamp for when the pixel tracking request is created as a comScore parameter!

Example

Vilynx can help you to send your data to comScore using the hook system methodology explained in the Other analytics tools integration section.
After you implement the code below, the comScore tracking pixels will be added to each preview and fired when the user starts watching any preview.
The same can be done for the 3 key events tracked by Vilynx: video_play, summary_play and thumbnail_shown.

window.vlx_comscore = {
     // trackingPixelOnLoad will be passed to Vilynx gallery script tag, and will be called once the gallery plugin is ready.
     trackingPixelOnLoad: function () {

        // summary_play: The tracking pixel URL will be called when the user starts watching a preview for 500ms or more.
        window.vilynxGallery.addOnTrackSummaryPlay(
            function () {
                var cs_data = {
                    cs_hostname: 'https://sb.scorecardresearch.com/b',
                    c1: '2',
                    c2: 'CLIENT_ID',// Your own client ID from comScore as the c2 parameter.
                    c3: 'CAMPAIGN_ID',
                    c4: '*null', // Unused mandatory labels must still be passed with the literal string value *null.
                    ns__t: Date.now() // Timestamp for when the pixel is created.
                };

                // Add the hostname and the custom or mandatory labels to the tracking pixel URL:
                var pixelUrl = cs_data.cs_hostname + '?c1=' + cs_data.c1 + '&c2=' + cs_data.c2 + '&c3=' + cs_data.c3 + '&c4=' + cs_data.c4 + '&ns__t=' + cs_data.ns__t;

                // comScore api call via tracking pixel.
                var noscript = document.body.querySelector('[vlx-id="vlx_cs"]'),
                    trackingPixel;

                if (!noscript) {
                    noscript = document.createElement('NOSCRIPT');
                    noscript.setAttribute('vlx-id', 'vlx_cs');
                    document.body.appendChild(noscript);

                    // Create an <img> tag from the comScore domain.
                    trackingPixel = document.createElement('IMG');
                    noscript.appendChild(trackingPixel);
                } else if (noscript.firstChild) {
                    trackingPixel = noscript.firstChild;
                }

                // On the img request, the pixelUrl is updated with new data every time the summary_play event is triggered.
                trackingPixel.setAttribute('src', pixelUrl);
            }
        );

     }
 };

 // The vilynx gallery plugin can be inserted with JS or can be in the DOM when the document load. But the trackingPixelOnLoad function must exist when the gallery is loaded.
 var galleryScript = document.createElement("script");

 // ongalleryload will be called when the gallery plugin is successfully loaded.
 galleryScript.setAttribute("data-ongalleryload", "window.vlx_comscore.trackingPixelOnLoad");

 // publickey is required to identify you as a vilynx user.
 galleryScript.setAttribute("data-publickey", "YOUR_USER_ID");

 galleryScript.setAttribute("src", "//static.vilynx.com/gallery/vpg.{{galleryVersion}}.min.js");

 document.body.appendChild(galleryScript);
Cookie Storage Policies

The new GDPR Policy prohibits publishers from storing any identifying information about users without their explicit consent. We’re happy to report that none of the Vilynx products collect personal information about users and are therefore fully compliant with the GDPR. That being said, we do use cookies to store Vilynx-specific user IDs.

If you want to allow your users to block this cookie for a specific page, you must:

  • Upgrade to the latest Gallery version.

  • Activate the disablestorage param in the Gallery script.

For example:

function () {
    var fileRef = document.createElement('script');
        fileRef.setAttribute("type", "text/javascript");
        fileRef.setAttribute("src", "//static.vilynx.com/gallery/vpg.{{galleryVersion}}.min.js");
        fileRef.setAttribute("data-publickey", "YOUR_USER_ID");
        fileRef.setAttribute("data-disablestorage", "true");
    document.body.appendChild(fileRef);
};
v0.1.6

Vilynx Recommendation

Get your recommendations

To start getting personalized recommendations from Vilynx you need to include the javascript below to enable the vilynx recommendation engine within your page framework. See below for more information about the code configuration.

<script src="//static.vilynx.com/vidrec/vidrec.{{vidrecVersion}}.min.js" publickey="youruserhash" onpluginload="handler.onPluginLoad" limit="5" ></script>
  • publickey="youruserhash" This is your user ID.

  • onpluginload="handler.onPluginLoad" Is the javascript function that will be called once the vidrec plugin is loaded. For more info, see integration examples

  • limit="5" The maximum number of recommendations to be returned.

If you need more help integrating the vilynx recommendation engine, send us an email to info@vilynx.com

Integration examples

There are a two ways you can integrate the recommendation plugin into your site:

  • JS Array response:

    Use the code below to enable the recommendation plugin, you'll get a Javascript array response which is a list of URLs and use it to display the content on your page.

    Example

    The Vilynx Recommendation Plugin works as follows: first, it fires the onPluginLoad event when the plugin is ready, which allows you to use the vilynxRecommendations object to obtain a list of recommendations calling the function vilynxRecommendations.get(). Once this function is completed, it fires the callback function passed as second parameter to the .get() call, where the recommendations can be retrieved. For example, if your callback function is onReturn(recs), the recommendations will be on the recs variable.
    The .get() function allow up to three parameters:

    The URL to get the recommendations from

    The callback function to receive the recommendations

    A options object with the settings for each individual request (more details)

    The following example displays how to use these two events to manage the recommendations.

    
             var handler = {
         // handler.onPluginLoad will be passed to Vilynx recommendation script tag, and will be called once the vidrec plugin is ready
         onPluginLoad: function () {
             // This variable must contain a valid URL or a valid GUID
             var url = "example.com/sports/somearticle", options = {"limit": 5, "type":["video", "article"]};
             // Let's get some feedback
             console.info('Vilynx Recommendation plugin loaded');
    
             // Vilynx recommendation plugin will find all the recommendations for 'url' and will call handler.onRecomendations wen the recommendations are ready
             vilynxRecommendations.get(url, handler.onRecomendations, options);
         },
         // handler.onRecomendations will be called when the vilynxRecommendations.get call is done
         onRecomendations: function (recomendations) {
             // 'recomendations' will be a ordered array of recommended urls
             console.log(recomendations)
         }
     }
    
     // The vilynx recommendation plugin can be inserted with JS or can be on the DOM when the document load. But the onPluginLoad function must exist when the vidrec is loaded
     var vidrecScript = document.createElement("script");
    
     // onpluginload will be called when the vidrec plugin is successfully loaded.
     vidrecScript.setAttribute("onpluginload", "handler.onPluginLoad");
    
     // publickey is required to identify you as a vilynx user.
     vidrecScript.setAttribute("publickey", "youruserhash");
    
     // limit will be the the max number of recommendations.
     vidrecScript.setAttribute("limit", "5");
    
     vidrecScript.src = "//static.vilynx.com/vidrec/vidrec.{{vidrecVersion}}.min.js";
    
     var target = document.querySelector("body");
     target.appendChild(vidrecScript)
                                    
  • HTML response:

    Alternatively, you can utilize our recommendation plugin to get an HTML response that will display your thumbnails and content title. The code is completely responsive and displays as many thumbnails as it can, depending on the size of the parent container, whether it’s set horizontally or vertically. You can also choose to override the default size settings by defining a minimum width/height value.

    Example

    This version fires the onPluginLoad event when the plugin is ready, which allows you to use the vilynxRecommendations object. To obtain the full HTML of your recommendations call the function vilynxRecommendations.insert(). Once this function is completed, the recommendations will be inserted on the desired DOM object passed as a parameter to the .insert() call.

    The URL to get the recommendations from

    The DOM path to insert the recommendations

    A options object with the settings for each individual request (more details)

    The following example displays how to use these two events to manage the recommendations.

    
             var handler = {
         // handler.onPluginLoad will be passed to Vilynx recommendation script tag, and will be called once the vidrec plugin is ready
         onPluginLoad: function () {
             // This variable must contain a valid URL or a valid GUID
             var url = "example.com/sports/somearticle",
                 options = {"limit": 5, "type":"articles"};
    
             // Let's get some feedback
             console.info('Vilynx Recommendation plugin loaded');
    
             // Vilynx recommendation plugin will find all the recommendations for 'url' and will insert the recommenations into the `#recommendations` DOM element
             vilynxRecommendations.insert(url, '#recommendations', options);
         }
     }
    
     // The vilynx recommendation plugin can be inserted with JS or can be on the DOM when the document load. But the onPluginLoad function must exist when the vidrec is loaded
     var vidrecScript = document.createElement("script");
    
     // onpluginload will be called when the vidrec plugin is successfully loaded.
     vidrecScript.setAttribute("onpluginload", "handler.onPluginLoad");
    
     // publickey is required to identify you as a vilynx user.
     vidrecScript.setAttribute("publickey", "youruserhash");
    
     // limit will be the the max number of recommendations.
     vidrecScript.setAttribute("limit", "5");
    
     vidrecScript.src = "//static.vilynx.com/vidrec/vidrec.{{vidrecVersion}}.min.js";
    
     var target = document.querySelector("body");
     target.appendChild(vidrecScript)
                                    
Options

Several options can be passed through the script:

Name type default description
publickey string none Unique id to identify your Vilynx account
debug boolean false Print debug console logs
feedhash string none If a feed hash is given, only the recommendations obtained from that feed will be returned
onpluginload function none Is the script that will be called once the plugin is loaded
limit number 5 The the max number of recommendations returned by the script
retrieveguid boolean false If is set to true, the plugin will return GUID insead of URLS
urlfilterregex regex none Will filter all the urls that match the given regex
type array ["video"] The type of recommenations to get ('video,'articles')
returnmetadata boolean false If set to True, will return a rich output.
v1.0.0

Vilynx Previews over TVos

Integration Instructions

Adding vilynx previews on tvOs is very simple and doesn't require any changes to your application's core code.

You’ll need to include the Vilynx TVJS script, enter your user key (which you can obtain from your User details in the Vilynx Dashboard) and add the vilynx_media parameter to your Media Content. Please refer to the following instructions for information on how to integrate Vilynx previews into your tvOS App.

  • Load the VilynxOTTScript

    Load the following script on your App.onLaunch function:

    An example of this can be seen here:
    
      App.onLaunch = function () {
        const vilynxOttScriptUrl = "https://static.vilynx.com/ott/tvOsVpg.1.0.0.min.js";
        var jsFilesArray = [vilynxOttScriptUrl];
    
        evaluateScripts(javascriptFiles, function (success) {
            if (success) {
                //All the script are injected
                vilynxGallery = new vilynxGallery();// Create a new vilynx gallery instance
                vilynxGallery.key = 'e685ff41322653a80f121a2957bc6d57'//Your user key
                var extension = "templates/main_template.xml"; //Get your TVML template
                getDocument(extension);
    
            } else {
                throw ("Playback Example: unable to evaluate scripts.");
            }
        });
    }
                            
  • Modify your TVML Layout

    The second step is to add the vilynx_media parameter to the media contents in which you want to enable the previews.
    Your mediaContent can be as you want, but it should contain at least the playbackMode="onFocus", the vilynx_media and include an image element.
    To do so, please follow this format on your TVML layout:

    
    <!--  Your TVML code -->
    <lockup>
        <mediaContent playbackMode="onFocus" vilynx_media="videoGUID or videoUrl">
            <img src="example.com/newsImage.jpg" width="250" height="141">
            <title>This is a title</title>
        </mediaContent>
    </lockup>
    <!-- More TVML code -->
                            

    Remember that you will have to pass the video url or GUID that identifies that video so that the API can understand which teaser to display.

  • Execute vilynxGallery.animateMedia()

    Finally, before inserting your TVML layout, you need to execute the following function:

    vilynxGallery.animateMedia(document);

    And that should be it. The VilynxGallery OTT plugin will take care of showing the teasers to animate your thumbnails!.

Integration examples

The following integration example should help you understand the three steps described above. If you need more help to integrate the OTT plugin send us an email to info@vilynx.com

On the next snippet, is a example of TVJS code for the integration


var vilynxGallery;

App.onLaunch = function () {
    const vilynxOttScriptUrl = "https://static.vilynx.com/ott/tvOsVpg.1.0.0.min.js";
    var jsFilesArray = [vilynxOttScriptUrl];

    evaluateScripts(javascriptFiles, function (success) {
        if (success) {
            //All the script are injected
            vilynxGallery = new vilynxGallery();// Create a new vilynx gallery instance
            vilynxGallery.key = 'e685ff41322653a80f121a2957bc6d57'//Your user key
            var extension = "templates/main_template.xml"; //Get your TVML template
            getDocument(extension);

        } else {
            throw ("Playback Example: unable to evaluate scripts.");
        }
    });
}

/* fetch a document page from a remote server */
function getDocument(extension) {
    var templateXHR = new XMLHttpRequest();
    var url = baseURL + extension;
    loadingTemplate();
    templateXHR.responseType = "document";
    templateXHR.addEventListener("load", function() {pushPage(templateXHR.responseXML);}, false);
    templateXHR.open("GET", url, true);
    templateXHR.send();
}

/* This function will inject a loaded xml doc into de main view */
function pushPage(document){
    var currentDoc = getActiveDocument();

    //Once the TVML is loaded and before injecting it into the page, we will let vilynx take control of all the media elements
    vilynxGallery.animateMedia(document);

    // Inject or replace
    if (currentDoc.getElementsByTagName("loadingTemplate").item(0) == null) {
        console.log("no loading");
        navigationDocument.pushDocument(document);

    } else {
        navigationDocument.replaceDocument(document, currentDoc);
        console.log("loading");
    }
}
                    

How to implement Vilynx in a TVOS Swift App

To use Vilynx in a TVOS Swift App you need to first call the API in order to receive a JSON with the hashes of the videos.
To do that, you’ll have to call a url with the ownerID parameter, as well as an array with the video urls and wait until you receive the JSON with the information in the URLSessionTask.


                            let ownerID = "YOUR_OWNER_ID"
let urls = ["URL_VIDEO_1",
            "URL_VIDEO_2",
            "URL_VIDEO_3"]
let urlsConcat = urls.joined(separator: “,”)
let url = URL(string: "http://www.vilynx.com/get_hashes.php?owner=" + ownerID + "&url=" + urlsConcat)!
let session = URLSession(configuration: .default)
let request = NSMutableURLRequest(url: url)
let task = session.dataTask(with: request as URLRequest, completionHandler: {
    (
    data, response, error) in
    guard let _:Data = data, let _:URLResponse = response  , error == nil else {
        print(error ?? "")
        return
    }
    do
    {
          //Extract the json information
    }
    catch let jsonError
    {
        print(jsonError)
        return
    }
})
task.resume()

Once you’ve made the call, you’ll have to extract the information from the JSON in order to store the hashes of the videos. To do this, you’ll need to create an array var:

var arrayData:[[String: Any]]!

Next, you’ll have to replace the comment “//Extract the JSON information” with the following code:

//Getting the info from the json
self.arrayData = try JSONDecoder().decode(Hashes.self, from: data!)

The next step is adding this structs at the end of the class:

private struct Hash: Codable {
    let url: [String]
    let hash: [String]
}

private struct Hashes: Codable {
    let hashes: [Hash]
}

Lastly, you’ll have to get the thumbnails to match your video array. There are 3 ways to get thumbnails:

  • Fullscreen preview

    This method displays the video preview in the background when the focus is over the thumbnail.
    To know which hash is contained in the thumbnail, use the tag of the button. This tag indicates the position in the array.

    var index = 0
    for item in self.arrayData.hashes
    {
        DispatchQueue.main.async {
            let button = UIButton()
            //You can calculate the rect values to show them in the way you want
            button.frame = CGRect.init(x: x, y: y, width: width, height: height)
            button.tag = index
            self.addSubview(button)
            index += 1
        }
    }

    The code above created one button for each hash/video. In order to display a thumbnail within each button, you’ll need to add the following code in each button iteration.

    let hash = item.hash[0]
    let urlImage = "http://public.vilynx.com/" + hash + "/pro69.viwindow0.jpg?v=100"
    let session = URLSession(configuration: .default)
    let request = URLRequest(url: URL(string: urlImage)!)
    let getImageFromUrl = session.dataTask(with: request) { (data, response, error) in
        if let e = error {
            print("Error Occurred: \(e)")
        } else {
            if (response as? HTTPURLResponse) != nil {
                if let imageData = data {
                    //getting the image
                    let image = UIImage(data: imageData)
                    //displaying the image
                    DispatchQueue.main.async {
                        button.setImage(image, for: .normal)
                    }
                } else {
                    print("Image file is corrupted")
                }
            } else {
                print("No response from server")
            }
        }
    }
    //starting the download task
    getImageFromUrl.resume()

    In order to determine whether the focus is on a thumbnail, you’ll need to override the function didUpdateFocus.

    override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
        guard let button = UIScreen.main.focusedView as? UIButton else {
            return
        }
        //Show the video preview
    }

    Now that you know that the focus is over a thumbnail, you can show the video preview. The video will play in a loop and using AVPlayerLooper.
    Add the following code to replace the previous commented line “//Show the video preview”.

    let hash = arrayData[button.tag].hash[0]
    let urlVideo = "https:public.vilynx.com/" + hash + "/pro69.viwindow.mp4"
    guard let url = URL(string: urlVideo) else {
        return
    }
    let asset = AVAsset(url: url)
    let playerItem = AVPlayerItem(asset: asset)
    let player = AVQueuePlayer(playerItem: playerItem)
    //Generating the loop in the player
    let playerLooper = AVPlayerLooper(player: player, templateItem: playerItem)
    let playerLayer = AVPlayerLayer(player: player)
    //Adding the layer of the player to the view in the background
    playerLayer.frame = self.view.bounds

    And lastly, add the video to the background of the viewcontroller.

    self.view.layer.addSublayer(playerLayer)
    player.play()
  • Preview over the thumbnails

    In this method, the preview is displayed directly over the thumbnail. Follow the same instructions as the first method (Fullscreen Preview) except for the last part of code.
    Instead of adding the playerlayer to the viewcontroller, it should be added to the thumbnail button.

    button.layer.addSublayer(playerLayer)
    player.play()
  • Preview in the center of the screen

    Finally, this method displays the preview video in the center of the screen. Follow the same instructions as in the first method (Fullscreen Preview) except for the last part of code.
    Instead of adding the playerlayer to the viewcontroller, it should be added to the view in the center.

    viewCenter.layer.addSublayer(playerLayer)
    player.play()
v1.0.0

How to use Vilynx in a Roku App

Integration Instructions

Adding vilynx previews to a Roku app is very simple and doesn't require many changes to your application's core code.

First, you need to create a scene object from HomeScene, and then load the rss with your videos in the main file. To do that, you have to get the filename rss and parse it.

sub RunUserInterface()
    screen = CreateObject("roSGScreen")
    scene = screen.CreateScene("HomeScene")
    port = CreateObject("roMessagePort")
    screen.SetMessagePort(port)
    screen.Show()
    fileName = "pkg:/staticXml/media.rss"

    rsp = CreateObject("roXMLElement")
    rsp.Parse(ReadAsciiFile(fileName))
end sub

Then you have to get the child elements in an array.

responseXML = rsp
responseXML = responseXML.GetChildElements()
responseArray = responseXML.GetChildElements()

Once the array is loaded, you have to get each item and fill an object with properties, such as stream url or thumbnail. With each item you have to fill an array to store all the videos.

result = []

    for each xmlItem in responseArray
        if xmlItem.getName() = "item"
            itemAA = xmlItem.GetChildElements()
            if itemAA <> invalid
                item = {}
                for each xmlItem in itemAA
                    item[xmlItem.getName()] = xmlItem.getText()
                    if xmlItem.getName() = "media:content"
                        item.stream = {url : xmlItem.url}
                        item.url = xmlItem.getAttributes().url
                        item.streamFormat = "mp4"

                        mediaContent = xmlItem.GetChildElements()
                        for each mediaContentItem in mediaContent
                            if mediaContentItem.getName() = "media:thumbnail"
                                item.HDPosterUrl = mediaContentItem.getattributes().url
                                item.hdBackgroundImageUrl = mediaContentItem.getattributes().url
                            end if
                        end for
                    end if
                end for
                result.push(item)
            end if
        end if
    end for

In the HomeScene, you need to create a new object for GridScreen in the Init.

Function Init()
    ' listen on port 8089
    ? "[HomeScene] Init"

    'main grid screen node
    m.GridScreen = m.top.findNode("GridScreen")
End Function

Going back to the main file, you have to create a list with the array of items in the RunUserInterface and send it to the GridScreen, parsing the content with a custom function called ParseXMLContent.

list = [
        {
            Title:"First row"
            ContentList : result
        }
    ]
    scene.gridContent = ParseXMLContent(list)

Now it's necessary to create the function ParseXMLContent. In this function you have to create a ContentNode, in this example RowItems. You will then store items of class VilynxContentNode, which you will define later, and save each key from the array of items previously loaded.

Function ParseXMLContent(list As Object)
    RowItems = createObject("RoSGNode","ContentNode")

    for each rowAA in list
        row = createObject("RoSGNode","ContentNode")
        row.Title = rowAA.Title

        for each itemAA in rowAA.ContentList
            item = createObject("RoSGNode","VilynxContentNode")
            ' We don't use item.setFields(itemAA) as doesn't cast streamFormat to proper value
            for each key in itemAA
                item[key] = itemAA[key]
            end for
            row.appendChild(item)
        end for
        RowItems.appendChild(row)
    end for

    return RowItems
End Function

The VilynxContentNode is just an xml extended from ContentNode with the field vilynxhash. In this field you will store the hashes of the videos.

<?xml version="1.0" encoding="UTF-8"?>

<component name="VilynxContentNode" extends="ContentNode">
    <interface>
        <field id="vilynxhash" type="string"/>
    </interface>

</component>

Now you’ll create the HomeScene xml. In this xml you can see two observers that will be notified when the item selected has changed. Also, you can see an id to the file GridScreen that you will see later, a poster with the logo, the main video node, a timer and a loadingindicator. All these components, will be explained later.

<?xml version="1.0" encoding="utf-8" ?>
<!-- main node which handles home screen children -->
<component name="HomeScene" extends="Scene">

    <interface>
        <!-- Specifies the content for the GridPannel -->
        <field id="gridContent" type="node" alias="GridScreen.content" onChange="OnChangeContent"/>
        <field id="rowItemSelected" type="intarray" alwaysnotify="true" alias="GridScreen.rowItemSelected"/>
    </interface>

    <!-- main handler -->
    <script type="text/brightscript" uri="pkg:/components/screens/HomeScene/HomeScene.brs" />

    <children>

        <GridScreen
            id="GridScreen"
            visible="true"
            translation="[0,0]" />

        <Group
            id="HomeSceneOverhang"
            >
            <Poster
                translation="[20, 0]"
                uri="pkg:/images/overhangLogo.png"
                width="110"
                height="70" />
        </Group>

        <!-- Main video node -->
        <Video
            id="videoPlayer"
            visible="false"
            translation="[0, 0]"
            width="1280"
            height="720"/>

        <!-- This timer will be used to make the vilynx preview to stop before playing the main video -->
        <Timer
          id="waitToFinishVilynxVideo"
          repeat="false"
          duration="1"/>

    </children>
</component>

In the Init of the HomeScene file, you have to define an object from VideoPlayer and add the handler OnRowItemSelected. Also you have to init the waitToFinishVilynxVideo, add an observer state to videoPlayer to be notified when the video has ended and add an observer to the timer to get notified when it has been fired.

'video player node
m.videoPlayer = m.top.findNode("videoPlayer")

'added handler on item selecting event in grid screen
m.top.observeField("rowItemSelected", "OnRowItemSelected")

m.waitToFinishVilynxVideo = m.top.findNode("waitToFinishVilynxVideo")
m.videoPlayer.observeField("state", "OnVideoPlayerStateChange")

m.waitToFinishVilynxVideo.observeField("fire", "OnTimeOut")

When the app starts, the OnRowItemSelected will be called. In this function you’ll have to hide the GridScreen to get the video of the selected item and make the videoPlayer visible, then the timer starts.

'Row item selected handler
Sub OnRowItemSelected()
    ? "[HomeScene] OnRowItemSelected"

    m.GridScreen.visible = false
    selectedItem = m.GridScreen.focusedContent
    m.videoPlayer.content = selectedItem
    m.videoPlayer.visible = true

    'init of video player and start playback
    m.waitToFinishVilynxVideo.control = "start"
End Sub

When the timer ends, the observer OnTimeOut will be called and you’ll have to stop the timer, and play the video.

Sub OnTimeOut()
    m.waitToFinishVilynxVideo.control = "stop"

    'init of video player and start playback
    m.videoPlayer.setFocus(true)
    m.videoPlayer.control = "play"


End Sub

When the video ends, the observer OnVideoPlayerStateChange will be called, then you’ll have to hide the video and make visible the GridScreen with the thumbnail.

Sub OnVideoPlayerStateChange()
    ? "HomeScene > OnVideoPlayerStateChange : state == ";m.videoPlayer.state
    if m.videoPlayer.state = "error"
        'hide vide player in case of error
        m.videoPlayer.visible = false
        m.GridScreen.visible = true
        m.GridScreen.setFocus(true)

        m.videoPlayer.control = "stop"
        m.waitToFinishVilynxVideo.control = "stop"

    else if m.videoPlayer.state = "playing"
    else if m.videoPlayer.state = "finished"
        'hide vide player if video is finished
        m.videoPlayer.visible = false
        m.GridScreen.visible = true
        m.GridScreen.setFocus(true)
        m.videoPlayer.content = ""

        m.waitToFinishVilynxVideo.control = "stop"

    end if
end Sub

Now you have to add this function to control when an item's changed to refresh the videoPlayer.

'if content set, focus on GridScreen
Sub OnChangeContent()
    ? "OnChangeContent "
    m.GridScreen.setFocus(true)
End Sub

To finish the HomeScene file you have to implement the function OnkeyEvent to hide the videoPlayer when the "back" key's pressed.

'Main Remote keypress event loop
Function OnkeyEvent(key, press) as Boolean
    ? ">>> HomeScene >> OnkeyEvent >> " ; key
    result = false
    if press
        '? "key == ";key

        if key = "options"
            ' option key handler
        else if m.GridScreen.visible = false and key = "back"
            'hide vide player and stop playback if back button was pressed
            m.videoPlayer.visible = false
            m.videoPlayer.control = "stop"
            m.GridScreen.visible = true
            m.GridScreen.setFocus(true)
            result = true
        end if
    end if

    return result
End Function

Now you are going to create the GridScreen file, starting with the xml. This xml contains the interface section, an observer for when the content changes, an observer for when the rowItemSelected changes, an observer for when the item's focused and an observer for when the item's selected. It also contains a node called focusedContent. You also have to define the children FadingBackground that you will see later, a RowList from the component VilynxGroup, that you will see later too, a Description, that will contain the description of the video and a timer.

<component name="GridScreen" extends="Group" initialFocus="RowList">
    <interface>
        <!-- input -->
        <!-- Grid Content Node -->
        <field id="content" type="node" alias="RowList.content" onChange="onContentChange"/>

        <!-- Row item selection handler -->
        <field id="rowItemSelected" type="intarray" alwaysnotify="true" alias="RowList.rowItemSelected"/>

        <!-- Row item focused handler -->
        <field id="itemFocused" type="intarray" alias="RowList.rowItemFocused" onChange="OnItemFocused"/>

        <field id="itemSelected" type="intarray" alias="RowList.rowItemSelected" onChange="OnItemSelected"/>


        <!-- Interface to focused item (Content Node) -->
        <field id="focusedContent"  type="node"/>
    </interface>

    <!-- main handler -->
    <script type="text/brightscript" uri="pkg:/components/screens/GridScreen/GridScreen.brs" />

    <children>

        <FadingBackground
            id="Background"
            width="1280"
            height="720"
            color="0xAAAAAA"
            ShadeOpacity="0.1"/>

        <Rectangle
          color="0x000000ff"
          width="20000"
          height="220"
          translation="[-40, 540]" />

        <RowList
            id="RowList"
            itemComponentName="VilynxGroup"
            focusBitmapUri="pkg:/images/focus_grid.9.png"
            translation="[-40, 540]"
            itemSize="[1327, 218]"
            numRows="1"
            itemSpacing="[13, 0]"
            focusXOffset="[147]"
            rowFocusAnimationStyle="fixedFocusWrap"
            rowItemSize="[[262, 147]]"
            rowItemSpacing="[[16.5, 3]]"
            rowLabelOffset="[[147, 20]]"/>

        <Poster
            translation="[0, 650]"
            uri="pkg:/images/BG_dark_down.png"
            width="2000"
            height="95" />

        <Description
            id="Description"
            translation="[25, 119]"
            itemSpacings="[7,17]"/>

        <Timer
          id="waitToParentToFinishVideo"
          repeat="false"
          duration="1"/>

    </children>
</component>

In the GridScreen, in the Init, you have to add the observer OnChildFocused and init the objects rowList, Description, Background and viewUri with a void value. Also, you have to init the timer waitToParentToFinishVideo and add and observer OnTimeOut to get notified when the timer ends.

Function Init()
    ? "[GridScreen] Init"
    m.top.observeField("focusedChild", "OnChildFocused")
    m.rowList = m.top.findNode("RowList")

    m.Description = m.top.findNode("Description")
    m.Background = m.top.findNode("Background")

    m.videoUri = ""

    m.waitToParentToFinishVideo = m.top.findNode("waitToParentToFinishVideo")

    m.waitToParentToFinishVideo.observeField("fire", "OnTimeOut")
End Function

When an item is selected, you’ll have to reset the Background properties and stop the timer waitToParentToFinishVideo.

sub OnItemSelected()
    print ">> GridScreen > OnItemSelected"
    m.waitToParentToFinishVideo.control = "stop"
    m.Background.uri = ""
    m.Background.videoUri = ""


    m.Background.itemSelected = ""
end sub

The next function that you have to define is OnItemFocused. This function will be called when an item in a row is in focus. Once you have the itemFocused, you have to assign the focusedContent finding the children from the m.top, and then assign the focusedContent to the Description content and the thumbnail to the Backgound uri. Then, you will call the timer waitToParentToFinishVideo and assign the viewUri.

'handler of focused item in RowList
Sub OnItemFocused()
    itemFocused = m.top.itemFocused
    ? ">> GridScreen > OnItemFocused "

    m.waitToParentToFinishVideo.control = "stop"

    'When an item gains the key focus, set to a 2-element array,
    'where element 0 contains the index of the focused row,
    'and element 1 contains the index of the focused item in that row.
    if itemFocused.Count() = 2 then
        'get content node by index from grid
        focusedContent = m.top.content.getChild(itemFocused[0]).getChild(itemFocused[1])

        if focusedContent <> invalid then
            'set focused content to top interface
            m.top.focusedContent = focusedContent

            'set content to description node
            m.Description.content = focusedContent
            ? "Setting  background image"
            'set background wallpaper
            m.Background.uri = focusedContent.hdBackgroundImageUrl

            '  If we do have a valid vilynx hash, play the video on background.
            if focusedContent.vilynxhash <> invalid
                m.waitToParentToFinishVideo.control = "start"
                m.videoUri = "http://public.vilynx.com/" + focusedContent.vilynxhash.toStr()  + "/pro69.viwindow.mp4"
            end if
        end if
    end if
end Sub

When the timer ends, the observer OnTimeOut will be called, and you have to assign the videoUri to the Background.

sub OnTimeOut()
    ? "Setting  background videoUri"

    m.Background.videoUri = m.videoUri
end sub

Now you have to create the VilynxGroup that you used as a RowList in the GridScreen. First of all you will create the xml. In this xml, you are creating some interface objects such as vilynxhash to store the hash, the itemContent and the width and height. You are also creating a video player the itemPoster to show the thumbnail and two animations to do the fade in and fade out. Also you have to define two timers.

<?xml version="1.0" encoding="UTF-8"?>

<component name="VilynxGroup" extends="Group">
    <interface>
        <field id="guid" type="string"/>
        <field id="vilynxhash" type="string"/>
        <field id="itemContent" type="node" onChange="itemContentChanged" />
        <field id="width" type="float" onChange="updateLayout"/>
    <field id="height" type="float" onChange="updateLayout"/>
    </interface>
    <script type="text/brightscript" uri="pkg:/components/screens/VilynxGroup/VilynxGroup.brs"/>
    <children>
        <Video id="VilynxVideoPlayer"/>
        <Poster id="itemPoster">
        </Poster>
        <Animation
                id="fadeoutAnimation"
                repeat="false"
                duration="1">
                <FloatFieldInterpolator
                    id="oldbackgroundInterpolator"
                    key="[0.0, 1.0]"
                    keyValue="[1.0, 0.0]"
                    fieldToInterp="itemPoster.opacity"/>
        </Animation>
        <Animation
            id="fadeinAnimation"
            repeat="false"
            easeFunction="linear"
            duration="0.2">
            <FloatFieldInterpolator
                id="backgroundInterpolator"
                key="[0.0, 1.0]"
                keyValue="[0.0, 1.0]"
                fieldToInterp="itemPoster.opacity"/>
        </Animation>
        <Timer
          id="pauseVideoTimer"
          repeat="false"
          duration="5"
        />
        <Timer
            id="showThumbTimer"
            repeat="false"
            duration="4"
        />
    </children>
</component>

Now, in the init, you have to initialize the objects from the xml and add some observers to control when the video has finished, a item has been selected, or when the timer has been launched.

function init()
    m.focusedNode = false
    m.videoVisible = false


    m.itemPoster  = m.top.findNode("itemPoster")
    m.pauseVideoTimer = m.top.findNode("pauseVideoTimer")
    m.showThumbTimer = m.top.findNode("showThumbTimer")

    m.videoNode = m.top.findNode("VilynxVideoPlayer")

    m.fadeoutAnimation = m.top.findNode("fadeoutAnimation")
    m.fadeinAnimation = m.top.findNode("fadeinAnimation")
    m.parentVideo = m.top.getParent().getParent().getParent().getParent().getParent().findNode("videoPlayer")

    m.videoNode.ObserveField("state", "observeStatevideoNode")
    m.videoNode.ObserveField("position", "observePositionvideoNode")

    m.parentVideo.ObserveField("state", "observeStateParentVideoNode")

    m.pauseVideoTimer.ObserveField("fire","resumeVideo")
    m.showThumbTimer.ObserveField("fire","showThumbnail")

    m.top.getParent().getParent().getParent().ObserveField("rowItemSelected", "parentItemSelected")

end function

When an item content has been changed the itemContentChanged is called, and in this function you have to create a ContentNode and get the url of the thumbnail and the hash and assign to the itemPoster uri and the new ContentNode url. Then you will assign the ContentNode to the videoNode content.

Sub itemContentChanged()
    videoContent = createObject("RoSGNode", "ContentNode")

    m.itemPoster.uri = m.top.itemContent.HDPOSTERURL
    videoContent.url = "http://public.vilynx.com/"+ m.top.itemContent.vilynxhash.toStr() +"/gallery.pro69.viwindow.mp4"
    m.videoNode.content = videoContent

End Sub

When an item focus is changed, you have to switch the focusedNode to true and assign play to the control in videoNode.

sub onItemFocusChange()
  m.focusedNode = true
  m.videoNode.control = "play"
end sub

Then you have to create the observer to get notified when the state of the video node has changed, to hide the video and launch the timer paseVideoTimer.

Sub observeStatevideoNode()
    if m.videoNode.state = "playing"
        m.showThumbTimer.control = "start"
    end if
    if m.videoNode.state = "finished"
        m.videoVisible = false
        m.pauseVideoTimer.control = "start"
    end if
End Sub

Now you have to define a function to start the fadeout animation of the thumbnail finishing with the opacity 0.

Sub observePositionvideoNode()
    if m.videoNode.position > 0.7 and m.videoVisible = false
        'If The local video is playing, remove the  thumbnail
        ? "Starting fadeoutAnimation"
        m.fadeoutAnimation.control = "start"
        'm.itemPoster.opacity = 0
        m.videoVisible = true
    end if

End Sub

You still needing to define some functions called from the observers such as resumeVideo, to continue with the playback, the function showThumbnail, to do the animation to make the thumbnail visble, the function to stop the video and the function to hide the video with an animation in the thumbnail.

Sub resumeVideo()
    ? "Resume Video called"
    if m.videoNode.state <> "playing" and m.videoNode.state <> "buffering"
        m.videoNode.control = "play"
    end if

End Sub

Sub showThumbnail()
    ? "Starting fadeinAnimation"
        m.fadeinAnimation.control = "start"
        'm.itemPoster.opacity = 1

End Sub

Sub stopVideo()

    m.videoNode.control = "stop"
    m.pauseVideoTimer.control = "stop"
    m.showThumbTimer.control = "stop"

End Sub

Sub hideVideo()
    if m.videoVisible = true
        ?"[VilynxGroup] Stoping and hidding video"
        m.videoVisible = false
        'm.fadeinAnimation.control = "start"
       showThumbnail()
    end if
End Sub

Next you’ll need to create the file Description. This file manages the description of the item. In the xml you’ll have to create the interface with the title, description, released date and an observer for when the content has changed. Then you’ll have to define the labels to show the title and the description.

Sub parentItemSelected()
    if m.focusedNode = true
        ?"[VilynxGroup] parentItemSelected!!"
        'm.focusedNode = false
        m.itemPoster.opacity = 1
        stopVideo()
        hideVideo()
    end if
End Sub

Finally, in this file you’ll have to define the observer when the parent item is selected. In this function you have to stop the video and hide it.

<?xml version="1.0" encoding="utf-8" ?>
<!--
    This item will show the description for each element, readed from the mrss
    -->
<component name="Description" extends="LayoutGroup">
    <interface>
        <!-- Alias to Title label -->
        <field id="Title"           type="node"/>

        <!-- Alias to Description label -->
        <field id="Description"     type="node"/>

        <!-- Alias to ReleaseDate label -->
        <field id="ReleaseDate"     type="node"/>

        <!-- Content node -->
        <field id="Content"         type="node" onChange="OnContentChanged"/>
    </interface>

    <!-- main handler -->
    <script type="text/brightscript" uri="pkg:/components/screens/Description/Description.brs" />

    <children>

        <Label
            id="Title"
            color="0xFFFFFF"
            height="50"
            text=""/>


        <Label
            id="Description"
            color="0xF2F2F2"
            wrap="true"
            width="345"
            height="245"
            lineSpacing="7"
            text=""
            font="font:SmallestSystemFont" />
    </children>

</component>

In the init, you have to initialize the title, ReleaseDate and Description.

sub Init()
    'setting top interfaces
    m.top.Title = m.top.findNode("Title")
    m.top.ReleaseDate = m.top.findNode("ReleaseDate")
    m.top.Description = m.top.findNode("Description")
end sub

When the content of the Description's changes, the OnContentchanged observer will be called, so you have to define the function, and assign the new title and description.

' Content change handler
' All fields population
sub OnContentchanged()
    item = m.top.content

    title = item.title.toStr()
    if title <> invalid then
        m.top.Title.text = title.toStr()
    end if

    value = item.description
    if value <> invalid then
        if value.toStr() <> "" then
            m.top.Description.text = value.toStr()
        else
            m.top.Description.text = "No description"
        end if
    end if

end sub

Finally you have to create the last file, FadingBackground, where the main video is controlled. First of all, you have to create the xml. In this file, you have to create in the interface tag, fields to detect when the uri, videoUri and itemSelected have changed. Then you have to create some controls on screen such as backgroundColor, to change the background color, video, storing the video that you want to playback, oldBackground, the image that contains the previous thumbnail video, background, the image with the current thumbnail video, some aesthetics rectangles and four animations, with fade in/fade out and hide/show the thumbnail.

<?xml version="1.0" encoding="utf-8" ?>

<!--
Fading background will show and interpolate the previews for the selecred element.
-->

<component name = "FadingBackground" extends="Rectangle">

    <interface>
        <!--Uri of image.-->
        <field id="uri"    type="string"   onChange="OnBackgroundUriChange"/>
        <field id="videoUri" type="string" onChange="OnVideoUriChange"/>
        <field id="itemSelected" type="string" onChange="OnRowListItemSelected"/>

        <!--Set color of background while image is loading.-->
        <field id="ShadeOpacity"  type="float" alias="shade.opacity"/>
    </interface>


    <!-- main handler -->
    <script type="text/brightscript" uri="pkg:/components/screens/FadingBackground/FadingBackground.brs" />

    <children>

        <Rectangle
          id="backgroundColor"
          color="0x141414ff"
          width="1280"
          height="200"
          translation="[0,0]" />

        <video id="video" visible="false" mute="true" />

        <Poster
            id="oldBackground"/>

        <Poster
            id="background"
            opacity="0"/>

        <Rectangle
            id="thumbBackground"/>

        <Rectangle
            id="shade"
            color="0x000000"
            opacity="0.0"/>

        <Poster
            id="mergerv"
            uri="pkg:/images/fadingVideoV.png"
            width="95"
            height="2000" />


        <Poster
            id="mergerh"
            uri="pkg:/images/fadingVideoH.png"
            width="2000"
            height="95" />

        <Rectangle
          color="0x141414ff"
          width="12800"
          height="2000"
          translation="[0,0]"
          opacity="0.2" />

        <Animation
            id="fadeoutAnimation"
            repeat="false"
            duration="0.5">
            <FloatFieldInterpolator
                id="oldbackgroundInterpolator"
                key="[0.0, 1.0]"
                keyValue="[1.0, 0.0]"
                fieldToInterp="oldBackground.opacity"/>
        </Animation>

        <Animation
            id="fadeinAnimation"
            repeat="false"
            easeFunction="linear"
            duration="0.5">
            <FloatFieldInterpolator
                id="backgroundInterpolator"
                key="[0.0, 1.0]"
                keyValue="[0.0, 1.0]"
                fieldToInterp="background.opacity"/>
        </Animation>


        <Animation
        id="hideThumnAniation"
        repeat="false"
        duration="1">
        <FloatFieldInterpolator
            id="hideThumnAniationInterpolator"
            key="[0.0, 1.0]"
            keyValue="[1.0, 0.0]"
            fieldToInterp="background.opacity"/>
        </Animation>

        <Animation
            id="showThumnAniation"
            repeat="false"
            easeFunction="linear"
            duration="0.1">
            <FloatFieldInterpolator
                id="showThumnAniationInterpolator"
                key="[0.0, 1.0]"
                keyValue="[0.0, 1.0]"
                fieldToInterp="background.opacity"/>
        </Animation>


    </children>
</component>

Now, in the init you have initialize all the objects and create the following observers. OnBackgroundLoaded is detecting when the background is loaded and observeStatevideoNode is detecting when the video state changes. Finally you have to initialize the mustStopVideo objecxt to false.

Sub Init()
    m.background = m.top.findNode("background")
    m.oldBackground = m.top.findNode("oldBackground")
    m.oldbackgroundInterpolator = m.top.findNode("oldbackgroundInterpolator")
    m.shade = m.top.findNode("shade")

    m.fadeoutAnimation = m.top.findNode("fadeoutAnimation")
    m.fadeinAnimation = m.top.findNode("fadeinAnimation")

    m.hideThumnAniation = m.top.findNode("hideThumnAniation")
    m.showThumnAniation = m.top.findNode("showThumnAniation")

    m.backgroundColor = m.top.findNode("backgroundColor")
    m.mergerv = m.top.findNode("mergerv")
    m.mergerh = m.top.findNode("mergerh")

    m.video = m.top.findNode("video")

    m.background.observeField("bitmapWidth", "OnBackgroundLoaded")

    m.video.ObserveField("state", "observeStatevideoNode")

    m.mustStopVideo = false

End Sub

When the background changes the function OnBackgroundUriChange is called and you have to pause the video, change the value of mustStopVideo to true and stop the fade out and hide animations. Then set the opacity of the background to 1 and change the uri. You have to check if the oldUrl had a value and make the animation of the oldBackgound with fade out to set the opacity to 0.

Sub OnBackgroundUriChange()
    ? "GOT NEW BG image -- "; m.top.uri
    m.video.control = "pause"
    m.mustStopVideo = true
    m.fadeoutAnimation.control = "stop"
    m.hideThumnAniation.control = "stop"

    m.background.opacity = 1


    oldUrl = m.background.uri
    m.background.uri = m.top.uri
    if oldUrl <> "" then
        ? "GOT NEW BACKGROUND"
        m.oldBackground.uri = oldUrl
        m.oldbackgroundInterpolator = [m.background.opacity, 0]
        m.fadeoutAnimation.control = "start"
    end if
End Sub

Once the video uri changes you have to stop the fade out and hide animations and set the opacity of the background to 1. Then you have to create a ContentNode and set it to videoContent, set the videoUri to the url in videoContent, set the title to "Preview Video" and set the visibility of the video to false. Then change the content of video to videoContent, set mustStopVideo to false and play the video.

Sub OnVideoUriChange()
    ? "GOT NEW BG VIDEO -- "; m.top.videoUri
    m.fadeoutAnimation.control = "stop"
    m.hideThumnAniation.control = "stop"

    m.background.opacity = 1


    if m.top.videoUri <> ""
        ? "TRYING TO PLAY NEW BG VIDEO -- "; m.top.videoUri
        m.videoContent = createObject("RoSGNode", "ContentNode")

        m.videoContent.url = m.top.videoUri
        m.videoContent.title = "Preview Video"
        m.video.visible = "false"

        m.video.content = m.videoContent
        m.mustStopVideo = false

        m.video.control = "play"

    end if

End Sub

When the state of the video changes, the function observeStatevideoNode is called. If the state is *"playing"* and mustStopVideo is false, you have to make the video visible and start the hide animation of the thumbnail. If the mustStopVideo is true pause the video. If the state is *"finished"* set the backgound opacity to 1 and play the video.

Sub observeStatevideoNode()
    ? "[Video1] " ; m.video.state

    if m.video.state = "playing"
        if m.mustStopVideo = false
            m.video.visible = "true"

            m.hideThumnAniation.control = "start"
        else
            m.video.control = "pause"
        end if

    end if

    if m.video.state = "finished" and m.top.videoUri <> ""
        m.background.opacity = 1
        'm.showThumnAniation.control = "start"
        m.video.control = "play"
    end if

End Sub

When a rowlist item is selected, the OnRowListItemSelected is called and you have to stop the video.

Sub OnRowListItemSelected()
    print "RowList Item Selected. Stoping previews"
    m.video.control = "stop"
End Sub

When the background is loaded, the OnBackgroundLoaded's called and you have to start the fade in animation.

Sub OnBackgroundLoaded()
    m.fadeinAnimation.control = "start"
End Sub
v1.0.0

Social Share

Share your amazing video previews in any social network smoothly.
Whether you are a developer using our products in your site or a community manager sharing your videos summaries this is your help guide.

Once you have videos uploaded to your Vilynx account you can share them by posting their auto-generated video previews. Let's see how:

Go to your Vilynx Dashboard, follow these steps:

In this menu you have two options available:

  • Download the summary

    You can download the video summary so you can upload it later to any social network you want. Use the link to get your summaries faster:

    https://www.vilynx.com/get_file.php?hash={{vilynx_id}}&url={{content_url}}&type=pro69.viwindow&format=mp4&token

    {{vilynx_id}} Vilynx owner ID. Example: 14ce449ceb70a3859bd19eb20c6823d8. You can get your owner ID by going to your Vilynx Dashboard and clicking on: Settings / Public Key

    {{content_url}} Link to your video content. Example: http://www.gridv.com/watch?v=Zoj2mJWlKUk.

  • Share through webapp

    If you want a quick share on the social networks listed just click on its icon.

    Dashboard

Contact Us

For more information about the integration of our products contact us: