Compare commits

..

6 Commits

Author SHA1 Message Date
Markos Gogoulos
e8d3ff25be Disable encoding and show only original file (#829)
Disable encoding and show only original file #829
2023-11-10 14:25:10 +02:00
Markos Gogoulos
15d217453b Update admins_docs.md (#842) 2023-07-17 16:47:06 +03:00
Markos Gogoulos
029665145e Python requirements and Docker version upgrades (#826)
v3.0.0: Python, Django, Celery and other version upgrades
2023-07-03 13:40:39 +03:00
Adi
487e098b96 Upgrade postgres docker compose (#749)
* Upgrade PG to latest stable version alpine
2023-07-03 13:39:15 +03:00
Markos Gogoulos
fe7427a1f2 check resolution for HLS (#832) 2023-07-03 12:19:23 +03:00
Markos Gogoulos
4bf41fe80e fix issue with AVI not being recognised as videos (#833) 2023-07-03 12:18:24 +03:00
26 changed files with 212 additions and 81 deletions

View File

@@ -1,4 +1,4 @@
FROM python:3.8-buster AS compile-image FROM python:3.11.4-bookworm AS compile-image
SHELL ["/bin/bash", "-c"] SHELL ["/bin/bash", "-c"]
@@ -24,7 +24,7 @@ RUN wget -q http://zebulon.bok.net/Bento4/binaries/Bento4-SDK-1-6-0-637.x86_64-u
rm Bento4-SDK-1-6-0-637.x86_64-unknown-linux.zip rm Bento4-SDK-1-6-0-637.x86_64-unknown-linux.zip
############ RUNTIME IMAGE ############ ############ RUNTIME IMAGE ############
FROM python:3.8-slim-buster as runtime-image FROM python:3.11.4-bookworm as runtime-image
ENV PYTHONUNBUFFERED=1 ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONDONTWRITEBYTECODE=1

View File

@@ -1,4 +1,4 @@
FROM mediacms/mediacms:latest FROM python:3.11.4-bookworm AS compile-image
SHELL ["/bin/bash", "-c"] SHELL ["/bin/bash", "-c"]
@@ -7,10 +7,65 @@ ENV VIRTUAL_ENV=/home/mediacms.io
ENV PATH="$VIRTUAL_ENV/bin:$PATH" ENV PATH="$VIRTUAL_ENV/bin:$PATH"
ENV PIP_NO_CACHE_DIR=1 ENV PIP_NO_CACHE_DIR=1
RUN cd /home/mediacms.io && python3 -m venv $VIRTUAL_ENV RUN mkdir -p /home/mediacms.io/mediacms/{logs} && cd /home/mediacms.io && python3 -m venv $VIRTUAL_ENV
# Install dependencies:
COPY requirements.txt . COPY requirements.txt .
COPY requirements-dev.txt . COPY requirements-dev.txt .
RUN pip install -r requirements-dev.txt RUN pip install -r requirements-dev.txt
COPY . /home/mediacms.io/mediacms
WORKDIR /home/mediacms.io/mediacms WORKDIR /home/mediacms.io/mediacms
RUN wget -q http://zebulon.bok.net/Bento4/binaries/Bento4-SDK-1-6-0-637.x86_64-unknown-linux.zip && \
unzip Bento4-SDK-1-6-0-637.x86_64-unknown-linux.zip -d ../bento4 && \
mv ../bento4/Bento4-SDK-1-6-0-637.x86_64-unknown-linux/* ../bento4/ && \
rm -rf ../bento4/Bento4-SDK-1-6-0-637.x86_64-unknown-linux && \
rm -rf ../bento4/docs && \
rm Bento4-SDK-1-6-0-637.x86_64-unknown-linux.zip
############ RUNTIME IMAGE ############
FROM python:3.11.4-bookworm as runtime-image
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
# See: https://github.com/celery/celery/issues/6285#issuecomment-715316219
ENV CELERY_APP='cms'
# Use these to toggle which processes supervisord should run
ENV ENABLE_UWSGI='yes'
ENV ENABLE_NGINX='yes'
ENV ENABLE_CELERY_BEAT='yes'
ENV ENABLE_CELERY_SHORT='yes'
ENV ENABLE_CELERY_LONG='yes'
ENV ENABLE_MIGRATIONS='yes'
# Set up virtualenv
ENV VIRTUAL_ENV=/home/mediacms.io
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
COPY --chown=www-data:www-data --from=compile-image /home/mediacms.io /home/mediacms.io
RUN apt-get update -y && apt-get -y upgrade && apt-get install --no-install-recommends \
supervisor nginx imagemagick procps wget xz-utils -y && \
rm -rf /var/lib/apt/lists/* && \
apt-get purge --auto-remove && \
apt-get clean
RUN wget -q https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz && \
mkdir -p ffmpeg-tmp && \
tar -xf ffmpeg-release-amd64-static.tar.xz --strip-components 1 -C ffmpeg-tmp && \
cp -v ffmpeg-tmp/ffmpeg ffmpeg-tmp/ffprobe ffmpeg-tmp/qt-faststart /usr/local/bin && \
rm -rf ffmpeg-tmp ffmpeg-release-amd64-static.tar.xz
WORKDIR /home/mediacms.io/mediacms
EXPOSE 9000 80
RUN chmod +x ./deploy/docker/entrypoint.sh
ENTRYPOINT ["./deploy/docker/entrypoint.sh"]
CMD ["./deploy/docker/start.sh"]

View File

@@ -1,5 +1,15 @@
# History # History
## 3.0.0
### Features
- Updates Python/Django requirements and Dockerfile to use latest 3.11 Python - https://github.com/mediacms-io/mediacms/pull/826/files. This update requires some manual steps, for existing (not new) installations. Check the update section under the [Admin docs](https://github.com/mediacms-io/mediacms/blob/main/docs/admins_docs.md#2-server-installation), either for single server or for Docker Compose installations
- Upgrade postgres on Docker Compose - https://github.com/mediacms-io/mediacms/pull/749
### Fixes
- video player options for HLS - https://github.com/mediacms-io/mediacms/pull/832
- AVI videos not correctly recognised as videos - https://github.com/mediacms-io/mediacms/pull/833
## 2.1.0 ## 2.1.0
### Fixes ### Fixes

View File

@@ -59,7 +59,7 @@ def login():
file.writelines(f'USERNAME={json.loads(response.text)["username"]}\n') file.writelines(f'USERNAME={json.loads(response.text)["username"]}\n')
print(f"Welcome to MediaCMS [bold blue]{username}[/bold blue]. Your auth creds have been suceesfully stored in the .env file", ":v:") print(f"Welcome to MediaCMS [bold blue]{username}[/bold blue]. Your auth creds have been suceesfully stored in the .env file", ":v:")
else: else:
print(f'Error: {"non_field_errors":["User not found."]}') print(f'Error: {"non_field_errors": ["User not found."]}')
@apis.command() @apis.command()

View File

@@ -467,7 +467,7 @@ except ImportError:
if "http" not in FRONTEND_HOST: if "http" not in FRONTEND_HOST:
# FRONTEND_HOST needs a http:// preffix # FRONTEND_HOST needs a http:// preffix
FRONTEND_HOST = f"http://{FRONTEND_HOST}" FRONTEND_HOST = f"http://{FRONTEND_HOST}" # noqa
if LOCAL_INSTALL: if LOCAL_INSTALL:
SSL_FRONTEND_HOST = FRONTEND_HOST.replace("http", "https") SSL_FRONTEND_HOST = FRONTEND_HOST.replace("http", "https")
@@ -485,3 +485,8 @@ if GLOBAL_LOGIN_REQUIRED:
r'/accounts/confirm-email/.*/$', r'/accounts/confirm-email/.*/$',
r'/api/v[0-9]+/', r'/api/v[0-9]+/',
] ]
# if True, only show original, don't perform any action on videos
DO_NOT_TRANSCODE_VIDEO = False
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'

View File

@@ -1,7 +1,7 @@
import debug_toolbar import debug_toolbar
from django.conf.urls import include, re_path from django.conf.urls import include
from django.contrib import admin from django.contrib import admin
from django.urls import path from django.urls import path, re_path
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
from drf_yasg import openapi from drf_yasg import openapi
from drf_yasg.views import get_schema_view from drf_yasg.views import get_schema_view

View File

@@ -8,15 +8,13 @@ User=www-data
Group=www-data Group=www-data
Restart=always Restart=always
RestartSec=10 RestartSec=10
Environment=APP_DIR="/home/mediacms.io/mediacms" WorkingDirectory=/home/mediacms.io/mediacms
Environment=CELERY_BIN="/home/mediacms.io/bin/celery" Environment=CELERY_BIN="/home/mediacms.io/bin/celery"
Environment=CELERY_APP="cms"
Environment=CELERYD_PID_FILE="/home/mediacms.io/mediacms/pids/beat%n.pid" Environment=CELERYD_PID_FILE="/home/mediacms.io/mediacms/pids/beat%n.pid"
Environment=CELERYD_LOG_FILE="/home/mediacms.io/mediacms/logs/beat%N.log" Environment=CELERYD_LOG_FILE="/home/mediacms.io/mediacms/logs/beat%N.log"
Environment=CELERYD_LOG_LEVEL="INFO" Environment=CELERYD_LOG_LEVEL="INFO"
Environment=APP_DIR="/home/mediacms.io/mediacms"
ExecStart=/bin/sh -c '${CELERY_BIN} beat -A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS} --workdir=${APP_DIR}' ExecStart=/bin/sh -c '${CELERY_BIN} -A cms beat --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL}'
ExecStop=/bin/kill -s TERM $MAINPID ExecStop=/bin/kill -s TERM $MAINPID
[Install] [Install]

View File

@@ -8,23 +8,21 @@ User=www-data
Group=www-data Group=www-data
Restart=always Restart=always
RestartSec=10 RestartSec=10
Environment=APP_DIR="/home/mediacms.io/mediacms" WorkingDirectory=/home/mediacms.io/mediacms
Environment=CELERYD_NODES="long1" Environment=CELERYD_NODES="long1"
Environment=CELERY_QUEUE="long_tasks" Environment=CELERY_QUEUE="long_tasks"
Environment=CELERY_BIN="/home/mediacms.io/bin/celery" Environment=CELERY_BIN="/home/mediacms.io/bin/celery"
Environment=CELERY_APP="cms"
Environment=CELERYD_MULTI="multi" Environment=CELERYD_MULTI="multi"
Environment=CELERYD_OPTS="-Ofair --prefetch-multiplier=1" Environment=CELERYD_OPTS="-Ofair --prefetch-multiplier=1"
Environment=CELERYD_PID_FILE="/home/mediacms.io/mediacms/pids/%n.pid" Environment=CELERYD_PID_FILE="/home/mediacms.io/mediacms/pids/%n.pid"
Environment=CELERYD_LOG_FILE="/home/mediacms.io/mediacms/logs/%N.log" Environment=CELERYD_LOG_FILE="/home/mediacms.io/mediacms/logs/%N.log"
Environment=CELERYD_LOG_LEVEL="INFO" Environment=CELERYD_LOG_LEVEL="INFO"
Environment=APP_DIR="/home/mediacms.io/mediacms"
ExecStart=/bin/sh -c '${CELERY_BIN} multi start ${CELERYD_NODES} -A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS} --workdir=${APP_DIR} -Q ${CELERY_QUEUE}' ExecStart=/bin/sh -c '${CELERY_BIN} -A cms multi start ${CELERYD_NODES} --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS} -Q ${CELERY_QUEUE}'
ExecStop=/bin/sh -c '${CELERY_BIN} multi stopwait ${CELERYD_NODES} --pidfile=${CELERYD_PID_FILE}' ExecStop=/bin/sh -c '${CELERY_BIN} -A cms multi stopwait ${CELERYD_NODES} --pidfile=${CELERYD_PID_FILE}'
ExecReload=/bin/sh -c '${CELERY_BIN} multi restart ${CELERYD_NODES} -A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS} --workdir=${APP_DIR} -Q ${CELERY_QUEUE}' ExecReload=/bin/sh -c '${CELERY_BIN} -A cms multi restart ${CELERYD_NODES} --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS} -Q ${CELERY_QUEUE}'
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

View File

@@ -8,14 +8,13 @@ User=www-data
Group=www-data Group=www-data
Restart=always Restart=always
RestartSec=10 RestartSec=10
Environment=APP_DIR="/home/mediacms.io/mediacms" WorkingDirectory=/home/mediacms.io/mediacms
Environment=CELERYD_NODES="short1 short2" Environment=CELERYD_NODES="short1 short2"
Environment=CELERY_QUEUE="short_tasks" Environment=CELERY_QUEUE="short_tasks"
# Absolute or relative path to the 'celery' command: # Absolute or relative path to the 'celery' command:
Environment=CELERY_BIN="/home/mediacms.io/bin/celery" Environment=CELERY_BIN="/home/mediacms.io/bin/celery"
# App instance to use # App instance to use
# comment out this line if you don't use an app # comment out this line if you don't use an app
Environment=CELERY_APP="cms"
# or fully qualified: # or fully qualified:
#CELERY_APP="proj.tasks:app" #CELERY_APP="proj.tasks:app"
# How to call manage.py # How to call manage.py
@@ -28,13 +27,12 @@ Environment=CELERYD_OPTS="--soft-time-limit=300 -c10"
Environment=CELERYD_PID_FILE="/home/mediacms.io/mediacms/pids/%n.pid" Environment=CELERYD_PID_FILE="/home/mediacms.io/mediacms/pids/%n.pid"
Environment=CELERYD_LOG_FILE="/home/mediacms.io/mediacms/logs/%N.log" Environment=CELERYD_LOG_FILE="/home/mediacms.io/mediacms/logs/%N.log"
Environment=CELERYD_LOG_LEVEL="INFO" Environment=CELERYD_LOG_LEVEL="INFO"
Environment=APP_DIR="/home/mediacms.io/mediacms"
ExecStart=/bin/sh -c '${CELERY_BIN} multi start ${CELERYD_NODES} -A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS} --workdir=${APP_DIR} -Q ${CELERY_QUEUE}' ExecStart=/bin/sh -c '${CELERY_BIN} -A cms multi start ${CELERYD_NODES} --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS} -Q ${CELERY_QUEUE}'
ExecStop=/bin/sh -c '${CELERY_BIN} multi stopwait ${CELERYD_NODES} --pidfile=${CELERYD_PID_FILE}' ExecStop=/bin/sh -c '${CELERY_BIN} -A cms multi stopwait ${CELERYD_NODES} --pidfile=${CELERYD_PID_FILE}'
ExecReload=/bin/sh -c '${CELERY_BIN} multi restart ${CELERYD_NODES} -A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS} --workdir=${APP_DIR} -Q ${CELERY_QUEUE}' ExecReload=/bin/sh -c '${CELERY_BIN} -A cms multi restart ${CELERYD_NODES} --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS} -Q ${CELERY_QUEUE}'
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

View File

@@ -32,7 +32,7 @@ services:
db: db:
condition: service_healthy condition: service_healthy
db: db:
image: postgres:13 image: postgres:15.2-alpine
volumes: volumes:
- ../postgres_data:/var/lib/postgresql/data/ - ../postgres_data:/var/lib/postgresql/data/
restart: always restart: always
@@ -40,8 +40,9 @@ services:
POSTGRES_USER: mediacms POSTGRES_USER: mediacms
POSTGRES_PASSWORD: mediacms POSTGRES_PASSWORD: mediacms
POSTGRES_DB: mediacms POSTGRES_DB: mediacms
TZ: Europe/London
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U mediacms"] test: ["CMD-SHELL", "pg_isready", "--host=db", "--dbname=$POSTGRES_DB", "--username=$POSTGRES_USER"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 5 retries: 5

View File

@@ -68,7 +68,7 @@ services:
depends_on: depends_on:
- migrations - migrations
db: db:
image: postgres:13 image: postgres:15.2-alpine
volumes: volumes:
- ../postgres_data/:/var/lib/postgresql/data/ - ../postgres_data/:/var/lib/postgresql/data/
restart: always restart: always
@@ -76,8 +76,9 @@ services:
POSTGRES_USER: mediacms POSTGRES_USER: mediacms
POSTGRES_PASSWORD: mediacms POSTGRES_PASSWORD: mediacms
POSTGRES_DB: mediacms POSTGRES_DB: mediacms
TZ: Europe/London
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U mediacms"] test: ["CMD-SHELL", "pg_isready", "--host=db", "--dbname=$POSTGRES_DB", "--username=$POSTGRES_USER"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 5 retries: 5

View File

@@ -70,7 +70,7 @@ services:
depends_on: depends_on:
- migrations - migrations
db: db:
image: postgres:13 image: postgres:15.2-alpine
volumes: volumes:
- ../postgres_data/:/var/lib/postgresql/data/ - ../postgres_data/:/var/lib/postgresql/data/
restart: always restart: always
@@ -78,8 +78,9 @@ services:
POSTGRES_USER: mediacms POSTGRES_USER: mediacms
POSTGRES_PASSWORD: mediacms POSTGRES_PASSWORD: mediacms
POSTGRES_DB: mediacms POSTGRES_DB: mediacms
TZ: Europe/London
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U mediacms"] test: ["CMD-SHELL", "pg_isready", "--host=db", "--dbname=$POSTGRES_DB", "--username=$POSTGRES_USER"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 5 retries: 5

View File

@@ -90,7 +90,7 @@ services:
depends_on: depends_on:
- migrations - migrations
db: db:
image: postgres:13 image: postgres:15.2-alpine
volumes: volumes:
- ../postgres_data:/var/lib/postgresql/data/ - ../postgres_data:/var/lib/postgresql/data/
restart: always restart: always
@@ -98,8 +98,9 @@ services:
POSTGRES_USER: mediacms POSTGRES_USER: mediacms
POSTGRES_PASSWORD: mediacms POSTGRES_PASSWORD: mediacms
POSTGRES_DB: mediacms POSTGRES_DB: mediacms
TZ: Europe/London
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U mediacms"] test: ["CMD-SHELL", "pg_isready", "--host=db", "--dbname=$POSTGRES_DB", "--username=$POSTGRES_USER"]
interval: 30s interval: 30s
timeout: 10s timeout: 10s
retries: 5 retries: 5

View File

@@ -66,7 +66,7 @@ services:
depends_on: depends_on:
- migrations - migrations
db: db:
image: postgres:13 image: postgres:15.2-alpine
volumes: volumes:
- postgres_data:/var/lib/postgresql/data/ - postgres_data:/var/lib/postgresql/data/
restart: always restart: always
@@ -74,8 +74,9 @@ services:
POSTGRES_USER: mediacms POSTGRES_USER: mediacms
POSTGRES_PASSWORD: mediacms POSTGRES_PASSWORD: mediacms
POSTGRES_DB: mediacms POSTGRES_DB: mediacms
TZ: Europe/London
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U mediacms"] test: ["CMD-SHELL", "pg_isready", "--host=db", "--dbname=$POSTGRES_DB", "--username=$POSTGRES_USER"]
interval: 30s interval: 30s
timeout: 10s timeout: 10s
retries: 5 retries: 5

View File

@@ -62,7 +62,7 @@ services:
depends_on: depends_on:
- migrations - migrations
db: db:
image: postgres:13 image: postgres:15.2-alpine
volumes: volumes:
- ../postgres_data:/var/lib/postgresql/data/ - ../postgres_data:/var/lib/postgresql/data/
restart: always restart: always
@@ -70,8 +70,9 @@ services:
POSTGRES_USER: mediacms POSTGRES_USER: mediacms
POSTGRES_PASSWORD: mediacms POSTGRES_PASSWORD: mediacms
POSTGRES_DB: mediacms POSTGRES_DB: mediacms
TZ: Europe/London
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U mediacms"] test: ["CMD-SHELL", "pg_isready", "--host=db", "--dbname=$POSTGRES_DB", "--username=$POSTGRES_USER"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 5 retries: 5

View File

@@ -18,19 +18,19 @@
- [15. Debugging email issues](#15-debugging-email-issues) - [15. Debugging email issues](#15-debugging-email-issues)
- [16. Frequently Asked Questions](#16-frequently-asked-questions) - [16. Frequently Asked Questions](#16-frequently-asked-questions)
- [17. Cookie consent code](#17-cookie-consent-code) - [17. Cookie consent code](#17-cookie-consent-code)
- [18. Disable encoding and show only original file](#18-disable-encoding-and-show-only-original-file)
## 1. Welcome ## 1. Welcome
This page is created for MediaCMS administrators that are responsible for setting up the software, maintaining it and making modifications. This page is created for MediaCMS administrators that are responsible for setting up the software, maintaining it and making modifications.
## 2. Server Installation ## 2. Server Installation
The core dependencies are Python3, Django3, Celery, PostgreSQL, Redis, ffmpeg. Any system that can have these dependencies installed, can run MediaCMS. But we strongly suggest installing on Linux Ubuntu 18 or 20 versions. The core dependencies are Python3, Django3, Celery, PostgreSQL, Redis, ffmpeg. Any system that can have these dependencies installed, can run MediaCMS. But we strongly suggest installing on Linux Ubuntu (tested on versions 20, 22).
Installation on a Ubuntu 18 or 20 system with git utility installed should be completed in a few minutes with the following steps. Installation on an Ubuntu system with git utility installed should be completed in a few minutes with the following steps.
Make sure you run it as user root, on a clear system, since the automatic script will install and configure the following services: Celery/PostgreSQL/Redis/Nginx and will override any existing settings. Make sure you run it as user root, on a clear system, since the automatic script will install and configure the following services: Celery/PostgreSQL/Redis/Nginx and will override any existing settings.
Automated script - tested on Ubuntu 18, Ubuntu 20, and Debian Buster Automated script - tested on Ubuntu 20, Ubuntu 22 and Debian Buster
```bash ```bash
mkdir /home/mediacms.io && cd /home/mediacms.io/ mkdir /home/mediacms.io && cd /home/mediacms.io/
@@ -49,10 +49,25 @@ If you've used the above way to install MediaCMS, update with the following:
cd /home/mediacms.io/mediacms # enter mediacms directory cd /home/mediacms.io/mediacms # enter mediacms directory
source /home/mediacms.io/bin/activate # use virtualenv source /home/mediacms.io/bin/activate # use virtualenv
git pull # update code git pull # update code
pip install -r requirements.txt -U # run pip install to update
python manage.py migrate # run Django migrations python manage.py migrate # run Django migrations
sudo systemctl restart mediacms celery_long celery_short # restart services sudo systemctl restart mediacms celery_long celery_short # restart services
``` ```
### Update from version 2 to version 3
Version 3 is using Django 4 and Celery 5, and needs a recent Python 3.x version. If you are updating from an older version, make sure Python is updated first. Version 2 could run on Python 3.6, but version 3 needs Python3.8 and higher.
The syntax for starting Celery has also changed, so you have to copy the celery related systemctl files and restart
```
# cp deploy/local_install/celery_long.service /etc/systemd/system/celery_long.service
# cp deploy/local_install/celery_short.service /etc/systemd/system/celery_short.service
# cp deploy/local_install/celery_beat.service /etc/systemd/system/celery_beat.service
# systemctl daemon-reload
# systemctl start celery_long celery_short celery_beat
```
### Configuration ### Configuration
Checkout the configuration section here. Checkout the configuration section here.
@@ -66,7 +81,7 @@ Database can be backed up with pg_dump and media_files on /home/mediacms.io/medi
## Installation ## Installation
Install a recent version of [Docker](https://docs.docker.com/get-docker/), and [Docker Compose](https://docs.docker.com/compose/install/). Install a recent version of [Docker](https://docs.docker.com/get-docker/), and [Docker Compose](https://docs.docker.com/compose/install/).
For Ubuntu 18/20 systems this is: For Ubuntu 20/22 systems this is:
```bash ```bash
curl -fsSL https://get.docker.com -o get-docker.sh curl -fsSL https://get.docker.com -o get-docker.sh
@@ -112,6 +127,18 @@ docker-compose down
docker-compose up docker-compose up
``` ```
### Update 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 ## Configuration
Checkout the configuration docs here. Checkout the configuration docs here.
@@ -735,3 +762,12 @@ this will re-create the sprites for videos that the task failed.
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. 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.
![Simple Cookie Consent](images/cookie_consent.png) ![Simple Cookie Consent](images/cookie_consent.png)
## 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 = True
```
This 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.

View File

@@ -538,8 +538,8 @@ def get_base_ffmpeg_command(
target_width = round(target_height * 16 / 9) target_width = round(target_height * 16 / 9)
scale_filter_opts = [ scale_filter_opts = [
f"if(lt(iw\\,ih)\\,{target_height}\\,{target_width})", f"if(lt(iw\\,ih)\\,{target_height}\\,{target_width})", # noqa
f"if(lt(iw\\,ih)\\,{target_width}\\,{target_height})", f"if(lt(iw\\,ih)\\,{target_width}\\,{target_height})", # noqa
"force_original_aspect_ratio=decrease", "force_original_aspect_ratio=decrease",
"force_divisible_by=2", "force_divisible_by=2",
"flags=lanczos", "flags=lanczos",

View File

@@ -427,12 +427,16 @@ class Media(models.Model):
Performs all related tasks, as check for media type, Performs all related tasks, as check for media type,
video duration, encode video duration, encode
""" """
self.set_media_type() self.set_media_type()
if self.media_type == "video": if self.media_type == "video":
self.set_thumbnail(force=True) self.set_thumbnail(force=True)
self.produce_sprite_from_video() if settings.DO_NOT_TRANSCODE_VIDEO:
self.encode() self.encoding_status = "success"
self.save()
self.produce_sprite_from_video()
else:
self.produce_sprite_from_video()
self.encode()
elif self.media_type == "image": elif self.media_type == "image":
self.set_thumbnail(force=True) self.set_thumbnail(force=True)
return True return True
@@ -477,7 +481,10 @@ class Media(models.Model):
self.duration = int(round(float(ret.get("video_duration", 0)))) self.duration = int(round(float(ret.get("video_duration", 0))))
self.video_height = int(ret.get("video_height")) self.video_height = int(ret.get("video_height"))
if ret.get("video_info", {}).get("codec_name", {}) in ["mjpeg"]: if ret.get("video_info", {}).get("codec_name", {}) in ["mjpeg"]:
audio_file_with_thumb = True # best guess that this is an audio file with a thumbnail
# in other cases, it is not (eg it can be an AVI file)
if ret.get("video_info", {}).get("avg_frame_rate", "") == '0/0':
audio_file_with_thumb = True
if ret.get("is_audio") or audio_file_with_thumb: if ret.get("is_audio") or audio_file_with_thumb:
self.media_type = "audio" self.media_type = "audio"
@@ -665,6 +672,13 @@ class Media(models.Model):
return ret return ret
for key in ENCODE_RESOLUTIONS_KEYS: for key in ENCODE_RESOLUTIONS_KEYS:
ret[key] = {} ret[key] = {}
# if this is enabled, return original file on a way
# that video.js can consume
if settings.DO_NOT_TRANSCODE_VIDEO:
ret['0-original'] = {"h264": {"url": helpers.url_from_path(self.media_file.path), "status": "success", "progress": 100}}
return ret
for encoding in self.encodings.select_related("profile").filter(chunk=False): for encoding in self.encodings.select_related("profile").filter(chunk=False):
if encoding.profile.extension == "gif": if encoding.profile.extension == "gif":
continue continue
@@ -816,6 +830,7 @@ class Media(models.Model):
""" """
res = {} res = {}
valid_resolutions = [240, 360, 480, 720, 1080, 1440, 2160]
if self.hls_file: if self.hls_file:
if os.path.exists(self.hls_file): if os.path.exists(self.hls_file):
hls_file = self.hls_file hls_file = self.hls_file
@@ -827,11 +842,20 @@ class Media(models.Model):
uri = os.path.join(p, iframe_playlist.uri) uri = os.path.join(p, iframe_playlist.uri)
if os.path.exists(uri): if os.path.exists(uri):
resolution = iframe_playlist.iframe_stream_info.resolution[1] resolution = iframe_playlist.iframe_stream_info.resolution[1]
# most probably video is vertical, getting the first value to
# be the resolution
if resolution not in valid_resolutions:
resolution = iframe_playlist.iframe_stream_info.resolution[0]
res["{}_iframe".format(resolution)] = helpers.url_from_path(uri) res["{}_iframe".format(resolution)] = helpers.url_from_path(uri)
for playlist in m3u8_obj.playlists: for playlist in m3u8_obj.playlists:
uri = os.path.join(p, playlist.uri) uri = os.path.join(p, playlist.uri)
if os.path.exists(uri): if os.path.exists(uri):
resolution = playlist.stream_info.resolution[1] resolution = playlist.stream_info.resolution[1]
# same as above
if resolution not in valid_resolutions:
resolution = playlist.stream_info.resolution[0]
res["{}_playlist".format(resolution)] = helpers.url_from_path(uri) res["{}_playlist".format(resolution)] = helpers.url_from_path(uri)
return res return res

View File

@@ -7,10 +7,11 @@ import tempfile
from datetime import datetime, timedelta from datetime import datetime, timedelta
from celery import Task from celery import Task
from celery.decorators import task from celery import shared_task as task
from celery.exceptions import SoftTimeLimitExceeded from celery.exceptions import SoftTimeLimitExceeded
from celery.signals import task_revoked from celery.signals import task_revoked
from celery.task.control import revoke
# from celery.task.control import revoke
from celery.utils.log import get_task_logger from celery.utils.log import get_task_logger
from django.conf import settings from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
@@ -460,10 +461,11 @@ def check_running_states():
if (now - encoding.update_date).seconds > settings.RUNNING_STATE_STALE: if (now - encoding.update_date).seconds > settings.RUNNING_STATE_STALE:
media = encoding.media media = encoding.media
profile = encoding.profile profile = encoding.profile
task_id = encoding.task_id # task_id = encoding.task_id
# terminate task # terminate task
if task_id: # TODO: not imported
revoke(task_id, terminate=True) # if task_id:
# revoke(task_id, terminate=True)
encoding.delete() encoding.delete()
media.encode(profiles=[profile]) media.encode(profiles=[profile])
# TODO: allign with new code + chunksize... # TODO: allign with new code + chunksize...

View File

@@ -1,7 +1,7 @@
from django.conf import settings from django.conf import settings
from django.conf.urls import include, re_path from django.conf.urls import include
from django.conf.urls.static import static from django.conf.urls.static import static
from django.urls import path from django.urls import path, re_path
from . import management_views, views from . import management_views, views
from .feeds import IndexRSSFeed, SearchRSSFeed from .feeds import IndexRSSFeed, SearchRSSFeed

View File

@@ -1,6 +1,5 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
from celery.task.control import revoke
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
@@ -1396,5 +1395,6 @@ class TaskDetail(APIView):
permission_classes = (permissions.IsAdminUser,) permission_classes = (permissions.IsAdminUser,)
def delete(self, request, uid, format=None): def delete(self, request, uid, format=None):
revoke(uid, terminate=True) # This is not imported!
# revoke(uid, terminate=True)
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)

View File

@@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# should be run as root and only on Ubuntu 18/20, Debian 10/11 (Buster/Bullseye) versions! # should be run as root and only on Ubuntu 20/22, Debian 10/11 (Buster/Bullseye) versions!
echo "Welcome to the MediacMS installation!"; echo "Welcome to the MediacMS installation!";
if [ `id -u` -ne 0 ] if [ `id -u` -ne 0 ]
@@ -22,11 +22,11 @@ done
osVersion=$(lsb_release -d) osVersion=$(lsb_release -d)
if [[ $osVersion == *"Ubuntu 20"* ]] || [[ $osVersion == *"Ubuntu 18"* ]] || [[ $osVersion == *"buster"* ]] || [[ $osVersion == *"bullseye"* ]]; then if [[ $osVersion == *"Ubuntu 20"* ]] || [[ $osVersion == *"Ubuntu 22"* ]] || [[ $osVersion == *"buster"* ]] || [[ $osVersion == *"bullseye"* ]]; then
echo 'Performing system update and dependency installation, this will take a few minutes' echo 'Performing system update and dependency installation, this will take a few minutes'
apt-get update && apt-get -y upgrade && apt-get install python3-venv python3-dev virtualenv redis-server postgresql nginx git gcc vim unzip imagemagick python3-certbot-nginx certbot wget xz-utils -y apt-get update && apt-get -y upgrade && apt-get install python3-venv python3-dev virtualenv redis-server postgresql nginx git gcc vim unzip imagemagick python3-certbot-nginx certbot wget xz-utils -y
else else
echo "This script is tested for Ubuntu 18 and 20 versions only, if you want to try MediaCMS on another system you have to perform the manual installation" echo "This script is tested for Ubuntu 20/22 versions only, if you want to try MediaCMS on another system you have to perform the manual installation"
exit exit
fi fi

View File

@@ -1,21 +1,21 @@
Django==3.1.12 Django==4.2.2
djangorestframework==3.12.2 djangorestframework==3.14.0
django-allauth==0.44.0 django-allauth==0.54.0
psycopg2-binary==2.8.6 psycopg==3.1.9
uwsgi==2.0.19.1 uwsgi==2.0.21
django-redis==4.12.1 django-redis==5.3.0
celery==4.4.7 celery==5.3.1
drf-yasg==1.20.0 drf-yasg==1.21.6
Pillow==8.2.0 Pillow==9.5.0
django-imagekit==4.1.0 django-imagekit==4.1.0
markdown==3.3.6 markdown==3.4.3
django-filter==21.1 django-filter==23.2
filetype==1.0.10 filetype==1.2.0
django-mptt==0.13.4 django-mptt==0.14.0
django-crispy-forms==1.13.0 django-crispy-forms==1.13.0
requests==2.25.0 requests==2.31.0
django-celery-email==3.0.0 django-celery-email==3.0.0
m3u8==1.0.0 m3u8==3.5.0
django-ckeditor==6.2.0 django-ckeditor==6.6.1
django-debug-toolbar==3.2.4 django-debug-toolbar==4.1.0
django-login-required-middleware==0.6.1 django-login-required-middleware==0.9.0

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.conf.urls import re_path from django.urls import re_path
from . import views from . import views

View File

@@ -1,5 +1,4 @@
from django.conf.urls import re_path from django.urls import path, re_path
from django.urls import path
from . import views from . import views

View File

@@ -1 +1 @@
VERSION = "2.0.0" VERSION = "3.0.0"