Jump to content

Tech Support

Administrators
  • Posts

    1,815
  • Joined

  • Days Won

    339

Posts posted by Tech Support

  1. Hi,

     

    You should really add a plugin for auto channel selection based on plugin auto model selection...

     

    It will be really helpful as now we have to manually add new videos to the channels which is painful...

     

    So please try to add the "Auto channel selection" plugin...

     

    Thanks

     

    But how do you expect it to work? Models / tags / categories autoselection are based on title / description and they look for specific words in content title or desc. Do you mean that for channels it should also use the same logic? Please post an example of video title and channel title that should be selected for this video, to make sure we understand this correctly. From my experience I don't recall that video titles have channel names, normally this is not true. But maybe you mean description, not title?

  2. 3.9.1 goes production today. You can download it in your customer zone on KVS website.

    Please consider updating from 3.9.0 to 3.9.1, as we have put a lot of fixes and enhancements for the new KVS player.

     

    For older KVS versions updating to 3.9.1 is up to you, we will just remind that 3.9.0 featured new HTML5 player and updating from earlier version can be a bit difficult, there are some potential issues described here in the 2nd post:

    http://www.kernel-video-sharing.com/forum/forum/general-discussion/announcements/28-kvs-v3-9-0

     

  3. This tag is for google, not for yandex. For some reason yandex decided to use its own tag, but in the old times it supported google tag as well.

     

    If you want to add the same info for yandex, you should create specific yandex tag as described here:

    https://yandex.com/support/video/par...-indexing.html

     

    But then probably google will say: Unknown tag ovs:video

     

    You can add this code into Website UI -> Pages -> [system] Sitemap (XML) -> Links To Videos:

    http://kvs-demo.com/admin/project_pa...%20To%20Videos

  4. In KVS you can define watermark image for each video format in Settings -> Video formats. Typically this is PNG image with some transparency and your site logo / name.

     

    How to make sure that watermark is stable for all video formats

    Since in most cases videos are provided in multiple formats, there is a common problem of watermark scaling. For example, consider a video file that is only 800px in width and the one that is 1920px in width. If your screen size is 1920px also, the first video file will be upscaled 2.5 times when displaying on full screen, while the last file won't be scaled at all. How do you decide which size watermark image should be rendered for each of this format, so that it remain stable size whether user is watching 800px format or 1920px one?

    The solution is very simple - you should upload watermark image with a big size in all formats, but configure it to take only specific % of video size. There are special options in video format settings:

    watermark_max_width.thumb.png.7fd1db828ad9fed3c6fb9ff47e34270d.png

    Having this set to 20% in all your video formats you will make sure despite of user chosen display format and user screen size the watermark will always be scaled to 20% of screen width.

    NOTE: we are not recommending using 20% and 40% values, this is something that you should decide yourself. And this is correct that max width for vertical videos is bigger than for landscape - their width in pixels is smaller.

    NOTE: KVS supports 2 different watermarks at the same time. Please note that for watermark #2 you specify max height, not width. This is on purpose for cases when you want to display running text; in some cases text length can be bigger than video file width, so in order to resize it correctly you will need to adjust max height for it.

     

    Running texts

    KVS allows showing running texts together with normal watermark images. We recommend using Watermark #2 for running text and Watermark for normal images. Running text should be still uploaded as image, e.g. you should first use image editor and create a text of your wish on transparent background; then save it into PNG and upload PNG into KVS.

    Then as a Watermark position you should select Top scrolling, or Bottom scrolling. These choices will show several more options where you configure scrolling speed and video positions when scrolling starts. This screenshot defines a scrolling watermark at bottom that will appear 3 times per video: on 10% duration, on 50% and on 90%. Watermark will be visible for 20 seconds, and this defines how fast it will scroll by dividing video width per watermark width:

    watermark_scrolling.thumb.png.69755ed81f891f936876beec0e4bd6da.png

    NOTE: it was configured that watermark takes max 5% of video height for landscape videos and max 3% of video height for portrait videos in order to make its size consistent across all formats and devices.

     

    Rendering customized watermarks

    If you want to apply different watermarks for different videos, one of the possible ways is to use custom fields of content sources to provide different watermark images for videos from different content sources. In order to use this approach, you should have well defined way of adding / importing videos with content source for each video that needs custom watermarks. The idea is each content source can define its custom watermark image and all videos that are tagged with this content source will be converted with this custom watermark image.

    In order to configure this approach, you should first go to Settings -> Customization and enable any available custom file field for content sources. Once enabled, go to each video format settings and select the activated custom field in Customize watermark for content sources field:

    watermark_customization_content_source.png.45d90e28e65b3915d7a719c9b0905f51.png

    After that you should go to each content source for which videos you want to customize watermark image and upload a custom image into Custom watermark field. Now, all videos that are created or imported with this content source, will have this custom watermark image.

    If you want to programmatically generate watermarks (e.g. type username who uploaded this video, or any other custom text which can be different), you can create custom PHP script providing hook method for KVS to use custom watermark image.

    The script should be put into /admin/include/kvs_watermark_video.php

    Here is sample script implementation, which creates watermark image with the following text: Uploaded by <username>

    <?php
    
    function kvs_watermark_video($format_postfix, $video_data)
    {
       global $config;
    
       // here you should create and return image path with your custom watermark text
       // this file will be deleted, so you need to create it each time
    
       // check $format_postfix if you need watermark to be limited to specific formats only, e.g.
       // if ($format_postfix == '.mp4' || $format_postfix == 'trailer.mp4')
    
       // for example you can query user data and render "uploaded by <username>" watermark
       $user_data = mr2array_single(sql_pr("select * from $config[tables_prefix]users where user_id=?", $video_data['user_id']));
       if ($user_data['user_id'] > 0)
       {
           $watermark_file = "$config[temporary_path]/custom_watermark.png";
    
           // settings: text, font, size and offset
           $watermark_text = "Uploaded by $user_data[display_name]";
           $font = "$config[project_path]/admin/data/system/verdanaz.ttf";
           $font_size = 10;
           $offset = 20;
    
           // rendering logic
           $box = imagettfbbox($font_size, 0, $font, $watermark_text);
    
           $im = imagecreatetruecolor(abs($box[2] - $box[0]) + 2 * $offset, abs($box[7] - $box[1]) + 2 * $offset);
           imagealphablending($im, false);
           imagefilledrectangle($im, 0, 0, abs($box[2] - $box[0]) + 2 * $offset, abs($box[7] - $box[1]) + 2 * $offset, imagecolorallocatealpha($im, 0, 0, 0, 127));
           imagealphablending($im, true);
    
           imagettftext($im, $font_size, 0, abs($box[0]) + $offset, abs($box[5]) + $offset, imagecolorallocate($im, 255, 255, 255), $font, $watermark_text);
    
           // save image to temp file
           imagesavealpha($im, true);
           imagepng($im, $watermark_file);
           imagedestroy($im);
    
           // return temp file back to KVS engine
           return $watermark_file;
       }
       return null;
    }

     

    If you need similar functionality (just plain text with custom wording), you can copy-paste this code and modify only these lines:

    $watermark_text = "Uploaded by $user_data[display_name]"; // text will render "Uploaded by <username>"
    $font = "$config[project_path]/admin/data/system/verdanaz.ttf"; // this font comes with KVS for captcha rendering, but you can use any other TTF font
    $font_size = 10; // text size
    $offset = 20; // offset from video edges, means 20 pixels from corner

     

    Here is a sample watermark created by this code. You can see that the font is a bit specific, so you should better use other font: custom_watermark.png.8c8577ab1f3baa3823aecc6b761c094a.png

    Some notes:

    • Please do not replace KVS font file with your custom font, or captcha functionality may not work correctly. If you want to use custom font, you can put it near by and correct font filename in the code.
    • This watermark will be applied to all video formats that are created by KVS. If you want to limit it to specific video format, you need to add "if" check on the $format_postfix value passed to this function and return null for formats where watermark is not needed.
    • The position of watermark will still be controlled by the Watermark position option of video format settings. By default it is set to Random, so if you don't change it then watermark will be positioned at random corner of the video.

     

    Testing watermark function

    You can test your watermark function by executing test_watermark.php script from your browser:

    http://yourdomain.com/test_watermark.php

    Here is code for test script:

    <?php
    
    require_once('admin/include/setup.php');
    require_once('admin/include/setup_db.php');
    require_once('admin/include/functions_base.php');
    require_once('admin/include/functions.php');
    
    error_reporting(E_ALL ^ E_NOTICE);
    ini_set('display_errors', 1);
    
    require_once('admin/include/kvs_watermark_video.php');
    
    $video = mr2array_single(sql("select * from ktvs_videos order by rand() limit 1"));
    $path = kvs_watermark_video(".mp4", $video);
    if ($path)
    {
       header("Content-Type: image/png");
       readfile($path);
    }

    Running this file will show you a watermark image created for random video and video format with ".mp4" postfix. If you want to test your code for another postfix, then change ".mp4" with another postfix you need.

    • Like 1
  5. In KVS list_videos and list_albums blocks won't select categories, tags, models, user or content source information by default for each video / album. This is due to performance restrictions, since in most cases such data is not needed when rendering lists. However when needed it can be enabled and displayed.

    Each list_videos / list_albums (and some other list_xxx) block supports a set of show_xxx_info parameters to enable selecting any specific additional data you need:

    show_xxx_info.thumb.png.f9ce168582adb67f2102860d52a925ba.png

    You should enable only the needed data loading, as it may significantly reduce your site performance.

    An issue here is that usually project contains multiple pages with list_videos / list_albums blocks. If you want this functionality to work consistently, you should enable the same options in almost all places. The most easy way to find pages with specific blocks is to search for block type, for example list_videos:

    search_for_list_videos.png.154eb0d16e31543930de0237696f7794.png

    You can see a plenty of list_videos blocks in your theme (Index, Common Videos List, Community, RSS, Sitemap, View Video pages and etc).

    Here are 3 places where you DON'T need this:

    • RSS Videos (XML)
    • [System] Sitemap (XML)
    • [System] Player Related Videos

    In all other blocks you may need to enable the same set of options to load additional data. Or if you want this to be visible on specific pages only (e.g. Index), then enable only there.

    The next step is to update template code to render additional data for each video. This code should be normally put into Website UI -> Page Components -> include_list_videos_block_common.tpl, which renders all video lists in your theme. This component will have some template code on top with rendering list title / sortings / filters, and then 2nd part is the actual list rendering enclosed into the following {{foreach}} tag:

    {{foreach item="item" from=$data}}
    ... each iteration renders one item here ...
    {{/foreach}}
    

    You should put your rendering code inside this {{foreach}} if you want it to be rendered for every item.

    Here are ready codes you can copy-paste. However you should consider your own styling for this, as rendering such additional info is not supported by theme styling.

    NOTE: for categories, tags and models if you want to limit the max number of displayed items you should set this limit into {{assign var="max_limit" value="0"}} value. Using zero means no limit, e.g. the code will display even 10 or 20 tags if they are all attached to a video or album.

     

    1. Categories:

    Categories:
    {{assign var="max_limit" value="0"}}
    {{assign var="index_limit" value="0"}}
    {{assign var="limit_over" value="0"}}
    {{foreach from=$item.categories item="category" name="categories"}}
       {{if $max_limit>0}}
           {{assign var="index_limit" value=$index_limit+1}}
       {{/if}}
       {{if $index_limit<=$max_limit}}
           <a href="{{$lang.urls.videos_by_category|replace:"%DIR%":$category.dir|replace:"%ID%":$category.category_id}}">{{$category.title}}</a>{{if !$smarty.foreach.categories.last}}, {{/if}}
       {{elseif $limit_over==0}}
           ...
           {{assign var="limit_over" value="1"}}
       {{/if}}
    {{/foreach}}

     

    2. Tags:

    Tags:
    {{assign var="max_limit" value="0"}}
    {{assign var="index_limit" value="0"}}
    {{assign var="limit_over" value="0"}}
    {{foreach from=$item.tags item="tag" name="tags"}}
       {{if $max_limit>0}}
           {{assign var="index_limit" value=$index_limit+1}}
       {{/if}}
       {{if $index_limit<=$max_limit}}
           <a href="{{$lang.urls.videos_by_tag|replace:"%DIR%":$tag.tag_dir|replace:"%ID%":$tag.tag_id}}">{{$tag.tag}}</a>{{if !$smarty.foreach.tags.last}}, {{/if}}
       {{elseif $limit_over==0}}
           ...
           {{assign var="limit_over" value="1"}}
       {{/if}}
    {{/foreach}}

     

    3. Models:

    Models:
    {{assign var="max_limit" value="0"}}
    {{assign var="index_limit" value="0"}}
    {{assign var="limit_over" value="0"}}
    {{foreach from=$item.models item="model" name="models"}}
       {{if $max_limit>0}}
           {{assign var="index_limit" value=$index_limit+1}}
       {{/if}}
       {{if $index_limit<=$max_limit}}
           <a href="{{$lang.urls.videos_by_model|replace:"%DIR%":$model.dir|replace:"%ID%":$model.model_id}}">{{$model.title}}</a>{{if !$smarty.foreach.models.last}}, {{/if}}
       {{elseif $limit_over==0}}
           ...
           {{assign var="limit_over" value="1"}}
       {{/if}}
    {{/foreach}}

     

    4. Content source:

    Sponsor:
    {{if $item.content_source.content_source_id>0}}
       <a href="{{$lang.urls.videos_by_sponsor|replace:"%DIR%":$item.content_source.dir|replace:"%ID%":$item.content_source.content_source_id}}">{{$item.content_source.title}}</a>
    {{/if}}

     

    5. Channel:

    Channel:
    {{if $item.dvd.dvd_id>0}}
       <a href="{{$lang.urls.videos_by_channel|replace:"%DIR%":$item.dvd.dir|replace:"%ID%":$item.dvd.dvd_id}}">{{$item.dvd.title}}</a>
    {{/if}}

     

    6. User:

    Uploaded by:
    {{if $item.user.user_id>0}}
       <a href="{{$lang.urls.memberzone_profile|replace:"%ID%":$item.user.user_id|replace:"%LOGIN%":$item.user.username}}">
           {{if $item.user.avatar}}<img src="{{$config.content_url_avatars}}/{{$item.user.avatar}}" alt="{{$item.user.username}}">{{/if}}
           {{if $lang.memberzone.truncate_username_to>0}}
               {{$item.user.display_name|truncate:$lang.memberzone.truncate_username_to:"...":true}}
           {{else}}
               {{$item.user.display_name}}
           {{/if}}
       </a>
    {{/if}}
     
  6. KVS theme customization engine provides a variety of ways to customize theme design and layout, but in some cases it is limited to sets of data it can select. The most important limitation is that you can't use blocks inside other blocks.

    There are 2 workarounds for doing this: adjust page layout structure (will not work in all cases) and pass block HTML into another block.

     

    Passing HTML from one block into another

    Let's take a look at the 2nd option, as it provides much more flexibility. Imagine that you have a list of videos and you want to render a drop down with categories there for fast navigation or to allow AJAX filtering on the selected categories. List of videos can be rendered only by list_videos block, which does not provide you list of categories to show a drop down inside. From the other hand list of categories can be rendered by list_categories block, however as it was said before you can't use one block inside another.

    For example this is how you insert list_videos on your page:

    {{insert name="getBlock" block_id="list_videos" block_name="Index Videos"}}

    In order to build category drop down and pass it to this list_videos block you should add list_categories block before it and assign its HTML result into a variable and then pass this variable to list_videos block using special var_ prefix:

    {{insert name="getBlock" block_id="list_categories" block_name="Categories Drop Down" assign="categories_dropdown_html"}}
    {{insert name="getBlock" block_id="list_videos" block_name="Index Videos" var_categories_dropdown_html=$categories_dropdown_html|smarty:nodefaults}}
    

    We added assign="categories_dropdown_html" to list_categories block in order to prevent it from printing its HTML into the place where it is inserted (since we need this HTML inside list_videos block). Then we passed $categories_dropdown_html into list_videos: var_categories_dropdown_html=$categories_dropdown_ html|smarty:nodefaults.

    Finally inside list_videos block template we can now display this HTML generated by list_categories block:

    {{$var_categories_dropdown_html|smarty:nodefaults}}

    This will print HTML code from list_categories block inside list_videos block. Looks like what we need.

    But in fact this will not work with AJAX pagination and other block-level AJAX functionality. So this approach can only be used with non-AJAX navigation.

     

    Using custom database queries from within blocks

    For advanced customization you may need to submit additional queries into database in order to select additional data, which is not selected by default in KVS. This will give you almost unlimited design customization abilities and at the same time will keep all KVS site engine benefits such as caching and high performance.

    This is not intended for basic users, in order to use it you should understand KVS database structure (since we do not provide any documentation for that, you can ask support if you have specific needs). You can use this in any cases where you want to display some data which is not provided by KVS.

    Here is the basic syntax:

    {{query_kvs select="list|single|count" table="table_name" [assign="var_name"] [sort_by="sort_by expression"] [limit="number"] [where_xxx="filter value"]}}

    Supported options:

    • select: required, one of the following: list (to select a list of items), single (to select a single item), count (to select a number of items in database)
    • table: required, table name to select from, should be specified in the following syntax: table="categories"
    • assign: required if you select list or single item, because you need to put it into a variable, but not required if selecting count; if omitted the output will be printed right a way
    • sort_by: optional, sorting SQL expression, should be a valid SQL expression for the specified table, example: sort_by="title asc"
    • limit: optional, specify the number of rows you want to select, if not specified then all rows will be selected

    You can also specify list of filters using 3 types of where parameters:

    • where_xxx: you should replace xxx with column name and specify value for "equals" match, for example: where_is_private="1" (will result in selecting only rows where is_private field = 1)
    • wheregt_xxx: you should replace xxx with column name and specify value for "greater than or equals" match, for example: wheregt_post_date="2017-05-23" (will result in selecting only rows where post_date field >= "2017-05-23")
    • wherelt_xxx: you should replace xxx with column name and specify value for "less than or equals" match, for example: wherelt_post_date="2017-05-23" (will result in selecting only rows where post_date field <= "2017-05-23")
    • wherelike_xxx: you should replace xxx with column name and specify value for LIKE match, for example:
      wherelike_title="test%" (will result in selecting only rows where title field starts with "test")
    • whereregexp_xxx: you should replace xxx with column name and specify value for regular expression match, for example:
      whereregexp_title="test.*" (will result in selecting only rows where title field matches regular expression "test.*")

    NOTE: where filters are protected from SQL injection, so you can safely use values passed from HTTP variables there, e.g.: where_is_private=$smarty.get.is_private, but sort_by expression is not protected, so you cannot use dynamic sorting here.

    Selecting data, which may have limited visibility, such as videos, albums, posts and playlists, will force default filtering (for example only active videos will be selected and etc). If for any specific reason you need to disable this filtering you should add default_filtering="false" option.

    You should be aware that submitting heavy selects may drop your project's performance. If used inside list_xxx blocks they can be cached pretty well and will not affect much. If used inside xxx_view blocks or outside blocks (at page level) their performance impact will be as much as many users log into your memberzone.

     

    Examples

    Take a look at these simple examples to see how powerful this feature can be for building an outstanding site design with very few lines.

     

    1. Show a drop down with all categories in list_videos block:

    {{query_kvs select="list" table="categories" assign="list_categories" sort_by="title asc"}}
    <ul>
    {{foreach from=$list_categories item="category"}}
       <li>{{$category.title}}</li>
    {{/foreach}}
    </ul>
    

    Note that we use assign="list_categories" here and then render this list using standard Smarty {{foreach}}.

     

    2. Show the number of videos added for the last year (last 365 days):

    {{assign var="where_post_date" value=$smarty.now-365*86400|date_format:"%Y-%m-%d"}}
    Videos added last year: {{query_kvs select="count" table="videos" wheregt_post_date=$where_post_date}}
    

    Note that we first form a $where_post_date variable in the needed date format and then pass it to query using wheregt_post_date=$where_post_date. Also we are not using assign with query function, so it will print result right a way:

    Videos added last year: 1276

     

    3. Show the number of videos that are in process now, e.g. processing queue:

    Videos processing right now: {{query_kvs select="count" table="videos" where_status_id="3" default_filtering="false"}}
    

    Note that here we disabled default filtering via default_filtering="false" since by default videos that are in process status will be filtered out from the query.

    Using this query can be useful if you want to prevent users from uploading content when there are too many videos being processed. For example you can add this code to video_edit block, which renders upload form:

    {{query_kvs select="count" table="videos" where_status_id="3" default_filtering="false" assign="videos_processed_now"}}
    {{if $video_processed_now>100}}
    Sorry, the upload is limited as we have too many videos in process right now. Please come back later!
    {{else}}
    ... show upload form as usual
    {{/if}}
    

    Note that here we are using assign="videos_processed_now" to assign the count of currently processed videos into a variable, so that we can further use it in IF statement.

     

    4. In model view page show how many other models with the same hair color:

    {{if $data.hair_id>0}}
        More models with the same hair color: {{query_kvs select="count" table="models" where_hair_id=$data.hair_id}}
    {{/if}}
    

    Note here we first check if hair color is specified for this model and then show count of models with the same hair color, we stick to the current model's hair color with using where_hair_id=$data.hair_id.

     
  7. If you want to get rid of Apache and have your site working purely on Nginx, please consider these steps to migrate Apache-specific configurations into Nginx.

    NOTE: we do not support this officially. Apache + mod_rewrite will still be required for KVS and all functionality we add or change in KVS is always tested in Apache environment. We cannot guarantee these steps are everything you need to migrate to pure Nginx. Also we cannot guarantee that any future features will work in pure Nginx environment or will not require changes in Nginx configuration to make them working correctly.

    Nginx should set the following environmental variables which are typically set by Apache:

    • REMOTE_ADDR
    • SCRIPT_FILENAME
    • SCRIPT_NAME
    • REQUEST_METHOD
    • QUERY_STRING
    • REQUEST_URI
    • DOCUMENT_ROOT

    These are typically set by default fastcgi configuration, but worth mentioning.

    You can find nginx rewrites in _INSTALL/nginx_config.txt file in your installation archive.

     
  8. In 3.9.2 we have updated categories and tags auto-selection plugins to allow lenient mode for compound tags of categories. In lenient mode the compound expression will be tested for match of its each component word instead of exact expression match.

     

    [ATTACH=JSON]{"data-align":"none","data-size":"full","title":"tags_autoselection.png","data-attachmentid":297}[/ATTACH]

     

    After some feedback we changed GUI for this implementation. It was noted that in many cases you will need lenient match only for specific expressions, while for the rest of compound expressions you will better not use it. Therefore we added ability to enable lenient match only for the specified expressions:

     

    tags_autoselection.thumb.png.987c1c5a15bfb70a9dafac95a32eaafc.png

  9. KVS serves and stores different types of static content, like video files, photo images, video screenshots, user avatars, theme design styles / scripts.

    For video files and album photos KVS supports multi-server architecture and this is completely another story described here. This topic describes how to move static to CDN or another server for the rest of static content.

     

    Theme design files

    These are typically files located under /static folder on your main server.

    In most cases you will need to move these design elements to CDN for faster load. You should do that manually following any guideline you have for CDN. Please note that you should also check with CDN guide / support about crossdomain security issues (for example fonts can be only loaded from another domain if they provide Access-Control-Allow-Origin "*" header and etc.)

    From KVS side you only need to adjust one option in /admin/include/setup.php file:

    $config['statics_url']="$config[project_url]";

    By default it points to the project URL, you should change it to your CDN:

    $config['statics_url']="//cdn.domain.com";

    It will force all design static files to be loaded from this domain.

    NOTE: If your project is running under HTTPS, you should use CDN which also supports HTTPS.

    In most cases CDN will cache files from your original server for some time (can be forever). If you do any changes in these files on your server, your site will still continue using old versions. You may need to reset your CDN cache so that it pulled new versions. Another option is to increment version of the modified file when it is linked from template (not sure if all CDNs support this). For example templates use this tag to include CSS style file:

    <link href="{{$config.statics_url}}/styles/all-responsive-white.css?v=5.0" rel="stylesheet" type="text/css"/>

    If this file is loaded from CDN and you modify it, you can increment its version so that CDN will update it from your server again. The actual numbers don't matter, it should be different from the old one:

    <link href="{{$config.statics_url}}/styles/all-responsive-white.css?v=5.0.1" rel="stylesheet" type="text/css"/>

     

    Video screenshots from CDN

    By default video screenshots are stored under this folder on your main server:

    /contents/videos_screenshots

    You can move them to CDN as well, however you should consider the problem of invalidation here. Screenshots can be changed from time to time in admin panel. For example if you create 20 screenshots per each video and then leave only 10 best screenshots, or if rotator automatically removes badly clickable screenshots, your CDN will still show the old ones incorrectly. There is no solution for this issue from KVS side, you should check with your CDN provider on which options are available. For example they can ping files from your server from time to time and check if they were changed or not. But if you don't commit any screenshots editing you will probably be fine with leaving this as it is, since in your case the files will unlikely be changed.

    In order to switch screenshots to CDN you should first configure CDN per their guidelines and then in /admin/include/setup.php file of your KVS installation you should modify this URL:

    $config['content_url_videos_screenshots']="$config[project_url]/contents/videos_screenshots";

    Please make sure to modify the correct option, as there are some similarly spelling options around. Your change should be something like:

    $config['content_url_videos_screenshots']="//cdn.domain.com/contents/videos_screenshots";

    NOTE: If your project is running under HTTPS, you should use CDN which also supports HTTPS.

    If you want to make screenshot loading even faster, you can define alternate URLs for screenshots via different subdomains. The reason is that browsers do have limits to the number of concurrent connections for a single server (~6 at the same time). If there are many screenshots on your page they will be loaded in portions, but you can make this happen in parallel by loading them from different subdomains. They should all be configured as aliases for the same server and should serve the same content. In order to do that there is another option in /admin/include/setup.php config file:

    $config['alt_urls_videos_screenshots']=array();

    You can list several alternate URLs there in the following format (make sure you retain the correct syntax or you may brake the code):

    $config['alt_urls_videos_screenshots']=array("//cdn2.domain.com/contents/videos_screenshots", "//cdn3.domain.com/contents/videos_screenshots");

    This will force KVS to randomly load screenshots from these 3 URLs:

    //cdn.domain.com/contents/videos_screenshots (configured as main URL)
    //cdn2.domain.com/contents/videos_screenshots (configured as alternate URL 1)
    //cdn3.domain.com/contents/videos_screenshots (configured as alternate URL 2)

     

    Video screenshots from another server but not CDN

    If you want to use another server for serving video screenshots, you have 2 options:

     

    Option 1. Use rsync to push updates in KVS /contents/videos_screenshots folder to another server. This should be configured by your server admins. In this case you need to modify screenshots URL (see Video screenshots from CDN section). However this approach is not recommended, because rsync works asynchronously with some delay, so the common problem is that for new videos the screenshots may not yet been synced to remote server. If you know the interval between each rsynс push, you can workaround this problem by configuring KVS to postpone new content for some time. You should then change this option in /admin/include/setup.php:

    $config['post_dates_offset']="0";

    It indicates the number of minutes all new content will be delayed. For example if rsync works every 1 hour you can configure it to be 70 or 80 minutes, to make sure that screenshots of new videos have been pushed to remote server in the moment when video appears on your site.

     

    Option 2. The second option is to move the whole screenshots storage folder to a remote server using network filesystem (NFS mount). This can be a good solution if remote server is located with the same datacenter for stability reason. You should ask your admins to create writable NFS mount to the remote server and move all existing content from /contents/videos_screenshots there. Then you should modify these 2 options in /admin/include/setup.php file:

    $config['content_path_videos_screenshots']="$config[project_path]/contents/videos_screenshots";
    ... there are some other options in between ...
    $config['content_url_videos_screenshots']="$config[project_url]/contents/videos_screenshots";

    The first option is a filesystem path and the second one is URL. Your changes should look like this:

    $config['content_path_videos_screenshots']="/mnt/server2/contents/videos_screenshots"; // should be a real path of the mounted folder
    ...
    $config['content_url_videos_screenshots']="//server2.domain.com/contents/videos_screenshots";

    NOTE: If your PHP is configured with open_basedir restriction you should also update it to include /mnt/server2 path, otherwise KVS will not be able to write new screenshots into the mounted folder. You can check if this folder is writable or not with KVS audit plugin.

    Using the 2nd approach is more preferred, as there won't be any delay in screenshots availability. But it needs stable connection between servers.

     

    Other static files

    Other static files are normally user avatars and images of categorization objects like categories, channels, models.

    You can use the same approach for them as for screenshots, either move them to CDN (see Video screenshots from CDN), or move to another server (see Video screenshots from another server but not CDN).

    The only difference is in what options you should change in /admin/include/setup.php. Here they are:

    $config['content_url_categories']="$config[project_url]/contents/categories";               // URL for categories
    $config['content_url_content_sources']="$config[project_url]/contents/content_sources";     // URL for content sources
    $config['content_url_models']="$config[project_url]/contents/models";                       // URL for models
    $config['content_url_dvds']="$config[project_url]/contents/dvds";                           // URL for channels / series / DVDs
    $config['content_url_posts']="$config[project_url]/contents/posts";                         // URL for posts
    $config['content_url_avatars']="$config[project_url]/contents/avatars";                     // URL for users
    $config['content_url_referers']="$config[project_url]/contents/referers";                   // URL for referers, not used in most cases
    $config['content_url_other']="$config[project_url]/contents/other";                         // URL for uncategorized static files

    By default these all point to your main server, you can switch them to CDN or another server in the same way.

  10. You should add an easy way to have Google reCaptcha to protect LOGIN / SIGNUP form.

     

    Thanks

     

    We will check that. We had the same issue with this KVS forum and using reCaptcha didn't help from spam registrations. Registrations can be done manually with easily completing reCaptcha manually, do you want to enable captcha on sending messages as well? Only this captcha can prevent from sending massive spam, but it will also bring inconvenience to normal users.

     

    There should be other solution like for example prevent from sending many similar messages, or messages with URLs, or require minimum 5 days account duration in order to be able to send messages. Probably the combination of these will give more effect.

     

  11. In 3.9.2 we have added a new option to video crop settings, which can be used to force crop for screenshots uploaded manually.

     

    Prior to that KVS never applied crop to the screenshots uploaded manually and this also included grabbers / feeds when importing embed codes or pseudo videos: the grabbed screenshots couldn't be cropped. Starting from 3.9.2 it be possible to enable this.

     

    crop_settings.thumb.png.c7397461ec873bab03bc5e765b158891.png

  12. KVS provides API to use youtube-dl server library for scrapping videos from other tube sites.

    You can implement your own grabber class in PHP language and upload it into KVS. Here is how this can be done. The example features fully working custom youtube grabber (KVS has built-in grabber for youtube by the way).

    NOTE: it is not strictly required to use youtube-dl API, it is also possible to create a completely custom grabber with your own code.

     

    Implementing grabber class using youtube-dl API

    Create CustomGrabberYoutube.php with the following code (also attached here as a text file):

    <?php
    
    // when you change classname, change it at the very bottom as well in this line:
    // $grabber = new CustomGrabberYoutube();
    class CustomGrabberYoutube extends KvsGrabberVideoYDL
    {
       // ===============================================================================================================
       // infrastructure methods
       // ===============================================================================================================
    
       public function get_grabber_id()
       {
           //prefix your grabber ID with "custom_"
           return "custom_videos_youtube";
       }
    
       public function get_grabber_name()
       {
           // name displayed in admin panel
           return "youtube.com";
       }
    
       public function get_grabber_version()
       {
           // this is required for grabbers that are autoupdated from KVS
           return "1";
       }
    
       public function get_grabber_domain()
       {
           // domain name, KVS will check this to find out if this grabber is suitable for the given URL
           return "youtube.com";
       }
    
       public function get_supported_url_patterns()
       {
           // returns list of regexp patterns that describe video URLs, for youtube this pattern will match
           // https://www.youtube.com/watch?v=htOroIbxiFY
           return array("/https?:\/\/(www\.)?youtube\.com\/watch.*/i");
       }
    
       public function can_grab_description()
       {
           // return true if your grabber is going to provide description for each video
           return false;
       }
    
       public function can_grab_categories()
       {
           // return true if your grabber is going to provide categories for each video
           return false;
       }
    
       public function can_grab_tags()
       {
           // return true if your grabber is going to provide tags for each video
           return false;
       }
    
       public function can_grab_models()
       {
           // return true if your grabber is going to provide models for each video
           return false;
       }
    
       public function can_grab_content_source()
       {
           // return true if your grabber is going to provide content source for each video
           return false;
       }
    
       public function can_grab_date()
       {
           // return true if your grabber is going to provide date for each video
           return false;
       }
    
       public function can_grab_rating()
       {
           // return true if your grabber is going to provide rating for each video
           return false;
       }
    
       public function can_grab_views()
       {
           // return true if your grabber is going to provide views for each video
           return false;
       }
    
    
       public function can_grab_video_files()
       {
           // this should be true for youtube-dl
           return true;
       }
    
       public function get_supported_qualities()
       {
           // list of supported video qualities, should match what youtube-dl returns in its info under formats
           // run this command:
           // youtube-dl --dump-json https://www.youtube.com/watch?v=PhDXRCLsqz4 >> test.json
           // and open test.json in Firefox, find "formats" array and look into the available formats
           // youtube has too many formats, KVS only supports formats with "ext"="mp4"
           // you can list them here and you will be able to select from them in grabber settings
           return array('360p', '720p');
       }
    
       public function get_downloadable_video_format()
       {
           // for youtube-dl grabber KVS only supports mp4 formats
           return 'mp4';
       }
    
       public function can_grab_lists()
       {
           // return true if you want to allow this grabber to grab lists and thus be used on autopilot
           // if true, you will also need to implement grab_list() method - see below
           return false;
       }
    
       // ===============================================================================================================
       // parsing methods - modify if you need to parse lists or add additional info
       // ===============================================================================================================
    
       public function grab_list($list_url, $limit)
       {
           // this method is used to grab lists of videos from the given list URL
           // $limit parameter means the number of videos to grab (including pagination)
           // if $limit == 0, then you just need to find all videos on the given URL, no need to care about pagination
    
           $result = new KvsGrabberListResult();
    
           // $page_content here is the HTML code of the given page
           $page_content = $this->load_page($list_url);
    
           // parse $page_content and add all video URLs to the result
           // consider pagination if needed
           // you can use $this->load_page($list_url) method to get HTML from any URL
           $result->add_content_page("https://youtube.com/video1");
           $result->add_content_page("https://youtube.com/video2");
           $result->add_content_page("https://youtube.com/video3");
    
           return $result;
       }
    
       protected function grab_video_data_impl($page_url, $tmp_dir)
       {
           // by default the base class will populate these fields (if provided by youtube-dl):
           // - title
           // - MP4 video files for the qualities listed in get_supported_qualities() function
           // - description (should be enabled in can_grab_description() function)
           // - date (should be enabled in can_grab_date() function)
           // - tags (should be enabled in can_grab_tags() function)
           // - categories (should be enabled in can_grab_categories() function)
    
           $result = parent::grab_video_data_impl($page_url, $tmp_dir);
           if ($result->get_error_code() > 0)
           {
               return $result;
           }
    
           // do any custom grabbing here for additional fields, which are not supported by youtube-dl
           // $page_content here is the HTML code of the given video page
           //$page_content = $this->load_page($page_url);
    
           // parse HTML code and set additional data into $result, e.g. data which is not provided by youtube-dl
           //$result->set_rating(85);
           //$result->set_votes(10);
           //$result->set_views(123874);
           //$result->set_content_source("Content Source Name");
           //$result->add_model("Model 1");
           //$result->add_model("Model 2");
    
           return $result;
       }
    }
    
    $grabber = new CustomGrabberYoutube();
    KvsGrabberFactory::register_grabber_class(get_class($grabber));
    return $grabber;

    The code has comments where needed. Basically youtube-dl provides main video info, such as title, description, tags, categories, date and files. If this is enough for you, you should only modify set of methods on top grouped under infrastructure methods section. These methods are designed to integrate grabber into KVS, so you should change them as described.

    You should also modify grabber class name in 2 places (top and bottom) and make sure that grabber class name is unique and has Custom in its name (to avoid intersections with any future grabbers we will add).

    If you want to implement parsing lists or add additional info, you should modify parsing methods as explained in the code.

     

    Implementing grabber class without youtube-dl

    Here is example grabber class that is not using youtube-dl. Put your custom parsing logic:

    <?php
    
    // when you change classname, change it at the very bottom as well in this line:
    // $grabber = new CustomGrabberYoutube();
    class CustomGrabberYoutube extends KvsGrabberVideo
    {
       // ===============================================================================================================
       // infrastructure methods
       // ===============================================================================================================
    
       public function get_grabber_id()
       {
           //prefix your grabber ID with "custom_"
           return "custom_videos_youtube";
       }
    
       public function get_grabber_name()
       {
           // name displayed in admin panel
           return "youtube.com";
       }
    
       public function get_grabber_version()
       {
           // this is required for grabbers that are autoupdated from KVS
           return "1";
       }
    
       public function get_grabber_domain()
       {
           // domain name, KVS will check this to find out if this grabber is suitable for the given URL
           return "youtube.com";
       }
    
       public function get_supported_url_patterns()
       {
           // returns list of regexp patterns that describe video URLs, for youtube this pattern will match
           // https://www.youtube.com/watch?v=htOroIbxiFY
           return array("/https?:\/\/(www\.)?youtube\.com\/watch.*/i");
       }
    
       public function can_grab_description()
       {
           // return true if your grabber is going to provide description for each video
           return true;
       }
    
       public function can_grab_categories()
       {
           // return true if your grabber is going to provide categories for each video
           return true;
       }
    
       public function can_grab_tags()
       {
           // return true if your grabber is going to provide tags for each video
           return true;
       }
    
       public function can_grab_models()
       {
           // return true if your grabber is going to provide models for each video
           return true;
       }
    
       public function can_grab_content_source()
       {
           // return true if your grabber is going to provide content source for each video
           return true;
       }
    
       public function can_grab_date()
       {
           // return true if your grabber is going to provide date for each video
           return true;
       }
    
       public function can_grab_rating()
       {
           // return true if your grabber is going to provide rating for each video
           return true;
       }
    
       public function can_grab_views()
       {
           // return true if your grabber is going to provide views for each video
           return true;
       }
    
       public function can_grab_video_files()
       {
           // return true if your grabber is going to provide video files for each video
           return true;
       }
    
       public function can_grab_video_embed()
       {
           // return true if your grabber is going to provide embed code for each video
           return true;
       }
    
       public function can_grab_video_duration()
       {
           // return true if your grabber is going to provide duration for each video
           return true;
       }
    
       public function can_grab_video_screenshot()
       {
           // return true if your grabber is going to provide screenshot for each video
          return true;
       }
    
       public function get_supported_qualities()
       {
           // list of supported video qualities that your grabber provides
           return array('360p', '720p');
       }
    
       public function get_downloadable_video_format()
       {
           // only grabbers that return MP4 files are supported
           return 'mp4';
       }
    
       public function can_grab_lists()
       {
           // return true if you want to allow this grabber to grab lists and thus be used on autopilot
           // if true, you will also need to implement grab_list() method - see below
           return false;
       }
    
       // ===============================================================================================================
       // parsing methods
       // ===============================================================================================================
    
       public function grab_list($list_url, $limit)
       {
           // this method is used to grab lists of videos from the given list URL
           // $limit parameter means the number of videos to grab (including pagination)
           // if $limit == 0, then you just need to find all videos on the given URL, no need to care about pagination
    
           $result = new KvsGrabberListResult();
    
           // $page_content here is the HTML code of the given page
           $page_content = $this->load_page($list_url);
    
           // parse $page_content and add all video URLs to the result
           // consider pagination if needed
           // you can use $this->load_page($list_url) method to get HTML from any URL
           $result->add_content_page("https://youtube.com/video1");
           $result->add_content_page("https://youtube.com/video2");
           $result->add_content_page("https://youtube.com/video3");
    
           return $result;
       }
    
       protected function grab_video_data_impl($page_url, $tmp_dir)
       {
           $result = new KvsGrabberVideoInfo();
    
           // $page_code here is the HTML code of the given video page
           $page_code = $this->load_page($page_url);
           if (!$page_code)
           {
               $result->log_error(KvsGrabberVideoInfo::ERROR_CODE_PAGE_UNAVAILABLE, "Page can't be loaded: $page_url");
               return $result;
           }
    
           // parse HTML code and set data into $result
           // replace with your parsing logic
    
           $result->set_canonical($page_url);
           $result->set_title("Demo title");
           $result->set_description("Demo description long description long description long description long description.");
    
           $result->set_screenshot("http://www.localhost.com/test/test.jpg");
           $result->set_duration(30);
           $result->set_date(time());
    
           $result->set_views(1526);
           $result->set_rating(87);
           $result->set_votes(11);
    
           $result->set_embed("<div>embed code</div>");
    
           $result->add_category("Category 1");
           $result->add_category("Category 2");
           $result->add_category("Category 3");
    
           $result->add_tag("Tag 1");
           $result->add_tag("Tag 2");
           $result->add_tag("Tag 3");
    
           $result->add_model("Model 1");
           $result->add_model("Model 2");
           $result->add_model("Model 3");
    
           $result->set_content_source("Content Source 1");
    
           $result->add_video_file("360p", "http://www.localhost.com/test/test_360p.mp4");
           $result->add_video_file("720p", "http://www.localhost.com/test/test_720p.mp4");
    
           $result->add_custom_field(1, "Custom1");
           $result->add_custom_field(3, "Custom3");
    
           return $result;
       }
    }
    
    $grabber = new CustomGrabberYoutube();
    KvsGrabberFactory::register_grabber_class(get_class($grabber));
    return $grabber;

     

    Testing grabber class

    Put grabber class file to your project root folder. Also create test_grabber.php file in the same folder with the following code:

    <?php
    
    header('Content-Type: text/plain; charset=utf8');
    ini_set('display_errors', 1);
    error_reporting(E_ERROR | E_PARSE | E_COMPILE_ERROR);
    
    require_once('admin/plugins/grabbers/classes/KvsGrabber.php');
    
    $grabber = require_once('CustomGrabberYoutube.php');
    $grabber->init(new KvsGrabberSettings(), "");
    if ($grabber instanceof KvsGrabberVideoYDL)
    {
       $grabber->set_ydl_path('/usr/bin/yt-dlp'); // make sure this path is correct in your system
    }
    print_r($grabber->grab_video_data('https://www.youtube.com/watch?v=htOroIbxiFY', 'tmp'));

    Modify this code to your class name and specify your demo URL.

    Then run via browser:

    http://domain.com/test_grabber.php

    If everything is fine, you should see dumped info from the scrapped video.

     

    Installing grabber into KVS

    Just go to Plugins -> Grabbers in admin panel and upload your grabber class into Custom grabber field. Then after saving the form you will see your grabber installed marked with red color. You need to open this grabber settings and select Content mode = Download. Also enable the needed fields under Data.

    NOTE: If you don't see any fields under Data, then your grabber class doesn't return true from can_grab_xxx() methods.

    If you want to update grabber class, simply upload it again. It is recommended to increment version in get_grabber_version() method to stay sure on which version KVS is using.

     

    Finding the list of supported video files to grab

    If you don't know which formats source site provides (usually a subset of: 240p, 360p, 480p, 720p, 1080p), you can check that from youtube-dl:

    youtube-dl --dump-json https://www.youtube.com/watch?v=PhDXRCLsqz4 >> test.json

    This should generate test.json file which can be open in firefox to show JSON structure.

    Find a node called formats, it should be a list with items describing each supported format.

    KVS can only import formats with ext = mp4, you can list them in get_supported_qualities() method using XXXp notation, e.g. 360p, 720p.

    Here is sample screenshot for youtube:

    youtube_dl_formats.png.e903bb9f4ba9692a6936073621b607db.png

    CustomGrabberYoutube.txt

  13. We added one small feature post factum to the 3.9.1.

     

    In admin panel if needed you can now show your custom HTML code in header black bar, main menu, on top of main area and at the bottom of main area. This can be used for example to supply any specific instructions to your employees. Here is an example a custom text displayed on video adding / editing:

     

    custom_ap_add.thumb.png.5f9d52330b6269aca4c132c453d257d0.png

     

    custom_ap_change.thumb.png.cffeafd1561858a331f942d7fc39c001.png

     

    In order to add these customizations you can create the following template files:

    /admin/template/ap_custom_header.tpl
    /admin/template/ap_custom_menu.tpl
    /admin/template/ap_custom_main.tpl
    /admin/template/ap_custom_footer.tpl
    

     

    These files won't be modified by any future update, so provide safe way to inject some customization in admin panel.

     

    For the above example here is sample code used. It affects only videos section:

    {{if $page_name=='videos.php'}}
       {{if $smarty.get.action=='add_new'}}
           <div style="padding: 10px;">
               This is a custom instruction for adding videos
           </div>
       {{elseif $smarty.get.action=='change'}}
           <div style="padding: 10px;">
               This is a custom instruction for modifying videos
           </div>
       {{/if}}
    {{/if}}
    

  14. Forget cron. No exceptions. Every outgoing mail must go through an ESP API. The SMTP server is not available to kvs. There is no other way to send mail.

    Outgoing mail is sent from a different server.

     

    All that matters is that you have one point where it can be intercepted, and all the necessary data is on hand at that point. For all outgoing email.

     

    Hope that is clear.

     

    Not clear yet... Not sure how is cron related to the way of sending emails.

     

    The reason for using cron emailing is the following. If you want to notify users about new private messages or new comments posted to their content, it makes no sense to do that immediately after the message was sent or after a comment was written. The reason is: there can be many of such messages or comments. I think it is not a good idea to send a separate email for each new message or comment. Instead it will make more sense to send something like:

    - You have 10 new private messages

    - You have 20 comments posted on your videos

    - You have 30 purchases of your content today (if user is configured to be paid in tokens)

    and etc.

     

    For such notifications we will need to collect them in database and to be grouped together, so that they are sent once a day or other period.

     

    With regard to API for sending emails, I was thinking that using phpmailer + external email service like google is kind of standard for small businesses. Is there any other way? What do you mean by ESP API?

  15. The choice of where you put the hook and how much information is provided can make the transition easy or difficult. We will never go back to SMTP on our own servers.

     

    Thanks for noting this. We are planning of cause use cron solution to send emails, except for immediate needs (signup and so on). We are planning to allow multiple sending options, e.g. sendmail (the currently used), phpmailer and we can also include custom script into this list, which will be called by KVS in case of need to send email.

     

    Please do not lock us into a proprietary kvs-only templating system for emails.

     

    Not sure I understand this point, but we will definitely not support any other templating than smarty. An email is HTML format, and any service which sells email templates, it sells in HTML format, correct? So any HTML code can be a valid template for smarty. But for example if you want to send emails with updates you will have to use KVS list_videos / list_albums blocks to render content, this is where you can use smarty functionality. I'm not sure however how we will technically implement this for now. Most probably we will have to stick to Website UI section, so that each such template should be added as a site page first and then it can be selected as a mail template. Since we already have the needed rendering engine we will reuse it for faster development.

     

  16. Update status

     

    3.9.1 update status is PRODUCTION. It means that the update was tested on many projects and projects with huge traffic.

     

    You can download 3.9.1 update for your project(s) in KVS customer zone

     

    Update cost

     

    3.9.1 update is free for all KVS installations using 3.x branch.

     

    If you want our team to update your project for you, please purchase this update service:

    http://www.kernel-video-sharing.com/en/services/#update

     

    Update important info

     

    Update will NOT affect your theme or any customizations in theme design (styles, templates, texts). Your site will be looking the same as it was before the update.

     

    Since player skins are considered as part of KVS system files, they will be updated. If you have any custom changes in existing player skins you will lose them. If you have created any custom player skins, they will not be affected, but it is highly recommended to update them from the original player skins, since there are some bugs fixed in skins and also your custom skin won't work correctly with the new player functionality.

     

    Important! Starting from KVS 3.9.1 each update will also update remote_cron.php files on all conversion servers automatically (previously this was only done for default local conversion server). If you did any customizations in this file you will lose them.

     

    Update procedure

     

    Any project starting from 3.0.0 can be updated to 3.9.1 with one only procedure. Depending on your current KVS version update procedure may contain additional steps for older versions.

     

    You must use KVS update plugin in order to update your project. For update you will need:

     

    - KVS update ZIP archive for your project and its hash code for update plugin (contact support in beta phase to get these).

    - FTP connection to your project so that you can upload files.

     

    If your project's version is 3.9.0, the update procedure is standard and nothing special is expected:

    • Create backup using Backup plugin.
    • Upload update ZIP into KVS update plugin and specify hash code.
    • KVS update plugin will notify you if there are any custom changes in KVS system files, which will be overridden by update (player skins are not checked here, so they will be silently updated if have custom changes).
    • KVS update plugin will update database automatically.
    • You will need to copy files from the archive on top of your project using FTP or filesystem copy.
    • KVS update plugin will verify the updated files and finalize update procedure.
    • You can use System audit plugin to verify everything looks good.

     

    If your project's version is before 3.9.0, the update procedure will be difficult and will include cache reset for the whole site (if you have much traffic it can make your project to be unavailable for some time). Also 3.9.0 update can have issues with displaying the new player if conflicting with your design styles, please check this post listing all issues:

    http://www.kernel-video-sharing.com/...-0?p=48#post48

     

    What's new in 3.9.1

     

    You can find explanations and screenshots for the most of new features in this topic:

    http://www.kernel-video-sharing.com/...implementation

     

    This topic also contains guides on how to enable some new features that require template changes and thus are not covered by automatic update.

     

    You can see some new features in action on KVS demo website and admin panel:

    http://kvs-demo.com

    http://kvs-demo.com/admin/

     

    1) Player improvements and bugfixes:

    • Better skin for touch devices and devices with small screen: some buttons are hidden, size of other buttons increased.
    • Added new player skin in youtube style.
    • For iOS devices player now supports metadata preload, which will allow faster video start (if you enabled the needed option in player settings and device supports this).
    • Text cue points can now be set up for timeline screenshots in video screenshots editor. Such cue points will be highlighted on player timeline and texts will be shown together with screenshots. Excellent feature to highlight video key scenes.
    • In pre-roll and post-roll advertising settings you can now enable built-in skip button and configure when it will become active. Also GUI of such advertising was changed - you can now show message with displaying advertising duration, and for video ads users can now pause and mute them.
    • Replay icon was added as a replacement for standard play button on video ending.
    • In player settings you can now specify initial player volume (and also mute player by default if needed). Also we've fixed some bugs with volume slider behavior.
    • In player settings you can now configure automatic loop for short videos - you can specify the minimum duration for that.
    • Some poster display issues fixed: earlier poster was not displayed before player fully initialized; also it was displayed without no need if autoplay was enabled.
    • Fixed context menu issue when trying to copy embed code from the player.
    • Fixed number of issues with timeline screenshots display: their size was limited and also they could be positioned incorrectly if skin was customized.
    • Display of vertical videos fixed - now they won't stretch vertically.
    • Fixed issue with caching remote servers redirects by some user agents. The new player will only allow cache them for 1 hour.

    2) We re-thinked IP limit blocking mechanism in video protection. Since we've added video file link obfuscation feature

    in 3.9.0 player, IP limit makes no much sense anymore. Now it can be switched off and will ease disk utilization. Also

    it doesn't count skipping anymore, so protection doesn't rely on how often user skips video. ATTENTION! After updating

    to 3.9.1 IP limit will be automatically switched off. You should switch it on manually in video protection settings if

    you still need this (for example if you are using 3rd party video player).

     

    3) Grabbers and content import improvements:

    • Added support for importing videos with multiple qualities via grabbers for those source sites that support it. This can save your CPU resources on conversion, but will take more time to import new content by downloading multiple files.
    • Grabbers can not import content source field for each object individually. This is not used in the grabbers KVS provides, but can be used in your custom grabbers.
    • You can now skip content with duplicate titles when importing content from grabbers.
    • You can now limit description length in grabbers: either by certain number words or by symbols.
    • For some grabbers KVS can now use their delete feeds to auto-delete videos from your database. This should be enabled separately for each grabber where supported.
    • When importing embed codes or pseudo-videos from grabbers, you can now specify URL postfix with your ref code to make URLs of all embed codes / pseudo-videos have it.
    • KVS grabbers plugin will now support youtube-dl server library, which implements parsing for many tube sites. This will help us to add grabbers faster in future.
    • Import functionality was enhanced with ability to skip content which files failed to be downloaded for whatever reason. Earlier such content would be imported in KVS and then would be moved to error status during conversion phase. This didn't allow try importing it once again because of duplicates check.

    4) In timeline screenshots settings you can now configure the desired number of screenshots instead of their interval.

    Based on that the interval can vary depending on video duration. On the one hand this will make navigation in video not

    so accurate, on the other hand this will prevent creating 200-500 images for long videos. The key aspect here is that

    interval will never be less than 10 seconds and any other intervals will be divisible by 10. For example if you

    configure the number of timelines to be 100, for short videos KVS will create timelines with 10 seconds interval -

    their number will depend on video duration. For videos longer than 10*100=1000 seconds KVS will choose 20 seconds

    interval and etc. If you already use timeline screenshots you can easily switch to the new approach in video format

    settings, this will affect new videos and old videos will continue showing timelines using the old way.

     

    5) Due to the changes in timelines creation logic and for supporting future changes in this area, starting from 3.9.1

    KVS will automatically update API for all conversion servers during update procedure. You should understand here that

    any custom changes you've put into remote_cron.php will be vanished. KVS will try to do a backup copy of this file and

    to put it near by. Conversion engine will not use conversion servers with obsolete API version anymore.

     

    6) Added integration with MPA3 script.

     

    7) The execution order of background tasks was changed a bit. Earlier when you had many secondary background tasks,

    the new content wouldn't be processed until other tasks are completed or until you manually increase priority for new

    content tasks. This won't be needed anymore, since KVS will automatically put new content tasks in the front of

    execution queue even if all tasks have the same priority. Moreover you can now configure default priority for content

    tasks submitted by different types of users: standard, trusted, premium, webmasters. Also you can now manually increase

    conversion priority for videos and albums from their listings - earlier this was only possible from the tasks listing.

     

    8) Finally we've added ability to mark content as removed. You can now do that for any set of videos / albums and

    specify the reason. All files of this content will be deleted including video files, screenshots and formats, but the

    data will remain in database. This content will disappear from public lists and will only remain available via direct

    URLs with displaying all the info, comments and delete reason. For correct rendering you should modify templates,

    please check our forum for instructions.

     

    9) User account generation plugin added in 3.9.0 can now generate access codes instead of user accounts. Access codes

    can be used on sign up and upgrade flows to get tokens or premium level. You can sell these codes via external online

    shops as an alternative to KVS billing solution. Access codes are more convenient than pre-generated accounts, since

    they can be used by existing users while keeping existing profiles, also users can use multiple access codes for

    refills / rebills.

     

    10) For hotlinked videos it is now possible to re-create screenshots. In order to do that KVS will download hotlinked

    video again to create screenshots.

     

    11) It is now possible to award users with tokens for sending traffic to their videos or albums to your site (embed

    codes do not support this). You can specify the number of tokens that should be awarded for each N unique views (only

    IPs unique within 24 hours are counted here). When calculating awards KVS will pay tokens for those videos and albums

    that get the needed number of views. You can use this functionality to get more external links to your project if your

    users will be interested in earning tokens. If needed you can pay out tokens with real money using KVS payout solution.

     

    12) KVS 3.9.1 provides new features in restricting access to videos and albums. It is now possible to configure access

    level for public videos and albums (previously you could only do that for private and premium). Also you can now

    configure access level for each video or album individually, which will override access level inherited from type

    field. This new feature can be used to workaround KVS architecture issue that doesn't allow changing video from public

    to premium type and vice versa. Now if you want to make any public video available for premium members only or by

    tokens purchase, you can do that without changing its type.

     

    13) Enhanced rendering of screenshots and album photos in admin panel, they will be adaptive now. Also added red

    highlights for fields which triggered validation errors when saving editors.

     

    14) In main video editor you can now delete screenshots as well if they are enabled for display there. Previously you

    could only change main screenshot.

     

    15) Set of import / export enhancements and bugfixes:

    • You can now filter export data by reviewed flag.
    • You can now export video source files for those videos that keep them.
    • It is now possible to export rating in percents (0-100%) and also import / export will support the number of votes for rating.
    • Fixed bug with importing / exporting models with commas in their names.
    • Fixed bug with incorrect sorting by rating.
    • Optimized memory usage in export.
    • Exporting feeds now support filtering by query string. In order to allow this feature you should enable it in feed settings, since it can affect database performance if frequently used.
    • Fixed a bug in exporting feeds which could lead to wrong size in embed codes for some types of videos.

    16) Model auto-selection plugin will now be looking into content tags as well. Previously it was only looking into

    title and description.

     

    17) You can now sort models manually like categories in order to force specific sorting when displaying on site.

     

    18) In models list block (list_models) it is now possible to display similar models using a big variety of criteria:

    by country, by city, by age, by sex, by height, by weight, by eye or hair color and so on.

     

    19) In video upload block (video_edit) you can now configure that uploaded files are considered as files of specific

    format to skip their conversion. This feature is not need in most cases, it was implemented for specific requirements

    when your project is designed to provide an upload gateway for known users who will correctly upload files in the

    needed format. This can also be used to create a separate upload page for webmasters to allow them upload videos faster

    without the need to process them.

     

    20) In video, album and playlist editing blocks (video_edit, album_edit, playlist_edit) the new option added that

    allows you to configure content deactivation after it was modified. In older KVS versions there was only one option

    (force_inactive) that affected both new content and modified content. If it was enabled, any modified video or album

    would become deactivated until you manually activate it back. Now this won't happen. After the update the new option

    (force_inactive_on_edit) will be switched off, so any modified content will remain active. If you want to force the old

    behavior, you should modify settings of these blocks and switch the new option on.

     

    21) In global stats block (global_stats) you can now render how many people visited your site yesterday, last week and

    last month from KVS stats.

     

    22) Flagging content will now store additional info about initiator: IP, country, user agent and page URL.

     

    23) On conversations list (mode_conversations mode in list_members block) you can now implement removal functionality

    to completely delete multiple conversations. Also for each conversation in the list it is now possible to display last

    message from it.

     

    24) It is now possible to display video duration in standard format HH:MM:SS. Historically KVS displayed it in MM:SS

    format, which could show 3 digit number for long videos: MMM:SS. In order to use the new format you should modify site

    templates, which is described on KVS forum.

     

    25) Bugs that have been fixed:

    • During content import there could be a case when all import lines triggered validation errors, so even in that case KVS would allow submitting this import with empty list of valid lines.
    • Redirecting to random video / album didn't consider some satellite settings.
    • Non critical XSS vulnerability when using dynamic HTTP parameters from site settings.
    • When detecting SAR of source video file in some cases KVS would absolutely redundantly reconvert it for normalization. This was fixed, as well as normalization method was optimized for faster time and avoid quality loss.
    • Search function could lead to empty search if using stop words (in case of searching for the whole stop word) and KVS would show all videos / albums for such empty search.
    • Some cURL operations worked incorrectly if open_basedir option was enabled in PHP configuration.

     

×
×
  • Create New...