File: README.md
MediaCMS
MediaCMS is a modern, fully featured open source video and media CMS. It is developed to meet the needs of modern web platforms for viewing and sharing media. It can be used to build a small to medium video and media portal within minutes.
It is built mostly using the modern stack Django + React and includes a REST API.
A demo is available at https://demo.mediacms.io
Screenshots
Features
- Complete control over your data: host it yourself!
- Modern technologies: Django/Python/Celery, React.
- Support for multiple publishing workflows: public, private, unlisted and custom
- Role-Based Access Control (RBAC): create RBAC categories and connect users to groups with view/edit access on their media
- Automatic transcription: through integration with Whisper running locally
- Multiple media types support: video, audio, image, pdf
- Multiple media classification options: categories, tags and custom
- Multiple media sharing options: social media share, videos embed code generation
- Use in LMS: LTI 1.3 support plus a Moodle plugin for embeding media in LMS
- Video Trimmer: trim video, replace, save as new or create segments
- SAML support: with ability to add mappings to system roles and groups
- Easy media searching: enriched with live search functionality
- Playlists for audio and video content: create playlists, add and reorder content
- Responsive design: including light and dark themes
- Advanced users management: allow self registration, invite only, closed.
- Configurable actions: allow download, add comments, add likes, dislikes, report media
- Configuration options: change logos, fonts, styling, add more pages
- Enhanced video player: customized video.js player with multiple resolution and playback speed options
- Multiple transcoding profiles: sane defaults for multiple dimensions (144p, 240p, 360p, 480p, 720p, 1080p) and multiple profiles (h264, h265, vp9)
- Adaptive video streaming: possible through HLS protocol
- Subtitles/CC: support for multilingual subtitle files
- Scalable transcoding: transcoding through priorities.
- Chunked file uploads: for pausable/resumable upload of content
- REST API: Documented through Swagger
- Translation: Most of the CMS is translated to a number of languages
Example cases
- Universities, schools, education. Administrators and editors keep what content will be published, students are not distracted with advertisements and irrelevant content, plus they have the ability to select either to stream or download content.
- Organization sensitive content. In cases where content is sensitive and cannot be uploaded to external sites.
- Build a great community. MediaCMS can be customized (URLs, logos, fonts, aesthetics) so that you create a highly customized video portal for your community!
- Personal portal. Organize, categorize and host your content the way you prefer.
Philosophy
We believe there's a need for quality open source web applications that can be used to build community portals and support collaboration.
We have three goals for MediaCMS: a) deliver all functionality one would expect from a modern system, b) allow for easy installation and maintenance, c) allow easy customization and addition of features.
License
MediaCMS is released under GNU Affero General Public License v3.0 license.
Copyright Markos Gogoulos.
Support and paid services
We provide custom installations, development of extra functionality, migration from existing systems, integrations with legacy systems, training and support. Checkout our services page for more information.
Commercial Hostings
Elestio
You can deploy MediaCMS on Elestio using one-click deployment. Elestio supports MediaCMS by providing revenue share so go ahead and click below to deploy and use MediaCMS.
Hardware considerations
For a small to medium installation, with a few hours of video uploaded daily, and a few hundreds of active daily users viewing content, 4GB Ram / 2-4 CPUs as minimum is ok. For a larger installation with many hours of video uploaded daily, consider adding more CPUs and more Ram.
In terms of disk space, think of what the needs will be. A general rule is to multiply by three the size of the expected uploaded videos (since the system keeps original versions, encoded versions plus HLS), so if you receive 1G of videos daily and maintain all of them, you should consider a 1T disk across a year (1G * 3 * 365).
In order to support automatic transcriptions through Whisper, consider more CPUs.
Installation / Maintanance
There are two ways to run MediaCMS, through Docker Compose and through installing it on a server via an automation script that installs and configures all needed services. Find the related pages:
Docker Compose page
A complete guide can be found on the blog post How to self-host and share your videos in 2021.
Documentation
- Users documentation page
- Administrators documentation page
- Developers documentation page
- Configuration page
- Transcoding page
- Developer Experience page
- Media Permissions page
- Moodle Plugin page
Technology
This software uses the following list of awesome technologies: Python, Django, Django Rest Framework, Celery, PostgreSQL, Redis, Nginx, Gunicorn, React, Fine Uploader, video.js, FFMPEG, Bento4
Who is using it
- Multiple Universities for hosting educational videos
- Cinemata non-profit media, technology and culture organization - https://cinemata.org
- Critical Commons public media archive and fair use advocacy network - https://criticalcommons.org
- American Association of Gynecologic Laparoscopists - https://surgeryu.org/
How to contribute
If you like the project, here's a few things you can do
- Hire us, for custom installations, training, support, maintenance work
- Suggest us to others that are interested to hire us
- Write a blog post/article about MediaCMS
- Share on social media about the project
- Open issues, participate on discussions, report bugs, suggest ideas
- Show and tell how you are using the project
- Star the project
- Add functionality, work on a PR, fix an issue!
Contact
File: cli-tool/README.md
MediaCMS CLI Tool
This is the CLI tool to interact with the API of your installation/instance of MediaCMS.
How to configure and use the tools
- Make sure that you have all the required installations (
cli-tool/requirements.txt)installed. To install it -- Create a new virtualenv using any python virtualenv manager.
- Then activate the virtualenv and enter
pip install -r requirements.txt.
- Create an .env file in this folder (
mediacms/cli-tool/) - Run the cli tool using the command
python cli.py login. This will authenticate you and store necessary creds for further authentications. - To check the credentials and necessary setup, run
python cli.py whoami. This will show your details.
File: docs/admins_docs.md
Administrators documentation
Table of contents
- 1. Welcome
- 3. Docker Installation
- 4. Docker Deployment options
- 5. Configuration
- 6. Manage pages
- 7. Django admin dashboard
- 8. On portal workflow
- 9. On user roles
- 10. Adding languages for Captions and subtitles
- 11. Add/delete categories and tags
- 12. Video transcoding
- 13. How To Add A Static Page To The Sidebar
- 14. Add Google Analytics
- 15. Debugging email issues
- 16. Frequently Asked Questions
- 17. Cookie consent code
- 18. Disable encoding and show only original file
- 19. Rounded corners on videos
- 20. Translations
- 21. How to change the video frames on videos
- 22. Role-Based Access Control
- 23. SAML setup
- 24. Identity Providers setup
- 25. Custom urls
- 26. Allowed files
- 27. User upload limits
- 28. Whisper Transcribe for Automatic Subtitles
1. Welcome
This page is created for MediaCMS administrators that are responsible for setting up the software, maintaining it and making modifications.
3. Docker Installation
Installation
Install a recent version of Docker, and Docker Compose.
For Ubuntu systems this is:
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.shThen run as root
git clone https://github.com/mediacms-io/mediacms
cd mediacmsThe default option is to serve MediaCMS on all ips available of the server (including localhost).
If you want to explore more options (including setup of https with letsencrypt certificate) checkout Docker deployment section for different docker-compose setups to use.
Run
docker compose upThis will download all MediaCMS related Docker images and start all containers. Once it finishes, MediaCMS will be installed and available on http://localhost or http://ip
A user admin has been created with random password, you should be able to see it at the end of migrations container, eg
migrations_1 | Created admin user with password: gwg1clfkwfor if you have set the ADMIN_PASSWORD variable on docker-compose file you have used (example docker-compose.yaml), that variable will be set as the admin user's password
Note: if you want to use the automatic transcriptions, you have to do one of the following:
- either use the docker-compose.full.yaml, so in this case run
docker-compose -f docker-compose.yaml -f docker-compose.full.yaml up - or edit the docker-compose.yaml file and set the image for the celery_worker service as mediacms/mediacms:full instead of mediacms/mediacms:latest
Plus set variable USE_WHISPER_TRANSCRIBE = True in the settings.py file
Update
Get latest MediaCMS image and stop/start containers
cd /path/to/mediacms/installation
docker pull mediacms/mediacms
docker compose down
docker compose upUpdate from version 2 to version 3
Version 3 is using Python 3.11 and PostgreSQL 15. If you are updating from an older version, that was using PostgreSQL 13, the automatic update will not work, as you will receive the following message when the PostgreSQL container starts:
db_1 | 2023-06-27 11:07:42.959 UTC [1] FATAL: database files are incompatible with server
db_1 | 2023-06-27 11:07:42.959 UTC [1] DETAIL: The data directory was initialized by PostgreSQL version 13, which is not compatible with this version 15.2.At this point there are two options: either edit the Docker Compose file and make use of the existing postgres:13 image, or otherwise you have to perform the migration from postgresql 13 to version 15. More notes on https://github.com/mediacms-io/mediacms/pull/749
Configuration
Checkout the configuration docs here.
Maintenance
Database is stored on ../postgres_data/ and media_files on media_files/
4. Docker Deployment options
The mediacms image is built to use supervisord as the main process, which manages one or more services required to run mediacms. We can toggle which services are run in a given container by setting the environment variables below to yes or no:
- ENABLE_UWSGI
- ENABLE_NGINX
- ENABLE_CELERY_BEAT
- ENABLE_CELERY_SHORT
- ENABLE_CELERY_LONG
- ENABLE_MIGRATIONS
By default, all these services are enabled, but in order to create a scaleable deployment, some of them can be disabled, splitting the service up into smaller services.
Also see the Dockerfile for other environment variables which you may wish to override. Application settings, eg. FRONTEND_HOST can also be overridden by updating the deploy/docker/local_settings.py file.
To run, update the configs above if necessary, build the image by running docker compose build, then run docker compose run
Simple Deployment, accessed as http://localhost
The main container runs migrations, mediacms_web, celery_beat, celery_workers (celery_short and celery_long services), exposed on port 80 supported by redis and postgres database.
The FRONTEND_HOST in deploy/docker/local_settings.py is configured as http://localhost, on the docker host machine.
Server with ssl certificate through letsencrypt service, accessed as https://my_domain.com
Before trying this out make sure the ip points to my_domain.com.
With this method this deployment is used.
Edit this file and set VIRTUAL_HOST as my_domain.com, LETSENCRYPT_HOST as my_domain.com, and your email on LETSENCRYPT_EMAIL
Edit deploy/docker/local_settings.py and set https://my_domain.com as FRONTEND_HOST
Now run docker compose -f docker-compose-letsencrypt.yaml up, when installation finishes you will be able to access https://my_domain.com using a valid Letsencrypt certificate!
Advanced Deployment, accessed as http://localhost:8000
Here we can run 1 mediacms_web instance, with the FRONTEND_HOST in deploy/docker/local_settings.py configured as http://localhost:8000. This is bootstrapped by a single migrations instance and supported by a single celery_beat instance and 1 or more celery_worker instances. Redis and postgres containers are also used for persistence. Clients can access the service on http://localhost:8000, on the docker host machine. This is similar to this deployment, with a port defined in FRONTEND_HOST.
Advanced Deployment, with reverse proxy, accessed as http://mediacms.io
Here we can use jwilder/nginx-proxy to reverse proxy to 1 or more instances of mediacms_web supported by other services as mentioned in the previous deployment. The FRONTEND_HOST in deploy/docker/local_settings.py is configured as http://mediacms.io, nginx-proxy has port 80 exposed. Clients can access the service on http://mediacms.io (Assuming DNS or the hosts file is setup correctly to point to the IP of the nginx-proxy instance). This is similar to this deployment.
Advanced Deployment, with reverse proxy, accessed as https://localhost
The reverse proxy (jwilder/nginx-proxy) can be configured to provide SSL termination using self-signed certificates, letsencrypt or CA signed certificates (see: https://hub.docker.com/r/jwilder/nginx-proxy or LetsEncrypt Example ). In this case the FRONTEND_HOST should be set to https://mediacms.io. This is similar to this deployment.
A Scaleable Deployment Architecture (Docker, Swarm, Kubernetes)
The architecture below generalises all the deployment scenarios above, and provides a conceptual design for other deployments based on kubernetes and docker swarm. It allows for horizontal scaleability through the use of multiple mediacms_web instances and celery_workers. For large deployments, managed postgres, redis and storage may be adopted.
5. Configuration
Several options are available on cms/settings.py, most of the things that are allowed or should be disallowed are described there.
It is advisable to override any of them by adding it to local_settings.py .
In case of a docker compose installation, add to deploy/docker/local_settings.py . This will automatically overwrite cms/local_settings.py .
Any change needs restart of MediaCMS in order to take effect.
#systemctl restart mediacmsDocker Compose installation: edit deploy/docker/local_settings.py, make a change and restart MediaCMS containers
#docker compose restart web celery_worker celery_beat5.1 Change portal logo
Find the default svg files for the white theme on static/images/logo_dark.svg and for the dark theme on static/images/logo_light.svg
You can specify new svg paths to override by editing the PORTAL_LOGO_DARK_SVG and PORTAL_LOGO_LIGHT_SVG variables in settings.py.
You can also use custom pngs, by setting the variables PORTAL_LOGO_DARK_PNG and PORTAL_LOGO_LIGHT_PNG in settings.py. The svg files have priority over png files, so if both are set, svg files will be used.
In any case, make sure the files are placed on the static/images folder.
5.2 Set global portal title
set PORTAL_NAME, eg
PORTAL_NAME = 'my awesome portal'5.3 Control who can add media
By default CAN_ADD_MEDIA = "all" means that all registered users can add media. Other valid options are:
email_verified, a user not only has to register an account but also verify the email (by clicking the link sent upon registration). Apparently email configuration need to work, otherise users won't receive emails.
advancedUser, only users that are marked as advanced users can add media. Admins or MediaCMS managers can make users advanced users by editing their profile and selecting advancedUser.
5.4 What is the portal workflow
The PORTAL_WORKFLOW variable specifies what happens to newly uploaded media, whether they appear on listings (as the index page, or search)
public is the default option and means that a media can appear on listings. If media type is video, it will appear once at least a task that produces an encoded version of the file has finished succesfully. For other type of files, as image/audio they appear instantly
private means that newly uploaded content is private - only users can see it or MediaCMS editors, managers and admins. Those can also set the status to public or unlisted
unlisted means that items are unlisted. However if a user visits the url of an unlisted media, it will be shown (as opposed to private)
5.5 Show or hide the Sign in button
to show button:
LOGIN_ALLOWED = Trueto hide button:
LOGIN_ALLOWED = False5.6 Show or hide the Register button
to show button:
REGISTER_ALLOWED = Trueto hide button:
REGISTER_ALLOWED = False5.7 Show or hide the upload media button
To show:
UPLOAD_MEDIA_ALLOWED = TrueTo hide:
UPLOAD_MEDIA_ALLOWED = False5.8 Show or hide the actions buttons (like/dislike/report)
Make changes (True/False) to any of the following:
- CAN_LIKE_MEDIA = True # whether the like media appears
- CAN_DISLIKE_MEDIA = True # whether the dislike media appears
- CAN_REPORT_MEDIA = True # whether the report media appears
- CAN_SHARE_MEDIA = True # whether the share media appears5.9 Show or hide the download option on a media
Edit templates/config/installation/features.html and set
download: false5.10 Automatically hide media upon being reported
set a low number for variable REPORTED_TIMES_THRESHOLD
eg
REPORTED_TIMES_THRESHOLD = 2once the limit is reached, media goes to private state and an email is sent to admins
5.11 Set a custom message on the media upload page
this message will appear below the media drag and drop form
PRE_UPLOAD_MEDIA_MESSAGE = 'custom message'5.12 Set email settings
Set correct settings per provider
DEFAULT_FROM_EMAIL = '[email protected]'
EMAIL_HOST_PASSWORD = 'xyz'
EMAIL_HOST_USER = '[email protected]'
EMAIL_USE_TLS = True
SERVER_EMAIL = DEFAULT_FROM_EMAIL
EMAIL_HOST = 'mediacms.io'
EMAIL_PORT = 587
ADMIN_EMAIL_LIST = ['[email protected]']5.13 Disallow user registrations from specific domains
Set domains that are not valid for registration via this variable:
RESTRICTED_DOMAINS_FOR_USER_REGISTRATION = [
'xxx.com', 'emaildomainwhatever.com']Alternatively, allow only permitted domains to register. This can be useful if you're using mediacms as a private service within an organization, and want to give free registration for those in the org, but deny registration from all other domains. Setting this option bans all domains NOT in the list from registering. Default is a blank list, which is ignored. To disable, set to a blank list.
ALLOWED_DOMAINS_FOR_USER_REGISTRATION = [
"private.com",
"vod.private.com",
"my.favorite.domain",
"test.private.com"]5.14 Require a review by MediaCMS editors/managers/admins
set value
MEDIA_IS_REVIEWED = Falseany uploaded media now needs to be reviewed before it can appear to the listings.
MediaCMS editors/managers/admins can visit the media page and edit it, where they can see the option to mark media as reviewed. By default this is set to True, so all media don't require to be reviewed
5.15 Specify maximum number of media for a playlist
set a different threshold on variable MAX_MEDIA_PER_PLAYLIST
eg
MAX_MEDIA_PER_PLAYLIST = 145.16 Specify maximum size of a media that can be uploaded
change UPLOAD_MAX_SIZE.
default is 4GB
UPLOAD_MAX_SIZE = 800 * 1024 * 1000 * 55.17 Specify maximum size of comments
change MAX_CHARS_FOR_COMMENT
default:
MAX_CHARS_FOR_COMMENT = 100005.18 How many files to upload in parallel
set a different threshold for UPLOAD_MAX_FILES_NUMBER
default:
UPLOAD_MAX_FILES_NUMBER = 1005.18 force users confirm their email upon registrations
default option for email confirmation is optional. Set this to mandatory in order to force users confirm their email before they can login
ACCOUNT_EMAIL_VERIFICATION = 'optional'5.20 Rate limit account login attempts
after this number is reached
ACCOUNT_LOGIN_ATTEMPTS_LIMIT = 20sets a timeout (in seconds)
ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT = 55.21 Disallow user registration
set the following variable to False
USERS_CAN_SELF_REGISTER = True5.22 Configure notifications
Global notifications that are implemented are controlled by the following options:
USERS_NOTIFICATIONS = {
'MEDIA_ADDED': True,
}If you want to disable notification for new media, set to False
Admins also receive notifications on different events, set any of the following to False to disable
ADMINS_NOTIFICATIONS = {
'NEW_USER': True,
'MEDIA_ADDED': True,
'MEDIA_REPORTED': True,
}- NEW_USER: a new user is added
- MEDIA_ADDED: a media is added
- MEDIA_REPORTED: the report for a media was hit
5.23 Configure only member access to media
- Make the portal workflow public, but at the same time set
GLOBAL_LOGIN_REQUIRED = Trueso that only logged in users can see content. - You can either set
REGISTER_ALLOWED = Falseif you want to add members yourself or checkout options on "django-allauth settings" that affects registration incms/settings.py. Eg set the portal invite only, or set email confirmation as mandatory, so that you control who registers.
5.24 Enable the sitemap
Whether or not to enable generation of a sitemap file at http://your_installation/sitemap.xml (default: False)
GENERATE_SITEMAP = False5.25 Control who can add comments
By default CAN_COMMENT = "all" means that all registered users can add comment. Other valid options are:
email_verified, a user not only has to register an account but also verify the email (by clicking the link sent upon registration). Apparently email configuration need to work, otherise users won't receive emails.
advancedUser, only users that are marked as advanced users can add comment. Admins or MediaCMS managers can make users advanced users by editing their profile and selecting advancedUser.
5.26 Control whether anonymous users can list all users
By default, anonymous users can view the list of all users on the platform. To restrict this to authenticated users only, set:
ALLOW_ANONYMOUS_USER_LISTING = FalseWhen set to False, only logged-in users will be able to access the user listing API endpoint.
5.27 Control who can see the members page
By default CAN_SEE_MEMBERS_PAGE = "all" means that all registered users can see the members page. Other valid options are:
- editors, only MediaCMS editors can view the page
- admins, only MediaCMS admins can view the page
5.28 Configure user search fields
By default, when searching for users (e.g., in bulk actions modals or the users API), the search is performed on the user's name and username. You can configure this behavior using the USER_SEARCH_FIELD setting:
USER_SEARCH_FIELD = "name_username" # Default - searches in name and usernameTo also include email addresses in the search and display them in the user interface:
USER_SEARCH_FIELD = "name_username_email" # Searches in name, username, and emailWhen set to "name_username_email":
- The user search will also match email addresses
- The email field will be returned in the API response
- Frontend components will display users as "Name - Email" instead of "Name - Username"
This setting is useful when you want to make it easier to find users by their email addresses, particularly in administrative interfaces like bulk action modals.
5.29 Require user approval on registration
By default, users do not require approval, so they can login immediately after registration (if registration is open). However, if the parameter USERS_NEEDS_TO_BE_APPROVED is set to True, they will first have to have their accounts approved by an administrator before they can successfully sign in.
Administrators can approve users through the following ways: 1. through Django administration, 2. through the users management page, 3. through editing the profile page directly. In all cases, set 'Is approved' to True.
5.30 Show or hide media count numbers on categories and tags pages
By default, the number of media items is displayed next to each category and tag on the /categories and /tags pages. To hide these numbers:
INCLUDE_LISTING_NUMBERS = FalseTo show the numbers (default behavior):
INCLUDE_LISTING_NUMBERS = TrueThis setting affects only the visual display on the categories and tags listing pages and does not impact the functionality of filtering by categories or tags.
6. Manage pages
to be written
7. Django admin dashboard
8. On portal workflow
Who can publish content, how content appears on public listings.Difference between statuses (private, unlisted, public)
9. On user roles
Differences over MediaCMS manager, MediaCMS editor, logged in user
10. Adding languages for Captions and subtitles
to be written
11. Add/delete categories and tags
Through the admin section - http://your_installation/admin/
12. Video transcoding
Add / remove resolutions and profiles by modifying the database table of Encode profiles through https://your_installation/admin/files/encodeprofile/
For example, the Active state of any profile can be toggled to enable or disable it.
13. How To Add A Static Page To The Sidebar
1. Create your html page in templates/cms/
e.g. duplicate and rename about.html
sudo cp templates/cms/about.html templates/cms/volunteer.html2. Create your css file in static/css/
touch static/css/volunteer.css3. In your html file, update block headermeta to reflect your new page
{% block headermeta %}
<meta property="og:title" content="Volunteer - {{PORTAL_NAME}}">
<meta property="og:type" content="website">
<meta property="og:description" content="">
<meta name="twitter:card" content="summary">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [{
"@type": "ListItem",
"position": 1,
"name": "{{PORTAL_NAME}}",
"item": {
"@type": "WebPage",
"@id": "{{FRONTEND_HOST}}"
}
},
{
"@type": "ListItem",
"position": 2,
"name": "Volunteer",
"item": {
"@type": "VolunteerPage",
"@id": "{{FRONTEND_HOST}}/volunteer"
}
}]
}
</script>
<link href="{% static "css/volunteer.css" %}" rel="stylesheet"/>
{% endblock headermeta %}4. In your html file, update block innercontent to reflect your actual content
Write whatever you like.
5. In your css file, write matching styles for you html file.
Write whatever you like.
6. Add your view to files/views.py
def volunteer(request):
"""Volunteer view"""
context = {}
return render(request, "cms/volunteer.html", context)7. Add your url pattern to files/urls.py
urlpatterns = [
url(r"^$", views.index),
url(r"^about", views.about, name="about"),
url(r"^volunteer", views.volunteer, name="volunteer"),8. Add your page to the left sidebar
To add a link to your page as a menu item in the left sidebar,
add the following code after the last line in _commons.js
/* Checks that a given selector has loaded. */
const checkElement = async selector => {
while ( document.querySelector(selector) === null) {
await new Promise( resolve => requestAnimationFrame(resolve) )
}
return document.querySelector(selector);
};
/* Checks that sidebar nav menu has loaded, then adds menu item. */
checkElement('.nav-menu')
.then((element) => {
(function(){
var a = document.createElement('a');
a.href = "/volunteer";
a.title = "Volunteer";
var s = document.createElement('span');
s.className = "menu-item-icon";
var icon = document.createElement('i');
icon.className = "material-icons";
icon.setAttribute("data-icon", "people");
s.appendChild(icon);
a.appendChild(s);
var linkText = document.createTextNode("Volunteer");
var t = document.createElement('span');
t.appendChild(linkText);
a.appendChild(t);
var listItem = document.createElement('li');
listItem.className = "link-item";
listItem.appendChild(a);
//if signed out use 3rd nav-menu
var elem = document.querySelector(".nav-menu:nth-child(3) nav ul");
var loc = elem.innerText;
if (loc.includes("About")){
elem.insertBefore(listItem, elem.children[2]);
} else { //if signed in use 4th nav-menu
elem = document.querySelector(".nav-menu:nth-child(4) nav ul");
elem.insertBefore(listItem, elem.children[2]);
}
})();
});9. Restart the mediacms web server
On docker:
sudo docker stop mediacms_web_1 && sudo docker start mediacms_web_1Otherwise
sudo systemctl restart mediacms14. Add Google Analytics
Instructions contributed by @alberto98fx
- Create a file:
touch $DIR/mediacms/templates/tracking.html
Add the Gtag/Analytics script
Inside
$DIR/mediacms/templates/root.htmlyou'll see a file like this one:
<head>
{% block head %}
<title>{% block headtitle %}{{PORTAL_NAME}}{% endblock headtitle %}</title>
{% include "common/head-meta.html" %}
{% block headermeta %}
<meta property="og:title" content="{{PORTAL_NAME}}">
<meta property="og:type" content="website">
{%endblock headermeta %}
{% block externallinks %}{% endblock externallinks %}
{% include "common/head-links.html" %}
{% block topimports %}{%endblock topimports %}
{% include "config/index.html" %}
{% endblock head %}
</head>Add
{% include "tracking.html" %}at the end inside the section<head>If you are using Docker and didn't mount the entire dir you need to bind a new volume:
web:
image: mediacms/mediacms:latest
restart: unless-stopped
ports:
- "80:80"
deploy:
replicas: 1
volumes:
- ./templates/root.html:/home/mediacms.io/mediacms/templates/root.html
- ./templates/tracking.html://home/mediacms.io/mediacms/templates/tracking.html15. Debugging email issues
On the Configuration section of this guide we've see how to edit the email settings.
In case we are yet unable to receive email from MediaCMS, the following may help us debug the issue - in most cases it is an issue of setting the correct username, password or TLS option
Enter the Django shell and inside the shell
from django.core.mail import EmailMessage
from django.conf import settings
settings.EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
email = EmailMessage(
'title',
'msg',
settings.DEFAULT_FROM_EMAIL,
['[email protected]'],
)
email.send(fail_silently=False)You have the chance to either receive the email (in this case it will be sent to [email protected]) otherwise you will see the error.
For example, while specifying wrong password for my Gmail account I get
SMTPAuthenticationError: (535, b'5.7.8 Username and Password not accepted. Learn more at\n5.7.8 https://support.google.com/mail/?p=BadCredentials d4sm12687785wrc.34 - gsmtp')16. Frequently Asked Questions
Video is playing but preview thumbnails are not showing for large video files
Chances are that the sprites file was not created correctly.
The output of files.tasks.produce_sprite_from_video() function in this case is something like this
convert-im6.q16: width or height exceeds limit `/tmp/img001.jpg' @ error/cache.c/OpenPixelCache/3912.Solution: edit file /etc/ImageMagick-6/policy.xml and set bigger values for the lines that contain width and height. For example
Newly added video files now will be able to produce the sprites file needed for thumbnail previews. To re-run that task on existing videos, enter the Django shell
root@8433f923ccf5:/home/mediacms.io/mediacms# source /home/mediacms.io/bin/activate
root@8433f923ccf5:/home/mediacms.io/mediacms# python manage.py shell
Python 3.8.14 (default, Sep 13 2022, 02:23:58)and run
In [1]: from files.models import Media
In [2]: from files.tasks import produce_sprite_from_video
In [3]: for media in Media.objects.filter(media_type='video', sprites=''):
...: produce_sprite_from_video(media.friendly_token)this will re-create the sprites for videos that the task failed.
17. Cookie consent code
On file templates/components/header.html you can find a simple cookie consent code. It is commented, so you have to remove the {% comment %} and {% endcomment %} lines in order to enable it. Or you can replace that part with your own code that handles cookie consent banners.
18. Disable encoding and show only original file
When videos are uploaded, they are getting encoded to multiple resolutions, a procedure called transcoding. Sometimes this is not needed and you only need to show the original file, eg when MediaCMS is running on a low capabilities server. To achieve this, edit settings.py and set
DO_NOT_TRANSCODE_VIDEO = TrueThis will disable the transcoding process and only the original file will be shown. Note that this will also disable the sprites file creation, so you will not have the preview thumbnails on the video player.
19. Rounded corners on videos
By default the video player and media items are now having rounded corners, on larger screens (not in mobile). If you don't like this change, set USE_ROUNDED_CORNERS = False in local_settings.py.
20. Translations
20.1 Set a default language
By default MediaCMS is available in a number of languages. To set the default language, edit settings.py and set LANGUAGE_CODE to the code of one of the languages.
20.2 Remove existing languages
To limit the number of languages that are shown as available, remove them from the LANGUAGES list in settings.py or comment them. Only what is there is shown.
20.3 Improve existing translation
To make improvements in existing translated content, in a language that is already translated, check the language by the code name in files/frontend-translations/ and edit the corresponding file.
20.4 Add more content to existing translation
Not all text is translated, so at any time you may find strings missing that need to be added to the translation. The idea here is that
a) you made the text as translatable, in the code
b) you add the translated string
For a), you have to see if the string to be translated lives in the frontend directory (React app) or on the Django templates. There are examples for both.
- the Django templates, which is found in templates/ dir. Have a look on
templates/cms/about.htmlto see an example of how it is done - the frontend code (React), have a look how
translateStringis used infrontend
After the string is marked as translatable, add the string to files/frontend-translations/en.py first, and then run
python manage.py process_translationsIn order to populate the string in all the languages. NO PR will be accepted if this procedure is not followed. You don't have to translate the string to all supported languages, but the command has to run and populate the existing dictionaries with the new strings for all languages. This ensures that there is no missing string to be translated in any language.
After this command is run, translate the string to the language you want. If the string to be translated lives in Django templates, you don't have to re-build the frontend. If the change lives in the frontend, you will have to re-build in order to see the changes. The Makefile command make build-frontend can help with this.
20.5 Add a new language and translate
To add a new language: add the language in settings.py, then add the file in files/frontend-translations/. Make sure you copy the initial strings by copying files/frontend-translations/en.py to it.
21. How to change the video frames on videos
By default while watching a video you can hover and see the small images named sprites that are extracted every 10 seconds of a video. You can change this number to something smaller by performing the following:
- edit ./frontend/src/static/js/components/media-viewer/VideoViewer/index.js and change
seconds: 10to the value you prefer, eg 2. - edit settings.py and set the same number for value SPRITE_NUM_SECS
- now you have to re-build the frontend: the easiest way is to run
make build-frontend, which requires Docker
After that, newly uploaded videos will have sprites generated with the new number of seconds.
22. Role-Based Access Control
By default there are 3 statuses for any Media that lives on the system, public, unlisted, private. When RBAC support is added, a user that is part of a group has access to media that are published to one or more categories that the group is associated with. The workflow is this:
- A Group is created
- A Category is associated with the Group
- A User is added to the Group
Now user can view the Media even if it is in private state. User also sees all media in Category page
When user is added to group, they can be set as Member, Contributor, Manager.
- Member: user can view media that are published on one or more categories that this group is associated with
- Contributor: besides viewing, user can also edit the Media in a category associated with this Group. They can also publish Media to this category
- Manager: same as Contributor for now
Use cases facilitated with RBAC:
- viewing a Media in private state: if RBAC is enabled, if user is Member on a Group that is associated with a Category, and the media is published to this Category, then user can view the media
- editing a Media: if RBAC is enabled, and user is Contributor to one or more Categories, they can publish media to these Categories as long as they are associated with one Group
- viewing all media of a category: if RBAC is enabled, and user visits a Category, they are able to see the listing of all media that are published in this category, independent of their state, provided that the category is associated with a group that the user is member of
- viewing all categories associated with groups the user is member of: if RBAC is enabled, and user visits the listing of categories, they can view all categories that are associated with a group the user is member
How to enable RBAC support:
USE_RBAC = Trueon local_settings.py and restart the instance.
23. SAML setup
SAML authentication is supported along with the option to utilize the SAML response and do useful things as setting up the user role in MediaCMS or participation in groups.
To enable SAML support, edit local_settings.py and set the following options:
USE_RBAC = True
USE_SAML = True
USE_IDENTITY_PROVIDERS = True
USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = True
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
SOCIALACCOUNT_ADAPTER = 'saml_auth.adapter.SAMLAccountAdapter'
SOCIALACCOUNT_PROVIDERS = {
"saml": {
"provider_class": "saml_auth.custom.provider.CustomSAMLProvider",
}
}To set a SAML provider:
- Step 1: Add SAML Identity Provider
- Navigate to Admin panel
- Select "Identity Provider"
- Configure as follows:
- Provider: saml
- Provider ID: an ID for the provider
- IDP Config Name: a name for the provider
- Client ID: the identifier that is part of the login, and that is shared with the IDP.
- Site: Set the default one
- Step 2: Add SAML Configuration
Select the SAML Configurations tab, create a new one and set:
- IDP ID: Must be a URL
- IDP Certificate: x509cert from your SAML provider
- SSO URL:
- SLO URL:
- SP Metadata URL: The metadata URL that the IDP will utilize. This can be https://{portal}/saml/metadata and is autogenerated by MediaCMS
- SP Certificate (optional): SP x509 certificate (PEM). Enables encrypted/signed SAML communication. If set, the SP Private Key must also be provided, and the certificate is published in the SP metadata so the IDP can encrypt assertions to MediaCMS.
- SP Private Key (optional): SP private key (PEM). Used to sign AuthnRequests/LogoutRequests and to decrypt assertions encrypted by the IDP. Required if SP Certificate is provided.
- Step 3: Set other Options
- Email Settings:
verified_email: When enabled, emails from SAML responses will be marked as verifiedRemove from groups: When enabled, user is removed from a group after login, if they have been removed from the group on the IDP
- Global Role Mapping: Maps the role returned by SAML (as set in the SAML Configuration tab) with the role in MediaCMS
- Group Role Mapping: Maps the role returned by SAML (as set in the SAML Configuration tab) with the role in groups that user will be added
- Group mapping: This creates groups associated with this IDP. Group ids as they come from SAML, associated with MediaCMS groups
- Category Mapping: This maps a group id (from SAML response) with a category in MediaCMS
A full SAML deployment with EntraID guide and troubleshooting steps is available here.. This guide can be used as reference for other IDPs too.
24. Identity Providers setup
A separate Django app identity_providers has been added in order to facilitate a number of configurations related to different identity providers. If this is enabled, it gives the following options:
- allows to add an Identity Provider through Django admin, and set a number of mappings, as Group Mapping, Global Role mapping and more. While SAML is the only provider that can be added out of the box, any identity provider supported by django allauth can be added with minimal effort. If the response of the identity provider contains attributes as role, or groups, then these can be mapped to MediaCMS specific roles (advanced user, editor, manager, admin) and groups (rbac groups)
- saves SAML response logs after user is authenticated (can be utilized for other providers too)
- allows to specify a list of login options through the admin (eg system login, identity provider login)
to enable the identity providers, set the following setting on local_settings.py:
USE_IDENTITY_PROVIDERS = TrueVisiting the admin, you will see the Identity Providers tab and you can add one.
25. Custom urls
To enable custom urls, set ALLOW_CUSTOM_MEDIA_URLS = True on settings.py or local_settings.py
This will enable editing the URL of the media, while editing a media. If the URL is already taken you get a message you cannot update this.
26. Allowed files
MediaCMS performs identification attempts on new file uploads and only allows certain file types specified in the ALLOWED_MEDIA_UPLOAD_TYPES setting. By default, only ["video", "audio", "image", "pdf"] files are allowed.
When a file is not identified as one of these allowed types, the file gets removed from the system and there's an entry indicating that this is not a supported media type.
If you want to change the allowed file types, edit the ALLOWED_MEDIA_UPLOAD_TYPES list in your settings.py or local_settings.py file. If 'all' is specified in this list, no check is performed and all files are allowed.
27. User upload limits
MediaCMS allows you to set a maximum number of media files that each user can upload. This is controlled by the NUMBER_OF_MEDIA_USER_CAN_UPLOAD setting in settings.py or local_settings.py. By default, this is set to 100 media items per user.
When a user reaches this limit, they will no longer be able to upload new media until they delete some of their existing content. This limit applies regardless of the user's role or permissions in the system.
To change the maximum number of uploads allowed per user, modify the NUMBER_OF_MEDIA_USER_CAN_UPLOAD value in your settings file:
NUMBER_OF_MEDIA_USER_CAN_UPLOAD = 528. Whisper Transcribe for Automatic Subtitles
MediaCMS can integrate with OpenAI's Whisper to automatically generate subtitles for your media files. This feature is useful for making your content more accessible.
How it works
When the whisper transcribe task is triggered for a media file, MediaCMS runs the whisper command-line tool to process the audio and generate a subtitle file in VTT format. The generated subtitles are then associated with the media and are available under the "automatic" language option.
Configuration
Transcription functionality is available only for the Docker installation. To enable this feature, you must either use the docker-compose.full.yaml file, as it contains an image with the necessary requirements, or you can also set that celery_worker service is usine mediacms:full image instead of mediacms:latest. Then you also have to set the setting: USE_WHISPER_TRANSCRIBE = True in your local_settings.py file.
By default, all users have the ability to send a request for a video to be transcribed, as well as transcribed and translated to English. If you wish to change this behavior, you can edit the settings.py file and set USER_CAN_TRANSCRIBE_VIDEO=False.
The transcription uses the base model of Whisper speech-to-text by default. However, you can change the model by editing the WHISPER_MODEL setting in settings.py.
File: docs/dev_exp.md
Developer Experience
There is ongoing effort to provide a better developer experience and document it.
How to develop locally with Docker
First install a recent version of Docker, and Docker Compose.
Then run docker compose -f docker-compose-dev.yaml up
user@user:~/mediacms$ docker compose -f docker-compose-dev.yaml upIn a few minutes the app will be available at http://localhost . Login via admin/admin
What does docker-compose-dev.yaml do?
It build the two images used for backend and frontend.
- Backend:
mediacms/mediacms-dev:latest - Frontend:
frontend
and will start all services required for MediaCMS, as Celery/Redis for asynchronous tasks, PostgreSQL database, Django and React
For Django, the changes from the image produced by docker-compose.yaml are these:
- Django runs in debug mode, with
python manage.py runserver - gunicorn and nginx are not run
- Django runs in Debug mode, with Debug Toolbar
- Static files (js/css) are loaded from static/ folder
- corsheaders is installed and configured to allow all origins
For React, it will run npm start in the frontend folder, which will start the development server.
Check it on http://localhost:8088/
How to develop in Django
Django starts at http://localhost and is reloading automatically. Making any change to the python code should refresh Django.
If Django breaks due to an error (eg SyntaxError, while editing the code), you might have to restart it
docker compose -f docker-compose-dev.yaml restart webHow to develop in React
React is started on http://localhost:8088/ , code is located in frontend/ , so making changes there should have instant effect on the page. Keep in mind that React is loading data from Django, and that it has to be built so that Django can serve it.
Making changes to the frontend
The way React is added is more complicated than the usual SPA project and this is because React is used as a library loaded by Django Templates, so it is not a standalone project and is not handling routes etc.
The two directories to consider are:
- frontend/src , for the React files
- templates/, for the Django templates.
Django is using a highly intuitive hierarchical templating system (https://docs.djangoproject.com/en/4.2/ref/templates/), where the base template is templates/root.html and all other templates are extending it.
React is called through the Django templates, eg templates/cms/media.html is loading js/media.js
In order to make changes to React code, edit code on frontend/src and check it's effect on http://localhost:8088/ . Once ready, build it and copy it to the Django static folder, so that it is served by Django.
Development workflow with the frontend
- Edit frontend/src/ files
- Check changes on http://localhost:8088/
- Build frontend with
docker compose -f docker-compose-dev.yaml exec frontend npm run dist - Copy static files to Django static folder with
cp -r frontend/dist/static/* static/ - Restart Django -
docker compose -f docker-compose-dev.yaml restart webso that it uses the new static files - Commit the changes
Helper commands
There is ongoing effort to provide helper commands, check the Makefile for what it supports. Eg
Bash into the web container:
user@user:~/mediacms$ make admin-shell
root@ca8c1096726b:/home/mediacms.io/mediacms# ./manage.py shellBuild the frontend:
user@user:~/mediacms$ make build-frontend
docker compose -f docker-compose-dev.yaml exec frontend npm run dist
> [email protected] dist /home/mediacms.io/mediacms/frontend
> mediacms-scripts rimraf ./dist && mediacms-scripts build --config=./config/mediacms.config.js --env=dist
...File: docs/developers_docs.md
Developers documentation
Table of contents
- 1. Welcome
- 2. System architecture
- 3. API documentation
- 4. How to contribute
- 5. Working with Docker tips
- 6. Working with the automated tests
- 7. How video is transcoded
1. Welcome
This page is created for MediaCMS developers and contains related information.
2. System architecture
to be written
3. API documentation
API is documented using Swagger - checkout ot http://your_installation/swagger - example https://demo.mediacms.io/swagger/
This page allows you to login to perform authenticated actions - it will also use your session if logged in.
An example of working with Python requests library:
import requests
auth = ('user' ,'password')
upload_url = "https://domain/api/v1/media"
title = 'x title'
description = 'x description'
media_file = '/tmp/file.mp4'
requests.post(
url=upload_url,
files={'media_file': open(media_file,'rb')},
data={'title': title, 'description': description},
auth=auth
)4. How to contribute
Before you send a PR, make sure your code is properly formatted. For that, use pre-commit install to install a pre-commit hook and run pre-commit run --all and fix everything before you commit. This pre-commit will check for your code lint everytime you commit a code.
Checkout the Code of conduct page if you want to contribute to this repository
5. Working with Docker tips
To perform the Docker installation, follow instructions to install Docker + Docker compose (docs/Docker_Compose.md) and then build/start docker-compose-dev.yaml . This will run the frontend application on port 8088 on top of all other containers (including the Django web application on port 80)
docker compose -f docker-compose-dev.yaml build
docker compose -f docker-compose-dev.yaml upAn admin user is created during the installation process. Its attributes are defined in docker-compose-dev.yaml:
ADMIN_USER: 'admin'
ADMIN_PASSWORD: 'admin'
ADMIN_EMAIL: 'admin@localhost'Frontend application changes
Eg change frontend/src/static/js/pages/HomePage.tsx , dev application refreshes in a number of seconds (hot reloading) and I see the changes, once I'm happy I can run
docker compose -f docker-compose-dev.yaml exec -T frontend npm run distAnd then in order for the changes to be visible on the application while served through nginx,
cp -r frontend/dist/static/* static/POST calls: cannot be performed through the dev server, you have to make through the normal application (port 80) and then see changes on the dev application on port 8088.
Make sure the urls are set on frontend/.env if different than localhost
Media page: need to upload content through the main application (nginx/port 80), and then use an id for page media.html, for example http://localhost:8088/media.html?m=nc9rotyWP
There are some issues with CORS too to resolve, in order for some pages to function, eg the manage comments page
http://localhost:8088/manage-media.html manage_mediaBackend application changes
After I make changes to the django application (eg make a change on files/forms.py) in order to see the changes I have to restart the web container
docker compose -f docker-compose-dev.yaml restart webHow video is transcoded
Original files get uploaded to the application server, and they get stored there as FileFields.
If files are videos and the duration is greater than a number (defined on settings, I think 4minutes), they are also broken in chunks, so one Encode object per chunk, for all enabled EncodeProfiles.
Then the workers start picking Encode objects and they transcode the chunks, so if a chunk gets transcoded correctly, the original file (the small chunk) gets replaced by the transcoded file, and the Encode object status is marked as 'success'.
original.mp4 (1G, 720px)--> Encode1 (100MB, 240px, chunk=True), Encode2 (100MB, 240px, chunk=True)...EncodeXX (100MB, 720px, chunk=True) ---> when all Encode objects are success, for a resolution, they get concatenated to the original_resolution.mp4 file and this gets stored as Encode object (chunk=False). This is what is available for download.
Apparently the Encode object is used to store Encoded files that are served eventually (chunk=False, status='success'), but also files while they are on their way to get transcoded (chunk=True, status='pending/etc')
(Parenthesis opening)
there is also an experimental small service (not commited to the repo currently) that speaks only through API and a) gets tasks to run, b) returns results. So it makes a request and receives an ffmpeg command, plus a file, it runs the ffmpeg command, and returns the result.I've used this mechanism on a number of installations to migrate existing videos through more servers/cpu and has worked with only one problem, some temporary files needed to be removed from the servers (through a periodic task, not so big problem)
(Parenthesis closing)
When the Encode object is marked as success and chunk=False, and thus is available for download/stream, there is a task that gets started and saves an HLS version of the file (1 mp4-->x number of small .ts chunks). This would be FILES_C
This mechanism allows for workers that have access on the same filesystem (either localhost, or through a shared network filesystem, eg NFS/EFS) to work on the same time and produce results.
6. Working with the automated tests
This instructions assume that you're using the docker installation
- start docker-compose
docker compose up- Install the requirements on
requirements-dev.txton web container (we'll use the web container for this)
docker compose exec -T web pip install -r requirements-dev.txt- Now you can run the existing tests
docker compose exec --env TESTING=True -T web pytestThe TESTING=True is passed for Django to be aware this is a testing environment (so that it runs Celery tasks as functions for example and not as background tasks, since Celery is not started in the case of pytest)
- You may try a single test, by specifying the path, for example
docker compose exec --env TESTING=True -T web pytest tests/test_fixtures.py- You can also see the coverage
docker compose exec --env TESTING=True -T web pytest --cov=. --cov-report=htmland of course...you are very welcome to help us increase it ;)
File: docs/user_docs.md
Users documentation
Table of contents
- Uploading media
- Downloading media
- Adding captions/subtitles
- Search media
- Using Timestamps for sharing
- Mentionning users in comments
- Show comments in the Timebar
- Share media
- Embed media
- Customize my profile options
- Trim videos
Uploading media
How to Upload Media
Uploading media is as simple as clicking the Upload Media button, waiting for media to upload, and then clicking the media to add metadata (title, description etc.) by filling out a form.
Click Upload Button
Click the Upload Media button from the right-side of the screen at the top:
Upload Page
Clicking the Upload Media button takes you to the upload page at a URL like this:
https://demo.mediacms.io/upload
Click Browse Button
Here you should click the "Browse your files" button (or drag and drop a file from your desktop):
Select media file and click Open button
Select the media file that you want to upload and click the "Open" button:
Wait for file to upload
Wait for the file to finish uploading:
Pause uploading
If you want you can pause upload by clicking Pause button:
Continue uploading
Continue upload by clicking Continue button:
Wait for media to finish Processing
Wait for the media file to finish Processing:
Click View media button
Click the View media button to open the media page:
Media will be in the encoding queue
The media will take some time to finish encoding (MediaCMS will transcode the file to several formats and resolutions). Meanwhile you can edit the media file to add metadata.
Click Edit Media button
Click the EDIT MEDIA button to add metadata and configure the poster image:
Add Metadata (Summary, Description etc.)
Make sure you fill in all the required fields, and try to complete as many of the non-required fields as possible. This ensures the database is populated with useful meta-data to help others access useful information about you and your video.
Downloading media
MediaCMS offers a configurable option whereby users can make their media files available for download. Downloads are available for transcoded files, and the original file.
How To Enable Download
Visit the media view page and choose the EDIT MEDIA button.
Select the checkbox for "Allow Downloads"
How To Download Media
Visit the media view page and click the DOWNLOAD button below the video player.
Choose the version you wish to download - a transcoded file or the original file:
Choose Save File and click the OK button.
Adding captions/subtitles
With MediaCMS you can add subtitles/captions to your video by uploading a subtitles file in the popular .vtt format.
Visit Media Page & Click EDIT SUBTITLE Button
Visit the "single media page" for the media you wish to add subtitles/captions to and click the EDIT SUBTITLES button:
Upload Subtitles in .vtt Format
Click the Language menu to select the correct language for your Subtitles/Captions file:
Choose the correct Language for your file:
Click Browse to find a subtitles/captions file on your computer (if your file is not in the .vtt format, you may find a conversion service on the Internet):
Choose a .vtt subtitles/captions file from your computer:
Click the Add button to add the file to your media:
View Subtitles/Captions in Video Player
You can now watch the captions/subtitles play back in the video player - and toggle display on/off by clicking the CC button:
Using Timestamps for sharing
Using Timestamp in the URL
An additional GET parameter 't' can be added in video URL's to start the video at the given time. The starting time has to be given in seconds.
Additionally the share button has an option to generate the URL with the timestamp at current second the video is.
Using Timestamp in the comments
Comments can also include timestamps. They are automatically detected upon posting the comment, and will be in the form of an hyperlink link in the comment. The timestamps in the comments have to follow the format HH:MM:SS or MM:SS
Mentionning users in comments
Comments can also mention other users by tagging with '@'. This will open suggestion box showing usernames, and the selection will refine as the user continues typing.
Comments send with mentions will contain a link to the user page, and can be setup to send a mail to the mentionned user.
Show comments in the Timebar
When enabled, comments including a timestamp will also be displayed in the current video Timebar as a little colorful dot. The comment can be previewed by hovering the dot (left image) and it will be displayed on top of the video when reaching the correct time (right image).
Only comments with correct timestamps formats (HH:MM:SS or MM:SS) will be picked up and appear in the Timebar.
Search media
How search can be used
Share media
How to share media
Embed media
How to use the embed media option
Customize my profile options
Customize profile and channel
Trim videos
Once a video is uploaded, you can trim it to create a new video or to replace the original one. You can also create segments of the video, which will be available as separate videos. Edit the video and click on the "Trime Video" option. If the original video has finished processing (encodings are created for all resolutions), then this is an action that runs instantly. If the original video hasn't processed, which is the case when you upload a video and edit it right away, then the trim action will trigger processing of the video and will take some time to finish. In all cases, you get to see the original video (or the trimmed versions) immediately, so you are sure of what you have uploaded or trimmed, with a message that the video is being processed.