MediaCMS 9.4.0 配置参数详解

按功能域逐项详解 MediaCMS 9.4.0 的 local_settings 配置体系:工作流、上传限制、转码、认证、邮件、存储与任务队列,附中小团队生产配置模板与生效验证方法。

MediaCMSMediaCMS2026/10/29

MediaCMS 9.4.0 配置参数详解

目标:系统梳理 MediaCMS 9.4.0 的配置体系——参数的存放位置、查看与修改方法、分类逐项含义,并给出生产环境推荐配置模板。全部参数均从实测部署的 9.4.0 镜像内置配置文件中核对,覆盖机制已在 Ubuntu 24.04 实测生效。

一、环境信息

本文基于以下实测环境,所有配置项均从实际部署的 MediaCMS 9.4.0 中核对:

  • 操作系统:Ubuntu 24.04.5 LTS(x86_64)
  • MediaCMS 版本:9.4.0(应用内版本文件 cms/version.py 实测为 VERSION = "9.4.0")
  • 应用根目录:/home/mediacms.io/mediacms/(官方镜像与源码部署的标准路径,下文所有配置文件路径均基于此)
  • 配套组件:PostgreSQL 17.2、Redis 8.10.3、Python 3.13.16、nginx 1.26.3、FFmpeg 7.0.2
  • 配置生效方式验证:修改 local_settings.py 后重启应用服务,实测配置变化在门户界面与 API 返回中即时体现

二、前置条件

阅读与操作本文内容前,需具备以下条件:

  1. 已有一套可运行的 MediaCMS 9.4.0 部署(部署过程见 《MediaCMS 9.4.0 Docker Compose 部署指南》),并能进入应用根目录。
  2. 理解 Django 配置层级:MediaCMS 是 Django 应用,配置本质是 Python 模块变量;settings.py 是全量默认值,local_settings.py 是官方预留的覆盖层。
  3. 管理员账号:部分参数(编码配置、分类等数据库侧配置)需在管理后台 /admin/ 操作,用管理员账号登录。

三、参数查看与修改方式

3.1 配置文件的存放与优先级

MediaCMS 9.4.0 的配置按以下优先级从低到高生效:

层级文件路径说明
1 默认层/home/mediacms.io/mediacms/cms/settings.py全量默认配置(实测 701 行),不建议直接修改(升级会被覆盖)
2 覆盖层/home/mediacms.io/mediacms/cms/local_settings.py官方预留的本地覆盖文件,settings.py 末尾通过 from .local_settings import * 引入
3 环境变量容器/服务环境变量仅覆盖少数启动项(ENABLE_* 服务开关、数据库连接、SECRET_KEY)

覆盖机制的实测依据——cms/settings.py 末尾的引入代码(实测原样照抄):

try:
    # keep a local_settings.py file for local overrides
    from .local_settings import *  # noqa

    # ALLOWED_HOSTS needs a url/ip
    ALLOWED_HOSTS.append(FRONTEND_HOST.replace("http://", "").replace("https://", ""))
except ImportError:
    # local_settings not in use
    pass

# Don't add new settings below that could be overridden in local_settings.py!!!

⚠️ 注意:settings.py 末尾这句注释是官方明确的分界线——新增配置项必须写在其上方才能被 local_settings.py 覆盖。另外 settings.py 中 SECRET_KEY 在 9.4.0 不再内置默认值:优先读环境变量 SECRET_KEY,否则读应用根目录的 .secret_key 文件,两者都没有会直接抛 RuntimeError 拒绝启动(实测配置代码如下):

SECRET_KEY = os.getenv('SECRET_KEY')
if not SECRET_KEY:
    _secret_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '.secret_key')
    if os.path.exists(_secret_path):
        with open(_secret_path) as _f:
            SECRET_KEY = _f.read().strip()
if not SECRET_KEY:
    raise RuntimeError("SECRET_KEY is not set. Set the SECRET_KEY env var or create a .secret_key file at the project root.")

3.2 修改参数的标准流程

以「关闭自助注册」为例的完整操作闭环(其余参数同法):

第一步,编辑(或创建)覆盖文件 cms/local_settings.py,加入覆盖项:

USERS_CAN_SELF_REGISTER = False

第二步,重启应用服务使配置生效(配置在进程启动时加载,改完必须重启):

systemctl restart mediacms

第三步,验证生效——门户前台登录区的「注册」入口消失,或用 Django shell 读当前值:

python manage.py shell -c "from django.conf import settings; print(settings.USERS_CAN_SELF_REGISTER)"

实测回显:

53 objects imported automatically (use -v 2 for details).
False

3.3 数据库侧配置(非文件参数)

有一类「配置」存在数据库而非文件:转码配置(Encode profiles)。在管理后台 首页 › Files › Encode profiles(路径 /admin/files/encodeprofile/)中可启用/停用各档分辨率与编码器,或用 API 查看(实测回显节选):

curl -s -u admin:q1w2e3r4 http://127.0.0.1:8137/api/v1/encode_profiles/
[
    {"name": "h264-144", "extension": "mp4", "resolution": 144, "codec": "h264"},
    {"name": "h264-240", "extension": "mp4", "resolution": 240, "codec": "h264"},
    {"name": "vp9-240", "extension": "webm", "resolution": 240, "codec": "vp9"},
    {"name": "h265-240", "extension": "mp4", "resolution": 240, "codec": "h265"},
    {"name": "h265-360", "extension": "mp4", "resolution": 360, "codec": "h265"}
]

💡 技术拓展:视频编码器三选对比——H.264(兼容性最好、硬解普及率最高,浏览器全支持)、H.265/HEVC(同画质体积省约 40%,但浏览器支持碎片化,Safari 完整支持、Chrome 依赖硬件)、VP9(Google 开放编码,WebM 容器,Chrome/Firefox 支持好)。MediaCMS 内置三者的编码配置并存,实际为每个上传视频生成哪些档位由 Encode profiles 表中「Active」的行决定,本站实测默认激活的是 h264 系列(144p/240p/360p…直到 2160p)。

四、参数总览

cms/settings.py 实测 701 行、约 200 个配置项,按功能域归纳如下(每个域的代表性参数,详细含义见第五章对应小节):

功能域代表参数作用
门户标识PORTAL_NAME、PORTAL_DESCRIPTION、FRONTEND_HOST、PORTAL_LOGO_*站名、描述、对外地址、Logo
工作流PORTAL_WORKFLOW、MEDIA_IS_REVIEWED、GLOBAL_LOGIN_REQUIRED上传内容如何进入公开列表
上传限制UPLOAD_MAX_SIZE、NUMBER_OF_MEDIA_USER_CAN_UPLOAD、ALLOWED_MEDIA_UPLOAD_TYPES、CAN_ADD_MEDIA谁能传、传多大、传什么类型
转码播放FFMPEG_COMMAND、FFMPEG_DEFAULT_PRESET、CHUNKIZE_VIDEO_DURATION、MINIMUM_RESOLUTIONS_TO_ENCODE、DO_NOT_TRANSCODE_VIDEOFFmpeg 行为与转码策略
注册认证USERS_CAN_SELF_REGISTER、ACCOUNT_EMAIL_VERIFICATION、USE_SAML、USE_RBAC、USE_LTI注册策略与企业身份集成
互动功能CAN_LIKE_MEDIA、CAN_COMMENT、REPORTED_TIMES_THRESHOLD、ALLOW_RATINGS点赞/评论/举报开关
邮件通知EMAIL_HOST、EMAIL_PORT、EMAIL_USE_TLS、USERS_NOTIFICATIONSSMTP 与通知矩阵
存储路径MEDIA_ROOT、MEDIA_UPLOAD_DIR、HLS_DIR、USE_X_ACCEL_REDIRECT媒体文件落盘与受保护下载
缓存任务REDIS_LOCATION、CACHES、CELERY_BEAT_SCHEDULE、CELERY_SOFT_TIME_LIMITRedis 与异步任务
界面语言LANGUAGE_CODE、LANGUAGES、DEFAULT_THEME、USE_ROUNDED_CORNERS语言与外观

关键差异解读:文件层参数(local_settings.py)覆盖的是 Django 应用行为;数据库层配置(Encode profiles)覆盖的是逐档转码开关——两者配合决定「传进来什么、转成什么样、谁能看到」。

五、核心参数分类详解

5.1 门户基础标识

门户身份四件套,是部署后最先要改的参数(实测默认值照抄自 settings.py):

PORTAL_NAME = "MediaCMS"
PORTAL_DESCRIPTION = ""
TIME_ZONE = "Europe/London"

FRONTEND_HOST = "http://localhost"
  • PORTAL_NAME:站点名,出现在页面标题、OG 分享卡片、邮件抬头。实测部署中将其改为中文站名后,页面 <title> 与 og:site_name 均即时变化。
  • PORTAL_DESCRIPTION:站点描述,用于 SEO 与分享卡片。
  • TIME_ZONE:后台与定时任务使用的时区,中文环境建议 Asia/Shanghai。
  • FRONTEND_HOST:最重要的对外地址。API 返回的所有 URL(媒体页、缩略图、作者主页)都以它拼接,与实际访问地址不符会出现「API 正常但返回的链接打不开」。必须带 http:// 或 https:// 前缀(settings.py 末尾会做一次补前缀兜底,但显式写全更稳);端口非 80/443 时必须带上端口,如 http://192.168.1.10:8137。
  • Logo 系列:PORTAL_LOGO_DARK_SVG / PORTAL_LOGO_LIGHT_SVG / PORTAL_LOGO_DARK_PNG / PORTAL_LOGO_LIGHT_PNG,SVG 优先于 PNG;自定义 Logo 文件放在 static/images/ 目录。

5.2 门户工作流与可见性

决定「内容上传后如何见光」,运营策略的核心:

# valid choices here are 'public', 'private', 'unlisted
PORTAL_WORKFLOW = "public"

MEDIA_IS_REVIEWED = True  # whether an admin needs to review a media file.

GLOBAL_LOGIN_REQUIRED = False
  • PORTAL_WORKFLOW = "public":新上传内容默认进入公开列表(视频需等至少一档转码完成);"private" 则只有作者与编辑/管理者可见;"unlisted" 不进列表但链接可访问。三种状态对应媒体三态,作者也可在编辑页逐个调整。
  • MEDIA_IS_REVIEWED = True:默认免审核。设为 False 后每条新上传必须由编辑/管理者/管理员在编辑页手动标记 reviewed 才会出现在公开列表——内容合规站点的必开项。
  • GLOBAL_LOGIN_REQUIRED = False:设为 True 时整个门户仅登录用户可见(实测该开关会向 Django 中间件链注入 LoginRequiredMiddleware,匿名访问任意页面都会跳登录)。

5.3 上传与媒体限制

# who can add media
# valid options include 'all', 'email_verified', 'advancedUser'
CAN_ADD_MEDIA = "all"

# bytes, size of uploaded media
UPLOAD_MAX_SIZE = 800 * 1024 * 1000 * 5

ALLOWED_MEDIA_UPLOAD_TYPES = ["video", "audio", "image", "pdf"]

# Maximum number of media a user can upload
NUMBER_OF_MEDIA_USER_CAN_UPLOAD = 100
  • CAN_ADD_MEDIA:all 所有注册用户可传;email_verified 需先完成邮箱验证(依赖邮件服务可用);advancedUser 仅高级用户。实测超限或不满足条件时 API 返回 {"detail":"You don't have permission to upload media, or have reached max number of media uploads."}。
  • UPLOAD_MAX_SIZE:单文件上限,默认表达式折算约 4GB(官方文档同口径);nginx 侧的 client_max_body_size 需同步放大。
  • ALLOWED_MEDIA_UPLOAD_TYPES:允许的媒体类型,默认视频/音频/图片/PDF 四类;上传后系统会识别文件类型,不在清单内的文件会被删除并记录「不支持的媒体类型」。设为 ["all"] 可跳过检查(不建议公开站点使用)。
  • NUMBER_OF_MEDIA_USER_CAN_UPLOAD:每用户上传总数上限,达到后禁止继续上传直到删除旧内容。

5.4 转码与播放

转码链路的全部关键参数(实测默认值照抄):

FFMPEG_COMMAND = "ffmpeg"  # this is the path
FFPROBE_COMMAND = "ffprobe"  # this is the path
MP4HLS = "mp4hls"

# for videos, after that duration get split into chunks
# and encoded independently
CHUNKIZE_VIDEO_DURATION = 60 * 5
# aparently this has to be smaller than VIDEO_CHUNKIZE_DURATION
VIDEO_CHUNKS_DURATION = 60 * 4

# always get these two, even if upscaling
MINIMUM_RESOLUTIONS_TO_ENCODE = [144, 240]

# ffmpeg options
FFMPEG_DEFAULT_PRESET = "medium"  # see https://trac.ffmpeg.org/wiki/Encode/H.264

# if True, only show original, don't perform any action on videos
DO_NOT_TRANSCODE_VIDEO = False

USE_WHISPER_TRANSCRIBE = False
WHISPER_MODEL = "base"
  • FFMPEG_COMMAND / FFPROBE_COMMAND / MP4HLS_COMMAND:三个外部工具的路径,镜像内已就位无需改;源码自装时指向实际安装路径(MP4HLS_COMMAND 指向 Bento4 SDK 内的 mp4hls)。
  • CHUNKIZE_VIDEO_DURATION = 300:超过 5 分钟的视频分块转码(官方开发者文档口径为 4 分钟量级,以实测配置文件 300 秒为准),每块独立转码成功后再按分辨率拼接成成品——大视频转码可横向扩展到多个 worker 并行的关键。
  • VIDEO_CHUNKS_DURATION = 240:每块 4 分钟,必须小于分块阈值。
  • MINIMUM_RESOLUTIONS_TO_ENCODE = [144, 240]:无论原片多小都保底生成这两档(必要时升采样),保证低配终端可播。实测一段 6 秒测试视频转码后 HLS 主清单自动出现 144p 与 240p 两档自适应流。
  • FFMPEG_DEFAULT_PRESET = "medium":x264 preset,可选 ultrafast→veryslow 十档;越慢体积越小耗时越长,转码吞吐不足时可降为 veryfast。
  • DO_NOT_TRANSCODE_VIDEO = False:低配服务器救命开关,设 True 后只播原片,转码、雪碧图预览全部跳过(官方文档第 18 节行为,实测确认配置项存在)。
  • USE_WHISPER_TRANSCRIBE / WHISPER_MODEL:自动字幕开关与 Whisper 模型档位(base 起,可换 small/medium 等);需 mediacms:full 镜像才有转写能力。
  • SPRITE_NUM_SECS = 10:播放进度条悬停雪碧图的抽帧间隔(秒)。

5.5 用户注册与身份认证

注册策略与三个企业级身份开关:

USERS_CAN_SELF_REGISTER = True

ACCOUNT_EMAIL_VERIFICATION = "optional"  # 'mandatory' 'none'
ACCOUNT_LOGIN_METHODS = {"username", "email"}
USERS_NEEDS_TO_BE_APPROVED = False
ALLOWED_DOMAINS_FOR_USER_REGISTRATION = []
RESTRICTED_DOMAINS_FOR_USER_REGISTRATION = ["xxx.com", "emaildomainwhatever.com"]

USE_SAML = False
USE_RBAC = False
USE_IDENTITY_PROVIDERS = False
USE_LTI = False  # Enable LTI 1.3 integration
  • USERS_CAN_SELF_REGISTER = False 即关闭自助注册(改为管理员后台手工建号),实测是私有部署最常用的一项。
  • ACCOUNT_EMAIL_VERIFICATION:mandatory 强制邮箱验证后才能登录(需邮件服务正常);optional 可跳过;none 完全不发验证邮件。
  • USERS_NEEDS_TO_BE_APPROVED = True 时新用户注册后需管理员在后台批准(Is approved 置真)才能登录。
  • ALLOWED_DOMAINS_FOR_USER_REGISTRATION:白名单域注册(企业内用),空列表禁用;RESTRICTED_DOMAINS_FOR_USER_REGISTRATION 为黑名单域。
  • 四个 USE_* 开关默认全关,按需开启:USE_RBAC(组→分类的私有媒体授权体系)、USE_SAML(SAML 单点登录,配合管理后台 Identity Provider 配置)、USE_IDENTITY_PROVIDERS(身份提供方框架)、USE_LTI(LTI 1.3,对接 Moodle 等 LMS;开启后 Django 会自动强制 SESSION_COOKIE_SECURE 等安全 Cookie,意味着必须 HTTPS)。

5.6 互动功能开关

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 appears
REPORTED_TIMES_THRESHOLD = 10
ALLOW_ANONYMOUS_ACTIONS = ["report", "like", "dislike", "watch"]  # need be a list

# who can comment
# valid options include 'all', 'email_verified', 'advancedUser'
CAN_COMMENT = "all"
MAX_CHARS_FOR_COMMENT = 10000  # so that it doesn't end up huge
ALLOW_RATINGS = False
  • 四个 CAN_*_MEDIA 控制点赞/点踩/举报/分享按钮的显示与可用;CAN_COMMENT 控制评论资格(取值同 CAN_ADD_MEDIA)。
  • REPORTED_TIMES_THRESHOLD:被举报达到该次数自动转私有并邮件通知管理员,公开站点建议调低(如 2)。
  • ALLOW_ANONYMOUS_ACTIONS:允许匿名执行的动作清单;从清单移除动作后对应按钮对未登录用户隐藏。
  • ALLOW_RATINGS:五星评分功能,官方注释明确标注实验性(experimental functionality for user ratings - does not work),生产不要开启。

5.7 邮件与通知

DEFAULT_FROM_EMAIL = "info@mediacms.io"
EMAIL_HOST_PASSWORD = "xyz"
EMAIL_HOST_USER = "info@mediacms.io"
EMAIL_USE_TLS = True
SERVER_EMAIL = DEFAULT_FROM_EMAIL
EMAIL_HOST = "mediacms.io"
EMAIL_PORT = 587
ADMIN_EMAIL_LIST = ["info@mediacms.io"]

USERS_NOTIFICATIONS = {
    "MEDIA_ADDED": True,  # in use
    "MEDIA_ENCODED": False,  # not implemented
    "MEDIA_REPORTED": True,  # in use
}
ADMINS_NOTIFICATIONS = {
    "NEW_USER": True,  # in use
    "MEDIA_ADDED": True,  # in use
    "MEDIA_ENCODED": False,  # not implemented
    "MEDIA_REPORTED": True,  # in use
}
  • SMTP 八件套按邮件服务商填改;EMAIL_BACKEND 默认走 Celery 邮件队列(djcelery_email.backends.CeleryEmailBackend,投递到 short_tasks 队列异步发送),邮件发送慢不影响页面响应。
  • EMAIL_HOST_PASSWORD 属系统级真实凭据,生产环境不要把明文写进 settings.py——放在 local_settings.py(该文件在私有部署盘上,权限可控)或以环境变量注入后读取。
  • 通知矩阵:注释标明 MEDIA_ENCODED 尚未实现;生效的三项分别是「用户新媒体通知」「举报达标通知」「管理员新用户/新媒体/举报通知」。

5.8 存储路径与受保护下载

MEDIA_ROOT = BASE_DIR + "/media_files/"

MEDIA_UPLOAD_DIR = "original/"
MEDIA_ENCODING_DIR = "encoded/"
THUMBNAIL_UPLOAD_DIR = f"{MEDIA_UPLOAD_DIR}/thumbnails/"
SUBTITLES_UPLOAD_DIR = f"{MEDIA_UPLOAD_DIR}/subtitles/"
HLS_DIR = os.path.join(MEDIA_ROOT, "hls/")

# Protect media files via nginx auth_request
USE_X_ACCEL_REDIRECT = True
X_ACCEL_PROTECTED_PATHS = ["encoded", "hls", "original"]
X_ACCEL_AUTH_CACHE_SECONDS = 300
  • MEDIA_ROOT:全部媒体文件的根目录,磁盘扩容/迁移时改这一处(配合操作系统层的挂载点)。
  • 子目录约定:original/(原始上传)→ encoded/(转码 MP4)→ hls/(HLS 切片)+ 缩略图/字幕目录,备份脚本按此清单覆盖全部资产。
  • USE_X_ACCEL_REDIRECT = True:私有媒体的访问保护机制——nginx 收到 /media/... 请求时先向 Django 的 /_media_auth 端点确认用户是否有权访问该媒体(按媒体 state 与用户身份判定),有权才由 nginx 内部重定向吐文件。X_ACCEL_PROTECTED_PATHS 列出受保护的子目录(encoded/hls/original),X_ACCEL_AUTH_CACHE_SECONDS = 300 是鉴权结果的缓存时长。若自建前置 nginx,必须保留官方配置中的 location = /_media_auth 与三个 /media/ 位置块(官方管理员文档 Custom nginx configuration 节明确要求)。

5.9 缓存、Celery 与周期任务

REDIS_LOCATION = "redis://127.0.0.1:6379/1"
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": REDIS_LOCATION,
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        },
    }
}
BROKER_URL = REDIS_LOCATION
CELERY_RESULT_BACKEND = BROKER_URL
CELERY_SOFT_TIME_LIMIT = 2 * 60 * 60
CELERY_WORKER_PREFETCH_MULTIPLIER = 1

CELERY_BEAT_SCHEDULE = {
    "clear_sessions": {"task": "clear_sessions", "schedule": crontab(hour=1, minute=1, day_of_week=6)},
    "get_list_of_popular_media": {"task": "get_list_of_popular_media", "schedule": crontab(minute=1, hour="*/10")},
    "update_listings_thumbnails": {"task": "update_listings_thumbnails", "schedule": crontab(minute=2, hour="*/30")},
}
  • REDIS_LOCATION:同时充当 Django 缓存与 Celery broker/结果后端(库号 1);会话也存 Redis(SESSION_ENGINE = "django.contrib.sessions.backends.cache")。
  • CELERY_SOFT_TIME_LIMIT = 7200:单个任务软超时 2 小时,超长视频转码接近该上限时可上调。
  • CELERY_WORKER_PREFETCH_MULTIPLIER = 1:worker 预取数为 1,防止长任务被单 worker 囤积导致其他 worker 空转,转码场景的正确姿势,不要改大。
  • 周期任务三项:周六 1:01 清过期会话、每 10 分钟刷新热门榜单、每 30 分钟更新列表缩略图;改频度直接编辑 crontab() 参数。

5.10 界面语言与外观

LANGUAGE_CODE = 'en'  # default language

LANGUAGES = [
    ('ar', _('Arabic')),
    ('zh-hans', _('Simplified Chinese')),
    ('zh-hant', _('Traditional Chinese')),
    # ... 共 22 种语言
]

DEFAULT_THEME = "light"
USE_ROUNDED_CORNERS = True
VIDEO_PLAYER_FEATURED_VIDEO_ON_INDEX_PAGE = False
LOAD_FROM_CDN = False
  • LANGUAGE_CODE:默认界面语言,中文站点设为 'zh-hans';LANGUAGES 列表决定语言切换菜单里出现的语言,删减列表项即可精简。
  • DEFAULT_THEME:light/dark 两套主题;USE_ROUNDED_CORNERS 控制视频卡片与播放器圆角。
  • LOAD_FROM_CDN = False:默认不从公共 CDN 拉字体/JS,全部本地静态资源——内网/合规部署保持默认即可。

六、生产配置模板

以下是一份面向「中小团队内部视频门户」场景的生产模板(适用规模:50–500 用户、单机 8 核 16GB 内存、500GB NVMe SSD、日上传 10GB 量级),放入 cms/local_settings.py 后重启应用服务生效:

# ===== 门户标识 =====
PORTAL_NAME = '团队视频站'
TIME_ZONE = 'Asia/Shanghai'
FRONTEND_HOST = 'https://video.example.com'   # 与实际对外访问地址一致

# ===== 工作流与可见性 =====
PORTAL_WORKFLOW = 'private'          # 上传后默认私有,编辑审核后公开
MEDIA_IS_REVIEWED = False            # 强制人工审核后才进公开列表
GLOBAL_LOGIN_REQUIRED = False        # 公开页可匿名看;全站私有则改 True

# ===== 上传限制 =====
CAN_ADD_MEDIA = 'email_verified'     # 邮箱验证通过才能上传
UPLOAD_MAX_SIZE = 2 * 1024 * 1024 * 1024   # 单文件 2GB
NUMBER_OF_MEDIA_USER_CAN_UPLOAD = 50
ALLOWED_MEDIA_UPLOAD_TYPES = ['video', 'image', 'pdf']

# ===== 转码 =====
FFMPEG_DEFAULT_PRESET = 'veryfast'   # 8 核机器吞吐优先
MINIMUM_RESOLUTIONS_TO_ENCODE = [144, 240]

# ===== 注册与认证 =====
USERS_CAN_SELF_REGISTER = False      # 管理员建号制
ACCOUNT_EMAIL_VERIFICATION = 'optional'

# ===== 互动 =====
REPORTED_TIMES_THRESHOLD = 2
ALLOW_ANONYMOUS_ACTIONS = ['watch']  # 匿名仅可观看

# ===== 邮件 =====
EMAIL_HOST = 'smtp.example.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'video@example.com'
EMAIL_HOST_PASSWORD = os.getenv('SMTP_PASSWORD')   # 经环境变量注入,勿落明文
DEFAULT_FROM_EMAIL = 'video@example.com'

# ===== 存储与安全 =====
USE_X_ACCEL_REDIRECT = True          # 私有媒体鉴权下载
DEBUG = False

模板要点解读:审核链路(PORTAL_WORKFLOW='private' + MEDIA_IS_REVIEWED=False)保证内容先审后放;UPLOAD_MAX_SIZE 从默认 4GB 收紧到 2GB 与 16GB 内存机器的转码能力匹配;SMTP 密码经环境变量注入(编排中为服务加 SMTP_PASSWORD: ${SMTP_PASSWORD} 并在宿主机导出),不落任何文件明文。更大规模(多 worker 转码、对象存储、SAML 对接)的扩展方式见官方管理员文档第 4 节与第 22–24 节。

七、常见问题(FAQ)

Q1:改了配置为什么不生效? 三步排查:确认改的是 cms/local_settings.py 而非 settings.py;确认书写的是合法 Python(缩进、引号、布尔大写 True/False);确认已重启应用服务(systemctl restart mediacms 或对应服务重启)。配置只在进程启动时加载,不重启不生效。

Q2:local_settings.py 与 deploy/docker/local_settings.py 是什么关系? Docker 部署下,容器入口每次启动会把 deploy/docker/local_settings.py 复制为 cms/local_settings.py 再启动应用。所以要持久化自定义,应挂载覆盖 deploy/docker/local_settings.py(编排文件挂载方法见部署篇第八节),而不是直接改 cms/local_settings.py(会被下次启动覆盖)。

Q3:SECRET_KEY 报 RuntimeError 起不来? 9.4.0 要求显式提供签名密钥:设 SECRET_KEY 环境变量,或在应用根目录放 .secret_key 文件(内容为随机串)。生成方式:python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())" > .secret_key。官方镜像的入口脚本会在首次启动时自动生成该文件。

Q4:设置 CAN_ADD_MEDIA = 'email_verified' 后大家都不能上传了? 该档位依赖邮件链路正常(注册验证邮件能送达)。先用管理员文档第 15 节的 Django shell 方式发一封测试邮件排障:from django.core.mail import EmailMessage 后构造发送,若报 SMTPAuthenticationError 检查账号密码与 TLS 参数;邮件通之前可临时退回 'all'。

Q5:怎么把默认语言改成中文? local_settings.py 中设 LANGUAGE_CODE = 'zh-hans' 并重启。若想隐藏其他语言,把 settings.py 的 LANGUAGES 列表整体复制进 local_settings.py 只留需要的条目(覆盖层整表替换)。

Q6:转码太慢怎么办? 按优先级:FFMPEG_DEFAULT_PRESET 降为 veryfast;确认 CHUNKIZE_VIDEO_DURATION 分块已启用(长视频并行);编排层面扩容 celery_worker 实例数(多 worker 共享同一媒体目录即可并行);极端低配直接 DO_NOT_TRANSCODE_VIDEO = True 放弃转码。

Q7:上传报「You don't have permission to upload media, or have reached max number of media uploads」? 命中 CAN_ADD_MEDIA 资格限制或 NUMBER_OF_MEDIA_USER_CAN_UPLOAD 数量上限,按 5.3 节调整两参数;管理员可在后台编辑用户资料勾选 advancedUser 提升资格。

八、参考链接