Jump to content

Tech Support

Administrators
  • Posts

    1,792
  • Joined

  • Days Won

    335

Everything posted by Tech Support

  1. Please submit a support ticket for this and specify your project domain, so that we have a look.
  2. Yes, you can duplicate [system] Sitemap page into another page using Duplicate option in Website UI pages list. You can change video info rendering to be whatever yandex expects and you will have another sitemap for yandex.
  3. 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?
  4. Not sure I understand what you mean...
  5. 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
  6. 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
  7. 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: 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: 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: 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: 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.
  8. 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: 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: 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}}
  9. 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.
  10. 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.
  11. 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:
  12. 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.
  13. 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.
  14. 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.
  15. I think youtube-dl is a public library and it has its own installation instructions, no need to duplicate it here since it may change with new releases.
  16. We posted instruction on how to create custom grabbers based on youtube-dl: http://www.kernel-video-sharing.com/forum/forum/educational-support/educational-series/302-how-to-create-custom-tube-video-grabber-for-kvs
  17. 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: CustomGrabberYoutube.txt
  18. Thanks for the info! We will consider this when re-designing email area.
  19. You should enable var_category_group_dir parameter in list_categories block, which allows filtering them by category group directory: http://kvs-demo.com/admin/project_pages.php?action=change_block&item_id=categories_videos||list_categories||categories_list&item_name=Categories%20List And then you can simply filter categories using such URLs: http://www.kvs-demo.com/categories/?group=group-1 http://www.kvs-demo.com/categories/?group=group-2
  20. 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.
  21. 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: 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}}
  22. 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?
  23. 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. 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.
  24. This is of cause not 100% YT player copy. But very similar, specifically the controlbar.
  25. Yes, but we don't have generic grabber yet. For now we have only added beeg.com which uses this.
×
×
  • Create New...