Jump to content

Search the Community

Showing results for tags 'howto'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • General Discussion
    • Announcements
    • Business Discussion
    • Business Services
    • Sell and Buy
  • Themes & templates
    • KVS default theme
    • KVS paysite theme
  • Educational / support
    • Technical Support
    • FAQ
    • Educational Series

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


About Me

  1. Multiple conversion servers can be used only in KVS ultimate package. They will let you reduce CPU load on main server and make video conversion faster, but only to some point. It is a common misunderstanding to assume that the more conversion servers you add, the more videos can be converted for the same time. This is not always true. The overall conversion speed depends not only on the actual conversion (e.g. video encoding), but on many other factors as well. Please read more about KVS conversion engine here. Adding new conversion server in KVS System requirements for a conversion server in KVS: PHP 7.1+ IonCube Loader 10.2+ (not required if your have open source code option with your license) PHP Client URL Library (curl) PHP FTP PHP Image Processing and GD PHP.ini disable_functions should not contain "exec" FFmpeg 1.0+ with libx264, libavfilter and AAC codec (libfaac, libfdk_aac or native ffmpeg aac codec) ImageMagick You can add a content server in admin panel in Settings -> Conversion servers. For Maximum tasks option it is recommended to keep it in 5-10 interval. This option doesn't mean how many tasks are executed in parallel; instead it affects how many tasks are uploaded to this conversion server. High values for this option may result on overall conversion performance degradation. For Optimize content copying options we provided complete explanation in this post. The next set of options are related to server connection. KVS uses these settings to copy tasks to conversion servers. In most cases you will need to specify FTP connection details here. The most confusing option here can be FTP folder. In order to specify it correctly you should first login to your FTP using standard FTP client and see where you come into. It can be possible that your FTP is directly configured to the needed folder, but in most cases FTP will be configured into home folder of FTP user or www root folder. NOTE: conversion folder doesn't require any HTTP access to it. Therefore it can be ANY folder on your remote server, but it should be unique and should belong to only 1 conversion server in KVS. Here is an example configuration for a remote conversion server: Configuring cron on remote conversion server NOTE: on conversion server with local connection you don't need to add any cron schedule for it, it will be automatically executed by KVS engine. After conversion server is created in KVS and its connection is validated, KVS will copy remote_cron.php file into the specified remote folder. This file is needed to perform remote conversion tasks. In order for it to start working, you should put it on cron every minute using the following command (please note that you should specify the valid filesystem path to remote_cron.php script): php /path/to/remote_cron.php > /dev/null 2>&1 Once configured, this script will create several files in the same folder, which will mean that this command works fine. KVS will change status for this conversion server from Initializing to Active within 5 minutes. After switching to Active status this server will be utilized by KVS conversion engine and will start processing conversion tasks. Troubleshooting issues KVS will validate basic issues when you try to save server settings in admin panel. After you add server, KVS will validate it on background every 5 minutes to check if it operates successfully. Even if initially you didn't have any errors, new errors may appear later due to various factors. First, FTP connection or remote server configuration may be changed externally and some functionality will simply stop working. All issues found on background are immediately reported to KVS start page as they all are considered CRITICAL and may indicate that your remote server is not working correctly and conversion may be blocked. You should make sure to fix them ASAP. Errors from background checks are not very detailed and just indicate some set of issues. In order to get more details you should try to save server settings in admin panel. NOTE: if server reports an error and you have already fixed it, please give it 5 minutes to do re-check and verify this error is fixed. Until that, server may still show this error. This only applies for background checks on existing servers. When you save server settings in admin panel, all issues are validated right a way without any delay. If saving server in admin panel still shows validation errors, these errors are not yet fixed. Here is the list of errors you can get when saving server settings: - This connection folder is already used by another server. This issue means that you are trying to configure this server into a folder, which is already used by another storage or conversion server. You should never do this, each storage or conversion server in KVS should be configured into a separate folder on filesystem. - Unable to connect to host : post. KVS is not able to connect to the specified FTP host or port. If the entered data is valid, most probably your FTP is protected by firewall and you should make sure that your main server's IP is whitelisted. Also sometimes your FTP may be configured for using non standard FTP port, you should check this as well. - Unable to login with credentials provided. Either FTP username or password is not valid. - Put / get / chmod / delete operations failed, insufficient permissions possible. When validating server connection, KVS will try to put a test file to the server and then delete it. You will get this error if any of the mentioned operations failed, which probably indicates wrong FTP folder or FTP configuration issue. Try to log in to FTP manually using desktop FTP client and try to copy any file into the specified folder. Can you do this manually? Also this error can happen if /tmp folder on your main KVS installation does not exist or is not writable. In order to check that go to Plugins -> Audit and run installation check. It will show error for tmp folder if anything is wrong. - No PHP extension for FTP was found. Your remote server's PHP doesn't have support for FTP module and therefore it is not possible to enable allow this server to copy content to storage servers option for this server. - No PHP extension for CURL was found. Your remote server's PHP doesn't have support for CURL module and therefore it is not possible to enable allow this server to pull source files from primary server option for this server. - Conversion script not configured / not working on this server. - Conversion script is not working. - Conversion script executed more than 15 minutes ago. These errors indicate that your remote server either doesn't have a cron task to execute remote_cron.php script every minute, or executing this script results in critical PHP error. Please check if you have cron task set. If you have it, then try executing this command manually from command line to see its output (please note that you should specify the valid filesystem path to remote_cron.php script): php /path/to/remote_cron.php In some cases if your remote server has another timezone than your main server, KVS may think that its remote_cron.php script is not executed, while it does. Open conversion server settings in KVS admin panel and specify its timezone offset under Configuration. Save conversion server settings and give it 5 minutes to re-check and remove this error. - Some libraries are not configured correctly on this server. This error indicates that KVS was not able to locate ffmpeg / imagemagick executables on your remote server. First of all you should make sure that these libraries are installed on the server. If not - please install them. If the libraries are installed, then most probably their binaries are not located using standard paths. Open conversion server settings in KVS admin panel and specify the correct paths for libraries that were not detected correctly under Configuration. Save conversion server settings and give it 5 minutes to re-check and remove this error.
  2. There is no built-in functionality in KVS to require users verify their documents or selfie, but there is alternative way to use Posts functionality for that. Even posts don't allow users to upload files, so it will be required to ask users to upload their documents to their own cloud services and specify secure link to the uploaded file. Here is how to configure that. Creating post type for the task and configuring global block for the users Step 1. Please go to Posts -> Post types and create new post type with the following data: Title: any of your choice, e.g. Identity Confirmation External ID: identity_confirmation Post page URL pattern: 404.php?%ID% Step 2. Go to Website UI -> Global blocks and add block with the following parameters: Block name: Identity Confirmation Block type: post_edit Cache: 86400 (default value) After saving global blocks list you will notice Identity Confirmation block added to the end. Click to edit this block. Step 3. Set the following Template code for this block: {{query_kvs select="single" table="posts_types" where_external_id='identity_confirmation' assign='post_type'}} {{query_kvs select="list" table="posts" where_user_id=$smarty.session.user_id where_post_type_id=$post_type.post_type_id assign='post'}} {{if $async_submit_successful=='true'}} <div class="success" data-fancybox="refresh"> {{$lang.edit_profile.success_message_identity_confirmation_requested}} </div> {{else}} <strong class="popup-title">{{$lang.edit_profile.title_identity_confirmation}}</strong> <div class="popup-holder"> {{if count($post)>0}} <div class="success" data-fancybox="refresh"> {{$lang.edit_profile.success_message_identity_confirmation_requested}} </div> {{elseif $smarty.session.status_id==6}} <div class="success" data-fancybox="refresh"> {{$lang.edit_profile.success_message_identity_confirmed}} </div> {{else}} <form action="{{$lang.urls.identity_confirmation}}" data-form="ajax" method="post"> <div class="generic-error hidden"></div> <p> {{$lang.edit_profile.field_identity_confirmation|replace:"%site%":$lang.project_name|smarty:nodefaults}} </p> <div class="row"> <input type="text" name="content" class="textfield"/> <div class="field-error down"></div> </div> <div class="bottom"> {{if $use_captcha==1}} <label>{{$lang.common_forms.field_captcha_hint}}</label> <div class="captcha-control"> {{if $recaptcha_site_key!=''}} <div data-name="code"> <div data-recaptcha-key="{{$recaptcha_site_key}}" data-recaptcha-theme="{{if $lang.theme.style=='metal'}}dark{{else}}light{{/if}}"></div> <div class="field-error down"></div> </div> {{else}} <div class="image"> <img src="{{$lang.urls.captcha|replace:"%ID%":"signup"}}?rand={{$smarty.now}}" alt="{{$lang.common_forms.field_captcha_image}}"/> <label for="identity_confirmation_code" class="field-label required">{{$lang.common_forms.field_captcha}}</label> <input type="text" name="code" id="identity_confirmation_code" class="textfield" autocomplete="off"/> <div class="field-error up"></div> </div> {{/if}} </div> {{/if}} <input type="hidden" name="action" value="add_new_complete"/> <input type="hidden" name="title" value="Identity Confirmation"/> <input type="submit" class="submit" value="{{$lang.edit_profile.btn_request}}"/> </div> </form> {{/if}} </div> {{/if}} Under block parameters change the following: post_type (String): identity_confirmation duplicates_allowed (On/Off): switch ON optional_description (On/Off): switch ON optional_tags (On/Off): switch ON optional_categories (On/Off): switch ON use_captcha (On/Off): switch ON, if you want users to solve captcha puzzle Step 4. Go to Website UI -> Language files -> default and add the following texts at the end. Feel free to adjust as needed: memberzone.profile_member_action_identity_confirmation = Verify your account here. edit_profile.title_identity_confirmation = Account Verification edit_profile.field_identity_confirmation = Create a selfie of yourself holding an A4 sheet with our site name written by hand:<br/><br/><b>%site%</b><br/><br/>Then upload this image to a cloud of your choice (e.g. Google Docs) and send us link to the uploaded file: edit_profile.success_message_identity_confirmation_requested = Thank you! Your account confirmation request was successfully registered and will be reviewed by our team soon. edit_profile.success_message_identity_confirmed = Your account has already been confirmed. edit_profile.btn_request = Submit Request edit_video.warning_upload = Only verified accounts can upload videos. urls.identity_confirmation = /confirm-account/ Step 5. You need to edit .htaccess file that is located in www root with your FTP client, or any other File Manager that might be provided by your server panel. Add the following line (could be added in the beginning, or next to RewriteRule ^delete-profile/$): RewriteRule ^confirm-account/$ index.php?mode=async&function=get_block&block_id=post_edit_identity_confirmation&global=true [L,QSA] Changing upload block to allow upload only for verified users To be noted, it will be required to use webmaster status to manually control which users are allowed to upload. In member profile editor in admin panel you should manually change member status to webmaster as a result of account verification process. Step 6. In order to change video upload block behavior, please go to Website UI -> Theme settings and scroll down to Functionality options group. Click on Video Edit link there to open video upload block settings. In Template code, your first line should look like this: {{if $async_submit_successful=='true'}} If it has something else, your video edit template is modified and you will need to adjust the proposed code to your template changes. The proposed code is to replace this line with this block: {{if $smarty.session.status_id!=6}} <div class="headline"> <h2> {{$lang.edit_profile.title_identity_confirmation}} </h2> </div> <div class="box"> {{$lang.edit_video.warning_upload}} <a href="{{$lang.urls.identity_confirmation}}" data-fancybox="ajax" style="text-decoration: underline; font-weight: bold">{{$lang.memberzone.profile_member_action_identity_confirmation}}</a> </div> {{elseif $async_submit_successful=='true'}} You may notice that we actually leave the old line almost there, with slightly changed from {{if}} to {{elseif}} syntax. This template change will hide video upload form for non-webmaster users and instead will show a link to verify their account: Step 7. However this may not stop bots, that could upload bypassing the actual site GUI, so you may need to add some small additional protection to make sure that bots can't upload as well. In the same video edit block settings activate the following parameters: max_duration (Integer): 1 max_duration_webmaster (Integer): 9999 These settings mean that all users will not be able to upload virtually any video, because of duration limit of 1 second. While webmaster users will be able to upload videos with duration up to 9999 seconds. So only webmaster users can actually upload videos. Testing all together Now log in with non-webmaster profile and go to upload page. You should see link to verify your account. If you see a white or partial page, you did wrong paste at step #6. You can go to Website UI -> Change history and look at your recent change to video edit block. There you can find original template version and return it back if needed, or check what you did wrong here. By clicking the account verification link you should see the popup to verify account. Submit something into the text field. This should show you success message that your data is submitted. If it shows any error, you did something wrong at step #3 with block parameters. If you go to admin panel start page, you may notice that it will show you alert like the following: Click this link and you will see Account Verification post submitted by you seconds ago. Open it and check the link under Content area. If you want to verify it, you first need to manually open user profile editor for this user and change their status to webmaster. Then approve this account verification post. If you want to reject it, you just need to delete it, so that user can re-submit again. Unfortunately KVS for now doesn't support any automated messages to be sent to users on different admin actions; if you want to notify user about some issue with their verification, you will need to manually submit a message to this user via Memberzone -> Messages.
  3. There are many sites which can be used to download videos from 3rd-party tube sites. For example this one: tubeninja.net KVS tube script comes with a fully-featured protection mechanism, which can do 3 things for your tube site: Prevent other users from downloading your videos via web tube downloaders. Prevent any other scripts from parsing and downloading your videos. Prevent other tube sites from hotlinking your videos and stealing your traffic. The settings are in Settings -> Content Settings under Video download script protection settings section: What you should do is to make sure that Enable protection for video download script is ON, Hotlink protection type is set to IP and Enable links obfuscation option is also switched ON. Link obfuscation will only work in KVS player. If you are using 3rd-party video player, then you cannot use this option. However, if your hotlink protection type is set to IP this will also prevent using web tube downloaders for your site. But your site will be vulnerable for other scripts to parse and download your content. If it is important for you to prevent that, you should use KVS video player and enable this option.
  4. In KVS there is no built-in support for country restrictions. The main reason is that KVS caching engine doesn't allow having these restrictions along with site caching, so for now we don't have any way to add this feature. However, if you discount caching aspect, it is possible to activate this feature with few theme adjustments. Disabling caching could have negative impact on your database load. But in this case you will only disable cache for video_view block, which is not the hardest block to be rendered. Step 1. First of all you need to switch off caching for the View Video page and video_view block on it. In order to do that go to Website UI -> Pages and search for video_view there. This will show you all pages that have this block (by default your theme will only have one page and block with caching time set to 3600 on both). Set caching time to 0 in both page and block fields (by default it will have 3600) and use Save caching option: Step 2. Go to Settings -> Customization and activate some custom text field in Videos. This will be the field where you need to list country codes of the countries where a specific video should be blocked. The format of the data is comma-separated list of 2-symbol country codes, for example like this: NOTE: the actual formatting doesn't matter, possible to specify in lower case, or without space between commas. Step 3. In Website UI -> Pages -> View Video page -> video_view block template find this fragment: {{if $data.status_id==5 || $data.status_id==2 || $data.status_id==3}} <div class="no-player" style="width: 100%; height: 0; padding-bottom: {{$player_size[1]/$player_size[0]*100|replace:",":"."}}%; background: black"> <span class="message">{{$data.delete_reason|default:$lang.videos.video_player_deleted}}</span> </div> {{elseif $is_limit_over==1}} .... Add the following block right before it: {{assign var="blocked_countries" value=","|explode:$data.custom1}} {{assign var="is_blocked_by_country" value="false"}} {{foreach from=$blocked_countries item="country_code"}} {{if $country_code|trim|strtolower==$smarty.server.GEOIP_COUNTRY_CODE|strtolower}} {{assign var="is_blocked_by_country" value="true"}} {{/if}} {{/foreach}} {{if $is_blocked_by_country=='true'}} <div class="no-player" style="width: 100%; height: 0; padding-bottom: {{$player_size[1]/$player_size[0]*100|replace:",":"."}}%; background: black"> <span class="message">This video is not available in your country</span> </div> and it order to make the smarty syntax complete you should changed {{if}} with {{elseif}} in the mentioned before block in the first line: {{elseif $data.status_id==5 || $data.status_id==2 || $data.status_id==3}} <div class="no-player" style="width: 100%; height: 0; padding-bottom: {{$player_size[1]/$player_size[0]*100|replace:",":"."}}%; background: black"> <span class="message">{{$data.delete_reason|default:$lang.videos.video_player_deleted}}</span> </div> {{elseif $is_limit_over==1}} .... IMPORTANT! If you fail to insert this block into the correct place, or to correct the IF -> ELSEIF logic, your template code may become broken and in this case it will stop rendering player. Then go to Website UI -> Change history to find the previous template version and restore it.
  5. This article provides step by step instruction on how to get categories dropdown in site header. Please note the CSS styles described here are not 100% perfect, as they in some way overlap with styles for upload item dropdown. Please adjust them as needed by your site design. Step 1. Go to Website UI -> Global blocks and click on Add block button at the bottom. In the new block line specify block name as Header Categories and under block type select list_categories. Save. Step 2. Open the newly appeared Header Categories block for editing. Configure block parameters as needed, e.g. items_per_page if you want to limit the number of categories displayed, and other filters if you want to limit which categories are displayed. Enter the following code into template code area and save: {{if count($data)>0}} <li class="drop"> <span>{{$lang.header.primary_menu_categories}}</span> <ul> {{foreach from=$data item="item"}} <li> <a href="{{$lang.urls.videos_by_category|replace:"%DIR%":$item.dir|replace:"%ID%":$item.category_id}}">{{$item.title}}</a> </li> {{/foreach}} </ul> </li> {{/if}} Step 3. Go to Website UI -> Page components -> include_header_general.tpl for editing. Find the <LI> node that renders categories menu item, similar to this: <li {{if $page_id=='categories_videos' || $page_id=='categories_albums'}}class="selected"{{/if}}> <a href="{{$lang.urls.categories_videos}}" id="item6">{{$lang.header.primary_menu_categories}}</a> </li> And replace it with this block insert: {{insert name="getGlobal" global_id="list_categories_header_categories"}} Step 4. To make styles look better, add the following basic styling into your theme CSS file: .navigation .primary .drop > span { display: block; position: relative; background-color: #e0dfdf; padding: 12px 38px 12px 17px; cursor: pointer; } .navigation .primary .drop > span:after { position: absolute; z-index: 1; content: "\e901"; font-family: "icomoon" !important; speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; font-size: 5px; top: calc(50% - 1px); right: 20px; will-change: transform; -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-transform: translateY(-50%) rotate(0); transform: translateY(-50%) rotate(0); -webkit-transition: -webkit-transform 0.3s; transition: -webkit-transform 0.3s; transition: transform 0.3s; transition: transform 0.3s, -webkit-transform 0.3s; } .navigation .primary .drop:hover > span { background-color: #276fdb; color: #fff; } .navigation .primary .drop:hover > span::after { -webkit-transform: translateY(-50%) rotate(180deg); transform: translateY(-50%) rotate(180deg); }
  6. KVS supports ability to sell subscriptions to individual profiles and channels. These subscriptions work using the internal token system and have the following features: A subscription can be for unlimited period, or for the given period of days. It is possible to specify only 1 period, which will affect all subscriptions of the same type (e.g. you can configure 1 period for subscription on profiles, and another period for subscription on channels). A subscription should be paid in tokens, so that users first need to purchase tokens using one of the supported and configured payment processor. Subscription means premium access to all videos uploaded by the given profiles or into the given channel. Subscription price can be set in admin panel for each profile / channel separately, or in site frontend in profile / channel editor (this field should be added into theme layout, not exist by default). So ultimately each member can have multiple paid channels with different prices, as well as separate price for the whole member's profile. If subscription is durable, at the end of subscription period KVS will try to deduct the needed amount of tokens from the user's account (e.g. rebill the subscription). If there will be no tokens on user's balance within 24 hours, the subscription will not be renewed. Unfortunately at the time of writing (5.5.1 KVS version) there is no support for sending emails, alerts to users at the moment with regard to this issue. Will be added in future. It is possible to configure that users who sell subscriptions to their profiles or channels will get some % of revenue in tokens paid by buyers. For simplicity this guide will consider the case when you activate only 1 type of subscription at a time: either channels or profiles. If you want to consider having both profile and channel subscriptions at a time, you will need more robust template coding to render video purchase forms correctly, because the same video can be accessed via channel subscription, or via profile subscription and thus 2 purchase options should be displayed. However the provided examples give the full code needed to create both cases and only minor IF / ELSE adjustments are needed. If you want to start using this feature you should first consider configuring a payment processor in Memberzone -> Billings. You need to choose a processor that supports tokens: SegPay, Paypal and Verotel at the moment + CoinPayments added in the new version already. For configuring them please create support ticket after you have your account approved at billing's side. Activating paid subscriptions in admin panel The very few and easy settings are located in Settings -> Memberzone Settings under Paid subscriptions section. You need to activate paid subscriptions for profiles and/or channels, set their default price as 0 and subscription duration as needed (leave empty for unlimited duration). In the next section you can also activate earning tokens from selling profiles and/or channels and specify your commission. Here is how the settings will look like for 30-day channel subscriptions with users earning 90% of all paid tokens (10% is your service fee): Adding fields for users to specify subscription price There could be 2 places where you may need to add this field based on whether you plan profile and/or channel subscriptions. For channels: Go to Website UI -> Language files -> default and add the following lines: edit_channel.field_tokens_required = Price in tokens edit_channel.field_tokens_required_hint = specify price for paid channels Then go to Website UI -> Global blocks -> Edit Channel Form and add the following code into the desired place to render token price field: <div class="row"> <label for="edit_channel_tokens_required" class="field-label">{{$lang.edit_channel.field_tokens_required}}</label> <input type="number" name="tokens_required" id="edit_channel_tokens_required" class="textfield" value="{{if $smarty.post.tokens_required>0}}{{$smarty.post.tokens_required}}{{/if}}" min="0" placeholder="{{$lang.edit_channel.field_tokens_required_hint}}" {{if $is_locked=='true'}}readonly{{/if}}/> <div class="field-error down"></div> </div> For profiles: Go to Website UI -> Language files -> default and add the following lines: edit_profile.field_tokens_required = Price in tokens edit_profile.field_tokens_required_hint = specify price for paid profiles Then go to Website UI -> Theme settings and under Profile options field find the active link (in some themes there could be several profile editing forms and only one of them is active). Then in the profile edit block settings add the following code into template where you want it to be displayed: <div class="row"> <label for="edit_profile_tokens_required" class="field-label">{{$lang.edit_profile.field_tokens_required}}</label> <input type="number" name="tokens_required" id="edit_profile_tokens_required" class="textfield" value="{{if $smarty.post.tokens_required>0}}{{$smarty.post.tokens_required}}{{/if}}" min="0" placeholder="{{$lang.edit_profile.field_tokens_required_hint}}" {{if $is_locked=='true'}}readonly{{/if}}/> <div class="field-error down"></div> </div> Closing access to videos in paid channels / from paid profiles Go to Website UI -> Language files -> default and add the following lines: videos.video_player_guest.channel = This video belongs to a premium channel %CHANNEL%. Only active members can watch videos from premium channels. <br/><br/> Please <a href="%LOGIN%" data-fancybox="ajax">log in</a> or <a href="%SIGNUP%" data-fancybox="ajax">sign up</a> for free. videos.video_player_tokens_not_enough.channel = This video belongs to a premium channel %CHANNEL%. To have access to videos in this channel you must spend <em>%TOKENS_COST%</em> tokens. <br/><br/> Your current tokens balance is <em>%TOKENS_AVAILABLE%</em> tokens. <br/> You need <em>%TOKENS_LEFT%</em> more tokens. videos.video_player_tokens_purchase.channel = This video belongs to a premium channel %CHANNEL%. To have access to videos in this channel you must spend <em>%TOKENS_COST%</em> tokens. <br/><br/> Your current tokens balance is <em>%TOKENS_AVAILABLE%</em> tokens. <br/> Please confirm spending <em>%TOKENS_COST%</em> tokens on this video. Now you need to modify video view block template in Website UI -> Pages -> View Video page -> Video View block. Locate the following line: {{elseif $data.can_watch==0}} and you need to add the following block RIGHT before this line. ATTENTION! This is the most complicated part, as you need to insert the fully copied code fragment into the specific part of Smarty template, failing to do correctly make break your video page. Please make sure you do a backup copy of original template code before you do any changes, just in case you need to restore it. For channels: {{elseif $data.dvd.tokens_required>0 && $data.dvd.is_purchased==0 && $data.user_id!=$smarty.session.user_id && $data.dvd.user_id!=$smarty.session.user_id}} <div class="no-player" style="width: 100%; height: 0; padding-bottom: {{$player_size[1]/$player_size[0]*100|replace:",":"."}}%"> <img src="{{$flashvars.preview_url}}" width="{{$player_size[0]}}" height="{{$player_size[1]}}" alt="{{$data.title}}"/> <span class="message"> {{if $smarty.session.user_id<1}} {{$lang.videos.video_player_guest.channel|replace:"%CHANNEL%":$data.dvd.title|smarty:nodefaults|replace:"%LOGIN%":$lang.urls.login|replace:"%SIGNUP%":$lang.urls.signup}} {{else}} {{if $smarty.session.tokens_available<$data.dvd.tokens_required}} {{assign var="tokens_left" value=$data.dvd.tokens_required-$smarty.session.tokens_available}} {{$lang.videos.video_player_tokens_not_enough.channel|replace:"%CHANNEL%":$data.dvd.title|replace:"%TOKENS_COST%":$data.dvd.tokens_required|replace:"%TOKENS_AVAILABLE%":$smarty.session.tokens_available|replace:"%TOKENS_LEFT%":$tokens_left|replace:"%UPGRADE%":$lang.urls.upgrade|smarty:nodefaults}} <form> <input type="button" class="submit" data-fancybox="ajax" data-href="{{$lang.urls.upgrade}}" value="{{$lang.videos.video_player_tokens_btn_buy|replace:"%TOKENS_COST%":$data.dvd.tokens_required|replace:"%TOKENS_AVAILABLE%":$smarty.session.tokens_available|replace:"%TOKENS_LEFT%":$tokens_left}}"> </form> {{else}} {{assign var="tokens_left" value=$smarty.session.tokens_available-$data.dvd.tokens_required}} {{$lang.videos.video_player_tokens_purchase.channel|replace:"%CHANNEL%":$data.dvd.title|replace:"%TOKENS_COST%":$data.dvd.tokens_required|replace:"%TOKENS_AVAILABLE%":$smarty.session.tokens_available|replace:"%TOKENS_LEFT%":$tokens_left|replace:"%UPGRADE%":$lang.urls.upgrade|smarty:nodefaults}} <form action="{{$data.canonical_url}}" method="post" data-form="ajax"> <div class="generic-error hidden"></div> <input type="hidden" name="action" value="subscribe"/> <input type="hidden" name="subscribe_dvd_id" value="{{$data.dvd.dvd_id}}"> <input type="submit" class="submit" value="{{$lang.videos.video_player_tokens_btn_spend|replace:"%TOKENS_COST%":$data.dvd.tokens_required|replace:"%TOKENS_AVAILABLE%":$smarty.session.tokens_available|replace:"%TOKENS_LEFT%":$tokens_left}}"> </form> {{/if}} {{/if}} </span> </div> For profiles: {{elseif $data.user.tokens_required>0 && $data.user.is_purchased==0 && $data.user_id!=$smarty.session.user_id}} <div class="no-player" style="width: 100%; height: 0; padding-bottom: {{$player_size[1]/$player_size[0]*100|replace:",":"."}}%"> <img src="{{$flashvars.preview_url}}" width="{{$player_size[0]}}" height="{{$player_size[1]}}" alt="{{$data.title}}"/> <span class="message"> {{if $smarty.session.user_id<1}} {{$lang.videos.video_player_guest.channel|replace:"%CHANNEL%":$data.username|smarty:nodefaults|replace:"%LOGIN%":$lang.urls.login|replace:"%SIGNUP%":$lang.urls.signup}} {{else}} {{if $smarty.session.tokens_available<$data.user.tokens_required}} {{assign var="tokens_left" value=$data.user.tokens_required-$smarty.session.tokens_available}} {{$lang.videos.video_player_tokens_not_enough.channel|replace:"%CHANNEL%":$data.username|replace:"%TOKENS_COST%":$data.user.tokens_required|replace:"%TOKENS_AVAILABLE%":$smarty.session.tokens_available|replace:"%TOKENS_LEFT%":$tokens_left|replace:"%UPGRADE%":$lang.urls.upgrade|smarty:nodefaults}} <form> <input type="button" class="submit" data-fancybox="ajax" data-href="{{$lang.urls.upgrade}}" value="{{$lang.videos.video_player_tokens_btn_buy|replace:"%TOKENS_COST%":$data.user.tokens_required|replace:"%TOKENS_AVAILABLE%":$smarty.session.tokens_available|replace:"%TOKENS_LEFT%":$tokens_left}}"> </form> {{else}} {{assign var="tokens_left" value=$smarty.session.tokens_available-$data.user.tokens_required}} {{$lang.videos.video_player_tokens_purchase.channel|replace:"%CHANNEL%":$data.username|replace:"%TOKENS_COST%":$data.user.tokens_required|replace:"%TOKENS_AVAILABLE%":$smarty.session.tokens_available|replace:"%TOKENS_LEFT%":$tokens_left|replace:"%UPGRADE%":$lang.urls.upgrade|smarty:nodefaults}} <form action="{{$data.canonical_url}}" method="post" data-form="ajax"> <div class="generic-error hidden"></div> <input type="hidden" name="action" value="subscribe"/> <input type="hidden" name="subscribe_user_id" value="{{$data.user.user_id}}"> <input type="submit" class="submit" value="{{$lang.videos.video_player_tokens_btn_spend|replace:"%TOKENS_COST%":$data.user.tokens_required|replace:"%TOKENS_AVAILABLE%":$smarty.session.tokens_available|replace:"%TOKENS_LEFT%":$tokens_left}}"> </form> {{/if}} {{/if}} </span> </div> After adding such block, video page should turn into a locked player for paid channels / profiles, unless user purchases them: Displaying subscription status for paid subscription Note: this functionality will become possible in KVS 6.0 update. Default theme renders list of user's subscriptions, but subscriptions can be free and paid. The default rendering doesn't separate them, and here is how to modify that. Go to Website UI -> Language files -> default and add the following lines: subscriptions.list_label_paid_unlimited = (Paid, never expires) subscriptions.list_label_paid_expired = (Paid, expired) subscriptions.list_label_paid_active = (Paid, expires in [count]%1% days || 1: 1 day[/count]) Then go to Website UI -> Pages -> [Memberzone] My Profile page -> My Subscriptions block settings. Locate the following code in its template: <a href="{{$subscribed_url}}" class="title">{{$item.title}}</a> And change it like this: <a href="{{$subscribed_url}}" class="title"> {{$item.title}} {{if $item.purchase.purchase_id>0}} {{if $item.purchase.expiry_date_is_unlimited==1}} {{$lang.subscriptions.list_label_paid_unlimited}} {{elseif $item.purchase.expiry_date_hours_left<0}} {{$lang.subscriptions.list_label_paid_expired}} {{else}} {{assign var="days_left" value=$item.purchase.expiry_date_hours_left/24|floor}} {{$lang.subscriptions.list_label_paid_active|count_format:"%1%":$days_left}} {{/if}} {{/if}} </a> And the result will look like this:
  7. By default KVS simply shows 404 error message on black screen when somebody is using embed code for a video that was deleted. The contents what is displayed for wrong / deleted embed codes can be customized in Settings -> Embed player settings under Error template field. Here is the example of how you can configure it to display list of videos in addition to error message. Just use the code below as Error template: <html> <head> <title>{{$lang.error_404.title}}</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <style type="text/css"> @import "https://fonts.googleapis.com/css?family=Roboto:400,500,700&amp;subset=cyrillic"; /* related videos in player */ .player-related-videos { position: absolute; left: 0; top: 0; right: 0; bottom: 0; padding: 30px 10px 30px 10px; overflow: hidden; } .player-related-videos .player-related-videos-container { position: relative; width: 100%; height: 100%; overflow: hidden; text-align: center; } .player-related-videos .player-related-videos-item { position: relative; display: inline-block; vertical-align: middle; margin-top: 5px; } .player-related-videos .player-related-videos-item .title { display: none; position: absolute; left: 0; top: 0; right: 0; height: 52px; overflow: hidden; text-align: left; padding: 5px; color: #ffffff; background: -moz-linear-gradient(top, rgba(12, 12, 12, 0.8) 0px, transparent 50px); background: -webkit-gradient(linear, left top, left bottom, color-stop(0px, rgba(12, 12, 12, 0.8)), color-stop(50px, transparent)); background: -webkit-linear-gradient(top, rgba(12, 12, 12, 0.8) 0px, transparent 50px); background: -o-linear-gradient(top, rgba(12, 12, 12, 0.8) 0px, transparent 50px); background: -ms-linear-gradient(top, rgba(12, 12, 12, 0.8) 0px, transparent 50px); background: linear-gradient(to bottom, rgba(12, 12, 12, 0.8) 0px, transparent 50px); } .player-related-videos .player-related-videos-item .duration { display: none; position: absolute; bottom: 5px; right: 5px; color: #ffffff; background: rgba(12, 12, 12, 0.8); padding: 2px 5px; } .player-related-videos .player-related-videos-item:hover .title, .touch .player-related-videos .player-related-videos-item .title, .touch .player-related-videos .player-related-videos-item .duration, .player-related-videos .player-related-videos-item:hover .duration { display: block; } body { font: 400 14px/1.2 "Roboto", Helvetica, sans-serif; } body > div:first-child { top: 0 !important; padding-top: 5px; } </style> </head> <body style="margin: 0; padding: 0; background: #000; color: #fff"> <div style="width: 100%; text-align: center; position: absolute; top: 49%">{{$lang.error_404.title}}</div> <script src="{{$config.statics_url}}/static/js/main.min.js"></script> <script> if ('ontouchstart' in document) { $('body').addClass('touch'); } $.ajax({ url: '{{$config.project_url}}/related_videos_html/0/', type: 'GET', cache: false, success: function (html) { $('body').append($(html)); } }); </script> </body> </html> NOTE: this code is for KVS default theme. For other themes you may need to check which theme scripts you have in http://domain.com/static/js directory. If you have main.min.js file, this code will work. In other themes you may have vendors.min.js - then you need to replace this line: <script src="{{$config.statics_url}}/static/js/main.min.js"></script> with this one: <script src="{{$config.statics_url}}/static/js/vendors.min.js"></script> Finally if you neither have main.min.js nor vendors.min.js, you need to include JQuery library there.
  8. List of search queries is displayed by search_results block. Here is how you can put it into the main pages: {{insert name="getBlock" block_id="search_results" block_name="Similar Searches"}} Put it into Index and Common Videos List (renders categories, tags, models, content sources and etc.) page templates. After you add this block into page template and save, it will appear in the list of blocks on this page and you can edit its settings. Here is template code for this block that will render cloud of search queries: {{if count($data)>0}} <div class="box search-cloud"> {{foreach item="item" from=$data}} {{assign var="query" value=$item.query|replace:"-":"[dash]"|replace:"&":"%26"|replace:"?":"%3F"|replace:"/":"%2F"|replace:" ":"-"|replace:"[dash]":"--"|rawurlencode}} <a href="{{$lang.urls.search_query|replace:"%QUERY%":$query}}" style="{{if $item.is_bold==1}}font-weight: bold; {{/if}}{{if $item.size>0}}font-size: {{$item.size}}px;{{/if}}">{{$item.query}}</a> &nbsp;&nbsp;&nbsp; {{/foreach}} </div> {{/if}} In block parameters configure: items_per_page: the number of queries you want to be displayed. sort_by: sorting of the queries. var_category_dir = category var_tag_dir = tag size_from = 12 size_to = 16 Also make sure you put a cache time of 86400, as this block will be quite heavy. When this is configured, you can see query cloud is displayed on Index and other video pages. For tag and category pages it should be relevant to the displayed tag / category. On other pages it may render the same set of queries, as they won't have context object that can be used to display similar queries.
  9. Sometimes when you migrate or for various reasons it does not display any screenshots on the site. See in the picture below. If you have content organized in per channels or tags, it's easier to edit multiple videos at once. In my case I had over 9000 videos that did not display screenshots on the site. I checked on the site to see which user posted and if the videos are put in different channels or unique tag. The user in question had all the content divided into channels, which made my job easier. 1. Go to the video section 2. Then to the channel section 3. Search for the channel name 4. In the Videos tab you have the number of videos in this channel 5. Click pe numarul de sub videos 6. Acum iti va afisa toate video din acel canal 7. Scroll in jos si la sectiunea Batch actions alege Mass edit filtered Videos (numarul de video) and click Execute 8. On the new page you can edit many things, but scroll down and check Re-create overview screenshots 9. Now click on Apply Changes 10. Depending on your server, it may take minutes or hours. When the process is finished on the site it should display everything ok. Have fun.
  10. 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_binary('/usr/local/bin/youtube-dl'); } 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
  11. Most of KVS themes come with popups for utility forms, such as login and signup. If you need to refer login or signup popups, you can do that without actually having them as separate pages: https://kvs-demo.com/?login https://kvs-demo.com/?signup If you want to create separate pages for them with custom design, you can also do that by following this guide. Creating login page Step 1. In Website UI -> Pages create a new page with the following template code: {{assign var="page_title" value=$lang.html.login_title}} {{assign var="page_canonical" value=$lang.urls.login}} {{include file="include_header_general.tpl"}} <div class="content"> <div class="main-content"> <div class="main-container"> {{insert name="getBlock" block_id="logon" block_name="Logon Form"}} </div> </div> </div> {{include file="include_footer_general.tpl"}} Set page External ID to login, you can set title to Login, this is only title for admin panel. NOTE: if you have error message saying that there are no permissions to create files, you have 2 choices: Either put 777 permissions on the directory where KVS is installed (using FTP client or server File manager tool) Or manually create /login.php file in the document root with the following code: <?php require_once("admin/include/process_page.php");?> Step 2. After you saved page in Step 1, you should see Logon Form block added to this page's blocks list at the bottom. Open it for editing. Now open another browser tab and go to Website UI -> Global blocks -> Logon Form and copy template code and block parameters from there into the settings of Logon Form on the new login page. Step 3. In /.htaccess file in the root directory of your project find these 2 lines: RewriteRule ^login/$ index.php?mode=async&function=get_block&block_id=logon_logon_form&global=true [L,QSA] RewriteRule ^login-required/$ index.php?mode=async&function=get_block&block_id=logon_logon_form&global=true&error=only_for_members [L,QSA] and change them to these: RewriteRule ^login/$ login.php [L,QSA] RewriteRule ^login-required/$ login.php?error=only_for_members [L,QSA] Step 4. In Website UI -> Texts add new text for rendering title of your newly selected login page: External ID: html.login_title Default: Login Page Title Now you should be able to click on login link in header and see your new login page. Do you still see it is open in popup instead of separate page? If yes, please update this file on your server with a newer version from kvs-demo.com (only for KVS default theme): https://kvs-demo.com/static/js/main.min.js Creating signup page Step 1. In Website UI -> Pages create a new page with the following template code: {{assign var="page_title" value=$lang.html.signup_title}} {{assign var="page_canonical" value=$lang.urls.signup}} {{include file="include_header_general.tpl"}} <div class="content"> <div class="main-content"> <div class="main-container"> {{insert name="getBlock" block_id="signup" block_name="Signup Form"}} </div> </div> </div> {{include file="include_footer_general.tpl"}} Set page External ID to signup, you can set title to Signup, this is only title for admin panel. NOTE: if you have error message saying that there are no permissions to create files, you have 2 choices: Either put 777 permissions on the directory where KVS is installed (using FTP client or server File manager tool) Or manually create /login.php file in the document root with the following code: <?php require_once("admin/include/process_page.php");?> Step 2. After you saved page in Step 1, you should see Signup Form block added to this page's blocks list at the bottom. Open it for editing. Now open another browser tab and go to Website UI -> Global blocks -> Signup Form XXX and copy template code and block parameters from there into the settings of Signup Form on the new signup page. NOTE: There are multiple different signup forms support in KVS themes: Simple signup form is default, Simple2 signup form requires email as a login, Advanced signup form renders additional profile fields on signup; finally Premium signup form renders paid access options. Choose the form that you need and copy its template and settings. Step 3. In /.htaccess file in the root directory of your project find this line: RewriteRule ^signup/$ index.php?mode=async&function=get_block&block_id=signup_signup_form_simple&global=true [L,QSA] and change it to this: RewriteRule ^signup/$ signup.php [L,QSA] Step 4. In Website UI -> Texts add new text for rendering title of your newly selected signup page: External ID: html.signup_title Default: Signup Page Title Now you should be able to click on signup link in header and see your new signup page. Do you still see it is open in popup instead of separate page? If yes, please update this file on your server with a newer version from kvs-demo.com (only for KVS default theme): https://kvs-demo.com/static/js/main.min.js
  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. For a video site most of the bandwidth is being used for serving videos. In many cases you will have a limited channel like 100mbit or 1000mbit, so you will not save any money by saving bandwidth, however there are several cases when saving bandwidth can make great benefit for you: When your channel is fully loaded with serving videos, your site may become unresponsive for some users and you may get SEO penalty. One solution is to buy a new server or extend bandwidth limit, but you can save this money with KVS by trying to limit video streaming speed. When you are using CDN, in most cases you pay for the maximum bandwidth peak. You can save some money by paying less if your maximum peak becomes less. Why limiting streaming speed can save your bandwidth? Many users do not watch videos in full length, they may skip up and down to different fragments. However if their internet speed is high, they can download full video at a max speed shortly even if they didn't watch most of it. With a speed limit you will reduce % of downloaded bandwidth by each user and finally you will get some cut in your global bandwidth usage. KVS provides 2 way to limit video streaming speed: Limit speed to fixed bitrate. This is not a good solution, since it can be inaccurate in many cases - since video bitrate is often dynamic and you won't know the exact bitrate to limit. Limit speed to dynamic bitrate with a multiplier. This option is much better as it will make sure different speed limits for videos of different bitrates and you don't need to investigate the average bitrate of your videos. However, there is one important issue which you should know about streaming MP4 files. Each MP4 file has a metadata atom in the beginning (MOOV atom). This atom contains keyframes from video file and can take up to 4MB depending on video duration and geometry. Player needs to download this atom before it can start playing videos. Therefore if you limit download speed, your videos will start playing with a big delay. However Nginx provides a way to fix that, we will describe this later. NOTE: limiting streaming speed is only possible with serving videos with Nginx or CDN. In case of CDN the implementation of speed limit is fully dependent on your CDN provider (BTW some CDNs are not interested in doing this for an obvious reason). KVS will pass speed limit info to the CDN integration script, which may or may not use it - but this is not KVS issue. How to configure download speed limit In KVS you can configure download speed limit per each video format separately. Go to Settings -> Video formats and for each video format you can set speed limit: Global speed limit: Dynamic bitrate x 1.2 (we recommend multipliers from 1.1 to 1.5) You can set other options under Speed limitation section as needed. For example you can give your premium or active members unlimited download speed. You can also limit speed for visitors from certain countries only, so that you main audience is not affected. In order to define list of countries you want to limit please take a look at Stats -> Countries for reference.
  14. How do I recover or find my admin password that I lost? There is no password reset button if you are locked out of admin panel.
  15. Is it possible to add filter videos by satellite in next update? Let's say I have Main Site A and Satellite B , I would like to filter videos uploaded from Satellite B and in the process give administrators access only to videos uploaded from satellite sites. Or Show videos from Satellite B in Satellite B admin also so admin from satellite B can add , delete or changes videos only owned by him, Videos from all satellites will show on Main site too .
  16. KVS doesn't support video popularity stats per country yet, but it is possible to emulate this for the end users, providing some personal attitude to every visitor: Step 1. In /admin/include/pre_initialize_page_code.php add the following line: $_GET['GEOIP_COUNTRY_CODE'] = $_REQUEST['GEOIP_COUNTRY_CODE'] = strtolower($_SERVER['GEOIP_COUNTRY_CODE']); This is needed to pass environmental variable with country code to request variables, that can be used by KVS site engine. Step 2. In Website UI -> Texts add the following text that will be rendered as a header: External ID: videos.list_title_by_country Default: Popular in %1% <img class="flag" title="%1%" alt="%2%" src="/static/images/flags/%2%.gif"> This text also contains IMG with reference to flag image. Step 3. Open Website UI -> Pages -> Index -> Videos Watched Right Now for editing. Change its Template code to the following: {{query_kvs select="single" table="list_countries" where_country_code=$smarty.get.GEOIP_COUNTRY_CODE where_language_code="en" assign="country"}} {{assign var="country_title" value=$country.title}} {{if !$country_title || $country.is_system==1}} {{assign var="list_videos_title" value=$lang.videos.list_title_watched_right_now}} {{else}} {{assign var="list_videos_title" value=$lang.videos.list_title_by_country|replace:"%1%":$country.title|replace:"%2%":$smarty.get.GEOIP_COUNTRY_CODE|smarty:nodefaults}} {{/if}} {{assign var="list_videos_use_h1" value="true"}} {{include file="include_list_videos_block_common.tpl"}} NOTE: KVS only supports country names in English and Russian languages, if your site is in Russian please change where_language_code="en" with "ru" to have country name in Russian. In block settings down the page specify GEOIP_COUNTRY_CODE under Dynamic HTTP parameters. This is needed for correct caching logic for this block. If you don't do that, KVS admin panel will show error that using $smarty.get.GEOIP_COUNTRY_CODE variable will not work correctly. The code does the following. First it queries KVS database and selects country record that matches the current visitor's country code using query_kvs template function. Then it checks whether any non-system country record is found (system countries are some satellite ISPs and anonymous proxies). If nothing is found, this code will show old "Videos Watched Right Now" text. Otherwise it will show the new text with country code and flag icon. Step 4. For better icon styling add this block into theme CSS file: h1 img.flag, h2 img.flag { vertical-align: middle; }
  17. 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.
  18. Please add the following code to your header template to prepare your video pages for Yandex.Video: {{if $storage.video_view_video_view.video_id>0}} <meta property="og:url" content="{{$storage.video_view_video_view.canonical_url}}"/> <meta property="og:video" content="{{$config.project_url}}/embed/{{$storage.video_view_video_view.video_id}}"/> <meta property="og:type" content="video.other"/> <meta property="og:video:type" content="video/mp4"/> {{if $storage.video_view_video_view.file_dimensions.0>0}} <meta property="og:video:width" content="{{$storage.video_view_video_view.file_dimensions.0}}"/> <meta property="og:video:height" content="{{$storage.video_view_video_view.file_dimensions.1}}"/> {{/if}} {{if $page_og_description==''}} <meta property="og:description" content="{{$storage.video_view_video_view.title|mb_ucfirst}}"/> {{/if}} <meta property="video:duration" content="{{$storage.video_view_video_view.duration_minutes*60+$storage.video_view_video_view.duration_seconds}}"/> {{if $storage.video_view_video_view.tags_as_string}} <meta property="video:tag" content="{{$storage.video_view_video_view.tags_as_string}}"/> {{/if}} <meta property="ya:ovs:upload_date" content="{{$storage.video_view_video_view.post_date|replace:" ":"T"}}"/> <meta property="ya:ovs:adult" content="false"/> <meta property="ya:ovs:allow_embed" content="true"/> <meta property="ya:ovs:views_total" content="{{$storage.video_view_video_view.video_viewed}}"/> <meta property="ya:ovs:comments" content="{{$storage.video_view_video_view.comments_count}}"/> <meta property="ya:ovs:rating" content="{{$storage.video_view_video_view.rating*2}}"/> {{if $storage.video_view_video_view.is_hd==1}} <meta property="ya:ovs:quality" content="HD"/> {{/if}} {{/if}} Also add the following attribute to your <html> tag in header: prefix="og: http://ogp.me/ns# video: http://ogp.me/ns#video"
  19. 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.
  20. Step 1. Open Website UI -> Pages -> View Video page -> Related Videos block for editing. Step 2. Change parameters: Under sort_by make sure you deselect Pseudo-random sorting and choose another sorting, as pseudo random sorting doesn't support pagination. Enable var_from = from. Step 3. Add the following 3 lines: {{assign var="pagination_use_load_more" value="true"}} {{assign var="pagination_no_links" value="more"}} {{include file="include_pagination_block_common.tpl"}} into block template code right after this one: {{include file="include_list_videos_block_common.tpl"}} Step 4. Adjust styles to add some spacing after load more button: .related-videos { padding-bottom: 15px; }
  21. Unfortunately it is not possible to update KVS theme like you can normally update KVS. Theme is subject to intensive customization: you modify styles and advertising (yes, advertising in KVS is part of theme as ads are displayed inside theme layout), you change texts and configure SEO. Updating theme with keeping your custom changes is not technically possible. The only possible way is to reset theme to a new version. When we say reset, we mean that your site will start looking like it was at initial KVS installation: You will lose all custom styling You will lose all site advertising (except in-player advertising, as player is not part of theme) You will lose all text changes, logo change You will lose all SEO changes (e.g. HTML titles, descriptions, SEO texts will be reset to their default values) So, this is only feasible if you still didn't start your site, or you didn't put much customization into it and can re-do everything quickly. Is there any sense to update theme at all? - We would say "no", since we don't put much changes into themes. The vast majority of theme changes are cosmetic changes only. All changes that we considered to be really important (e.g. search suggestions, chunked upload), were provided with a guide on how to put them into old theme version, examples: If you still for any reason want to reset to a new theme version, please contact support to get instructions, we do not want to print them publicly to prevent from accidentally resetting theme.
  22. KVS Project backup plugin can be used to either restore theme from a specific date, or to move theme from one project to another. Step1. In order to create theme backup for copy please go to Plugins -> Project backup and choose backup website option there. It will create an archive with theme backup in the backup directory configured in plugin: You can also choose any of the automated backup file, every of them contains theme backup. IMPORTANT! Theme backup also includes advertising defined in Website UI -> Advertising section, as advertising is part of theme. By using backup archive to restore theme you will also restore advertising to the date of backup. Step 2. When you have the needed backup archive, unpack it locally to some directory. Backup archive may contain multiple sub-directories, but the only needed sub-directory is website. Step 3. By using FTP client connect to your server and drag and drop the contents of website sub-directory on top. Using drag and drop is the best way to make sure that you NEVER EVER use "sync" function, because "sync" function can destroy your project without ability to restore it later. We recommended using free Filezilla FTP client: After the copying is finished, your project will have theme version from backup. Step 4. If you move theme from one project to another, it may not work correctly after copying. The reason is that theme may refer screenshot and album formats that are not available in your new project. Go to Website UI -> Theme settings and check if there are any errors displayed about formats being used. You may need to either choose another formats, or create the missing formats in your new project. Another issue could be that your theme is using some 3rd-party files, scripts, images that are not known to KVS backup plugin, so that they were not included into backup archive. Then you should typically see some 404 errors in your project when looking into Network or Console section of browser DEV tools. You should solve these by manually copying the missing files and / or sub-directories from your old project. Finally you may also experience lack of editing permissions in KVS admin panel when opening certain objects in Website UI section. To make sure you won't have this, please login to your server command line with administrative user and apply these command after opening your project www root to correct permissions for the copied files: find template -type d | xargs chmod 777 find template -type f \( ! -iname ".htaccess" \) | xargs chmod 666 find admin/data/config -type d | xargs chmod 777 find admin/data/config -type f \( -iname "*.dat" \) | xargs chmod 666 find admin/data/advertisements -type f \( -iname "*.dat" \) | xargs chmod 666
  23. Migrating categorization In most cases you don't need to consider categorization, as it will be automatically migrated along with content. However if you want to migrate categorization details as well (such as model details, screenshots, or custom fields) the only way to do that is to use Migrator plugin in KVS. Migrator plugin will connect to another KVS database and will pull categorization that you choose to pull. There are certain important aspects that you should consider when using Migrator plugin: Migrator plugin only supports categorization for KVS migrator. Content migration should be done using export and import functionality, which has much more options. Migrator plugin needs direct connection to other project's database. This works fine if your other project is on the same server, but won't work if your projects are on different servers. One option is to ask admins to expose KVS database on the other project's server to be available for public connections, which is not good from security point. Another option is to create a temporary local database and import backup from the other project's database into it, then configure Migrator plugin to migrate from this local temporary database. Migrator plugin needs your new database to be fully empty (e.g. no new categorization objects in it), as it will migrate objects by using the same IDs and will replace any existing objects that have the same IDs that are migrated from the other project's database. WARNING! If you try using Migrator plugin on project where you already have some categorization, it can be lost. It is recommended that both projects have the same KVS version before you try migration. Otherwise it is not guaranteed to fully succeed. Having these in mind, if your other project is on the same server and your new project is just installed, you can easily pull up all categories, tags, models, content sources with all their data within 5 minutes. All you need is to specify database connection to the other project's database. If you don't know MySQL connection details, please open /admin/include/setup_db.php file to find them. Here is an example: NOTE: for the Old path please specify any existing empty directory path, you can specify path to /tmp directory in your www root. Manually migrating video or album content Use manual content export / import when you want to do a one time migration of all (or part) of your content from older project and then allow these projects run separately. If you want to constantly sync one project based on another project, you need to use feeds, which are explained in the next section. The idea is that you first export content data into a text file and then use this text file to import the exported content into another project. Export / import of albums and videos works in exactly same way, so we will describe on videos. You can access export function in Videos -> Export videos (Import videos for import). The important thing is to create a named pattern of export (and later import), so that you can return to it later if you do any mistakes with fields or options. The recommended way is to first export a dozen of test videos and then try importing them to test the whole scheme and that you get the result you need; and only after you are fine with the imported content you can do the full migration. Another important thing to consider is which video content types you have (file uploads, embeds, hotlinks, or mixed) and how you want them to be imported. The most common scenario is that you have file uploads (videos that store files in KVS storage) and you want to migrate them in the same way. Another possible scenario is that you have videos embedded from other sites and you want to migrate them in the same way. In these cases when you have ALL videos of the same content type, you just do one time export of them ALL and one time import of them ALL. However, there are rare cases when you have some videos uploaded to your servers, some more videos embedded and another set of videos just hotlinked. In this specific case you should do separate export and import for each content type that you have. This is needed because videos of different content types have different data structure. Video export GUI offers Loaded as filter that allows you separating videos by their content type. With regard to Field and Line separators it is recommended to leave them as default. This may not work only if you have videos with multiline descriptions, but in this case manual export and import won't work for you at all and you have to fallback to using KVS feeds. In general it is recommended to leave all export and import options to their default values, unless you need anything specific. The main area where you should put your effort is Fields for export (Fields for import). First of all you should be using the same Field and Line separators in both export and import, we recommend use them as set by default. Next you should make sure that you select the same sets of fields in both export and import. Many fields like title and description are obvious, how about the rest of them? Here is a short summary: Use Video ID only if you want to keep the same IDs across 2 projects. In most cases this is not needed. Use Directory only if you had some specific rules on directory generation or transliteration. In most case this is not needed as directory is usually generated from title. If you want to migrate rating, make sure you select both Rating and Rating (votes). If you want to migrate usernames of video creators, you can do that by selecting User field, but please note that this will only migrate the username, not the whole user data. KVS will create new fake users with the given usernames in new projects. Finally there is a set of fields under Content group, which are related to content structure. As we noted before, depending on video content type these fields structure will be different: For file upload content type, you should first get understanding which video formats you want to migrate. In many cases video formats on your new site will be configured in the same way as on your old site, so you will need to migrate all video formats. But in some cases your new site may have less formats, for example it could have no video preview format, or you occasionally want video preview to be generated differently on this new site. Based on this understanding you should export Video file "XXX" (for hotlink) field for each of the video formats you want to migrate. At the same time you should select the corresponding Video file "XXX" (without processing) field in import fields configuration. For embed content type, you should export and import these fields: Embed code (embedded video), Duration, Main screenshot number and Overview screenshots (sources comma-separated). For hotlink content type, you should export and import these fields: Hosted file URL (hotlinking), Duration, Main screenshot number and Overview screenshots (sources comma-separated). For pseudo video content type, you should export and import these fields: Outgoing URL (pseudo video), Duration, Main screenshot number and Overview screenshots (sources comma-separated). NOTE: if you have mixed content types, remember to do separate export and import for each content type with different set of content fields. NOTE: change Sorting to Video ID Asc so that videos are exported and imported in the same order as on the original site. IMPORTANT! When importing uploaded videos you should make sure that source site has video download protection disabled for the whole period of import. You can disable this in Settings -> Content settings -> Enable protection for video download script option. After import is fully completed, please enable it back. With regard to screenshots, for file uploads they are optional and it is up to you if you want to migrate them or not. In any way KVS will create new screenshots if needed. When migrating screenshots, please make sure that you export their source files, not files of any specific format. And also make sure you migrate main screenshot number. Here is example of how we selected fields in export and import to migrate some uploaded videos from one site to another: Automating content sync with feed You only need to use feeds if you plan to repeatedly sync other sites from the content of you primary site, or in case descriptions of your videos may contain line breaks, so that it is not possible to normally transfer them via manual CSV import. For a one time content transfer it is better to use manual import, as it provides more options and features. It also worth mentioning that only KVS Ultimate supports exporting feeds, so your primary project should have ultimate license. Importing feeds are supported in all KVS licenses. Also at the moment KVS doesn't support feeds for albums. Part 1: Exporting feed. You should start with creating exporting feed in your primary project, you can do that in Videos -> Exporting feeds. The most important section is Feed data and its Content type option. This option indicates which content details you want to expose in feed, and this depends on how you plan to sync your content into another KVS project (please find several examples of how to create site network from a single KVS site in How to build your tube empire with KVS article): Use Website link option if you want to migrate these videos as pseudo videos. Use Hotlink option if you plan to hotlink video files from this project on another projects. Use Embed option if you want to embed these videos on your another projects. Finally use Download link option if you are going to fully sync video files of videos of this project to your another projects. IMPORTANT! When using this option you should make sure that source site has video download protection disabled for the whole period of import. You can disable this in Settings -> Content settings -> Enable protection for video download script option. After import is fully completed, please enable it back. For other options make sure to enable all categorization data, screenshot and poster sources, custom and translated fields. Increase Max limit option to 10000, or bigger value that you want to use (see explanation below). If you plan to use embed codes or pseudo videos and you need some tracking of all traffic that comes to your primary site, you may also need to set some Traffic tracking parameters that you can later specify in feed builder. After your new exporting feed is saved, open its Feed access point to see feed builder form that provides ability to query the needed data from the feed. You should have Feed format set to KVS. Use Filters section if you want to sync only subset of content. If you are going to embed videos on another projects, check URLs and embeds section options. You will also need to specify details for any Traffic tracking parameters there if you enabled them. If you plan to hotlink video files on another projects, check Video files section that provides ability to select either quality factor for hotlinked URLs, or choose a specific video format to hotlink. In most cases you won't need anything specific for download mode, as it works fine by default. Another important thing to consider at this point is how many videos your feed would contain. If your database has less than 10k videos, you won't face any issue in most cases. More videos mean more memory and database load to generate all feed data, which will reach red line at one point and feed will stop working or hang for a long time. In order to solve this, you should use feed limit and pagination control to paginate over the whole list. E.g. import the first 10k videos with the first iteration, then import another 10k videos, and etc. In order to do that you should generate all feed URLs once, don't leave it for the latter time, as later you may forget which options you selected. Change Sorting to Biggest ID last so that videos are exported in the order as they were added. First specify Limit = 10000 and press Get videos button. It should open another tab with feed URL that queries the first 10k videos. Copy URL and save it to a text document. Then in feed constructor set Skip to 10000 and press Get videos button again. You will get another URL that queries the second 10k videos. Repeat the same by incrementing Skip by 10000 again and again until you finally get empty list that will indicate end of paginated data. You can try increasing limit to 20000 and see if feed works with more videos, so that you do less iterations. This will give you some set of URLs to query all your existing videos. Finally you need the last URL that will query some set of new videos for repeated sync. Change Sorting to Most recent first to make sure that now only new videos are in the feed. Set Limit to 1000 now and get URL for querying most recent 1000 videos that you will later use to sync new videos. Part 2: Importing feeds. Now you should go to admin panels of sites that you want to pull videos from your exporting feeds. Go to Videos -> Importing feeds and create a new importing feed. In Feed URL set the first URL of your URLs list that you created when using feed builder. Choose KVS (XML) parser. In Duplicates prefix specify domain name of your primary project you export videos from. If you create multiple importing feeds for the same project, please make sure that all share that same duplicates prefix, so that's why the best idea is to use source project domain name here. Under Interval field choose Run this feed only once and deactivate. Since you have paginated data (if source site contains more than 10k videos you will most likely end up with feed data split into 10k-volume pages), you will need to import each page separately. The proposed way is to first configure feed to import all videos from the first page, then wait for it to be deactivated and re-configure to import from the second page URL, and etc. until you import all pages with all existing videos. After that you should change Feed URL to the last URL you created that will pull latest 1000 videos and configure its Interval to how often you want feed to pull new videos. Then feed will automatically pull new videos for the rest of time. Under Feed data check all data fields you want to import. In Video data section set Video status to Active, Video screenshots to Use screenshots from feed, Video publishing dates to Use publishing date from feed. Finally in Video adding mode option you should choose whether you want to embed, or hotlink, or download videos. If you want to download, then in most cases you will need to set All formats that have match by postfixes (without processing) in Format option. However in order this option to work correctly, you should go to Settings -> Video formats in this project and make sure the formats are configured in the same way they are configured on source site. At least the formats that you want to be downloaded via feeds. When we say "in the same way", we mean that their postfixes and statuses should be set accordingly. For example if on source project you have 480p, 720p formats and MP4 preview format, then you should make sure your importing site also have these formats with the same postfixes. If you don't want, for example, to download MP4 preview format and you want it to be created on the importing project with some other options - create it with another postfix syntax and required status. Then importing feed should download 480p and 720p files only and KVS will auto-create your custom MP4 preview from them. NOTE: for testing purposes it is recommended to set Max videos per execution to some small number (e.g. 10-100) for the first iteration to make sure you configured importing feed correctly. Then you can remove this limit and run feed again allowing it importing the whole set of data.
  24. KVS doesn't provide any specific GUI controls to manage indexing, as it is not virtually possible due to very custom theme structure. However you can get everything you need with a very few fixes. Step 1. First of all you need to add noindex tag into site header template. Go to Website UI -> Page components -> include_header_general.tpl and add the following code somewhere inside its <head> section: {{if $page_noindex=='true'}} <meta name="robots" content="noindex" /> {{/if}} This code check if there is a page variable named page_noindex and it is equal to true, then this page should not be indexed by SE. Step 2. Set page_noindex variable anywhere you want this page to be not indexable: {{assign var="page_noindex" value="true"}} somewhere in page template around these values (the example is from Index page): How do you find where to add it? If you have KVS 5.3.0 or above, you should be able to see KVS Admin Toolbar at the bottom of each page and you can open page editor right from the toolbar menu. If your KVS version doesn't support toolbar yet, just add ?debug=true to the URL you are looking at and it should open debugger that will print link to open page editor.
×
×
  • Create New...