行业资讯
📅 2026/8/16 17:34:57
自托管服务实战(9):自建媒体与下载服务
上一篇建立了更新与告警门禁。本篇加入 Jellyfin 与下载任务这类大容量、高 I/O、可能持续占用 CPU 或核显的负载并通过目录、权限和资源预算把它们与密码库、代理等核心服务隔离。一、先设计媒体流转路径目录至少分为下载临时区、完成区、媒体库和应用配置。下载器只写临时区与完成区整理任务在校验完成后把文件移动到媒体库Jellyfin 对媒体库只读。若下载区和媒体库位于同一文件系统原子移动几乎立即完成跨文件系统会变成复制加删除期间占用双倍空间并产生半成品风险。能直接播放就不转码。直播放由客户端解码服务器只传输文件转封装只改变容器成本较低视频转码会持续消耗 CPU 或硬件编码单元。选型要用真实客户端、字幕和码率测试不能只看影片分辨率。硬件转码时仅映射需要的渲染设备并确认容器用户属于正确组不要为了省事使用特权模式。媒体元数据、观看进度与用户配置是小而重要的状态应定期备份可从合法来源重新取得的大媒体文件可采用不同保留等级。下载内容必须遵守来源许可与当地法律。下载器的 Web 界面不应直接公开到公网默认密码必须更换完成脚本也不能拥有整个宿主文件系统权限。下面的程序根据客户端能力判断直播放、转封装或转码并汇总并发转码预算。规则简化但完整可运行适合改成上线前的设备兼容性清单。fromdataclassesimportdataclassdataclass(frozenTrue)classSession:name:strvideo:straudio:strcontainer:strclient_video:set[str]client_audio:set[str]client_container:set[str]sessions[Session(电视,h264,aac,mp4,{h264,hevc},{aac},{mp4,mkv}),Session(浏览器,hevc,aac,mkv,{h264},{aac},{mp4}),Session(平板,h264,aac,mkv,{h264},{aac},{mp4}),]transcodes0foriteminsessions:ifitem.videonotinitem.client_videooritem.audionotinitem.client_audio:modetranscodetranscodes1elifitem.containernotinitem.client_container:moderemuxelse:modedirect-playprint(f{item.name}: mode{mode})capacity2print(ftranscodes{transcodes})print(fcapacity_gate{PASSiftranscodescapacityelseFAIL})运行输出电视: modedirect-play 浏览器: modetranscode 平板: moderemux transcodes1 capacity_gatePASS二、用水位和限额保护核心服务下载任务会制造持续写入、校验读取和大量连接。为容器设置 CPU、内存和 I/O 优先级限制并发下载与上传速度并给系统盘、下载盘、媒体盘分别告警。保留空间不能只看百分比10TB 盘剩 5% 仍有 500GB小系统盘剩 5% 可能已经无法写日志应同时使用绝对容量和预测耗尽时间。媒体扫描安排在低峰并避免每次启动全库重扫。缩略图和转码缓存是可重建数据可设置容量上限配置数据库与观看进度进入备份。下载未完成文件使用专用后缀或目录整理器只处理完成且校验通过的项目避免 Jellyfin 索引到半个文件。以下程序模拟空间水位与整理决策。只有状态完成、摘要正确且目标盘保留安全余量时才移动所有输入明确便于把规则迁移到实际自动化脚本。fromdataclassesimportdataclassdataclass(frozenTrue)classDownload:name:strsize_gb:intcomplete:boolchecksum_ok:booldownloads[Download(family-video.mp4,18,True,True),Download(archive.iso,42,False,False),Download(licensed-film.mkv,36,True,True),]free_gb120reserve_gb50moved[]foritemindownloads:enough_spacefree_gb-item.size_gbreserve_gb eligibleitem.completeanditem.checksum_okandenough_spaceprint(f{item.name}: eligible{eligible}free_before{free_gb}GB)ifeligible:free_gb-item.size_gb moved.append(item.name)print(fmoved{len(moved)})print(ffree_after{free_gb}GB)print(fstorage_gate{PASSiffree_gbreserve_gbelseFAIL})运行输出family-video.mp4: eligibleTrue free_before120GB archive.iso: eligibleFalse free_before102GB licensed-film.mkv: eligibleTrue free_before102GB moved2 free_after66GB storage_gatePASS三、上线和迁移验收先导入少量样本覆盖 H.264、HEVC、不同音轨、内嵌与外挂字幕。分别在电视、浏览器和移动网络测试记录是否直放、首帧时间、服务端负载和带宽。再进行两路并发测试确认密码库和代理延迟没有明显恶化。若资源争用先限制转码并发和扫描时间不要用无限重启掩盖 OOM。迁移媒体库时保持原目录结构和稳定挂载路径可以减少重新匹配。先备份应用配置在新实例只读挂载媒体并完成扫描对比库数量、用户和观看进度最后切换客户端。旧实例停止写入后保留短期回退避免两个服务同时修改元数据。可迁移的核心是“临时—完成—只读媒体”的单向数据流、真实客户端兼容矩阵和资源水位门禁。下一篇把前九篇资产整合成家庭私有云的服务目录、依赖图与灾难恢复顺序。参考来源Jellyfin容器安装Jellyfin硬件加速Docker资源约束 觉得有用就点个赞 收藏方便回头查阅有疑问直接在评论区留言我看到都会回。 本文属于《自托管服务实战》系列持续更新关注不迷路。 文章里的代码都能直接跑。想要可直接 clone 的完整工程 配套部署脚本 / 踩坑清单评论一声或发邮件到cj2664qq.com我免费发你。如果你正好在做类似系统、或有工程化难题想找人做也欢迎邮件聊一句——我按实际情况评估能落地的就接单或出方案。评论和邮件都能直接找到我不用跳别的平台。