news 2026/10/8 11:13:53

Ubuntu Server视频播放与网页显示:从零部署媒体服务全攻略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ubuntu Server视频播放与网页显示:从零部署媒体服务全攻略

1. 先把问题说清楚:Server上“播放视频”和“显示网页”其实是两件事

我见过太多朋友第一次接触 Ubuntu Server 时被这个标题搞晕。一台默认连桌面环境都没有的服务器,怎么“播放视频”?怎么“显示网页”?两句话听起来像两个独立需求,但实际操作中它们往往是一件事的两种表达:把服务器变成一台能出画面、能出声音的媒体设备,或者变成一台能通过浏览器远程看视频的网页服务。本文把这整条链路拆开讲清楚,并给出可复现的部署过程。

先说结论:Ubuntu Server 本身不提供图形界面,想让它“播放视频”,要么你给它接显示器再装一套播放器,要么你让视频文件通过网络以网页形式输出,用户在任意设备的浏览器里打开一个地址就能播放。第二种才是绝大多数人的真实诉求——比如家里闲置的旧电脑装 Ubuntu Server,想当成家庭媒体中心;比如公司内网的服务器需要提供培训视频点播;比如开发环境里要快速验证一段视频能不能被网页正常拉流播放。而且顺着“播放视频”这个需求的延伸,你会不可避免地碰到 nginx、nodejs、HTML5 video 标签、m3u8 切片、转码、硬解这些词,这些都是同一个生态里的东西。

顺便提一句,很多人在搜索“ubuntu server 播放视频显示网页”时,其实真正想要的是“我做了一个网页,里面嵌了视频,放到 Ubuntu Server 上之后怎么让访问者能看到”。这个问题就不是播放器的问题了,而是 Web 服务配置和视频流格式的问题。

1.1 无头服务器为什么不能直接“看”视频

大多数 Ubuntu Server 安装完的状态是:没有桌面、没有 HDMI 输出渲染、连声卡都可能没被初始化。运行一个startx都会直接报错,更别说双击打开一个 mp4 文件。很多新手在这里会卡很久,以为是自己装错了版本。

根本原因在于服务器版的定位:它被设计用于长期运行服务,而不是交互式操作。图形界面相关组件默认不安装,连显卡驱动都不一定加载。这带来一个很实际的影响:你需要明确自己的目标模式。

  • 模式A:本地播放。服务器本身接了一台显示器,你在服务器上操作界面播放视频。这种情况建议直接装桌面版或者补装一个轻量桌面环境。
  • 模式B:远程网页播放。服务器只负责通过网络提供视频内容,用户在自己电脑或手机浏览器里打开网页观看。这是绝大多数实际需求。
  • 模式C:两者结合。服务器接显示器但只显示一个自动打开的网页,全屏循环播放视频,相当于一个“信息发布终端”。

本文主要围绕模式B和模式C展开,因为模式A直接装桌面版就行,没什么好讲的。

1.2 整个技术链路的真实形态:媒体服务 + Web前端

理清需求后,你会发现真正要构建的是一条媒体链路,而不是装一个“万能视频播放器”。这套链路从下往上看是三层:

第一层是媒体源。也就是你的视频文件放在服务器的哪个目录,权限对不对,文件名有没有中英文问题,视频编码是 H.264、H.265 还是老旧的 MPEG-4。这些因素直接决定后续步骤的复杂程度。

第二层是媒体服务。它负责把视频“喂”给浏览器。最简单的做法是用 nginx 直接把 mp4 文件当静态资源提供;进阶做法是用 nginx 的 HLS 模块把视频切片成 ts 文件,浏览器端通过 m3u8 播放列表拉流;更彻底的做法是上 Jellyfin、Emby 这类媒体服务器,它们自带转码能力,能把不兼容的视频格式实时转换成浏览器能播的格式。

第三层是 Web 前端。一个最简单的 HTML 页面里放一个<video>标签,src指向服务器上的视频地址,就完成了“显示网页”的使命。别小看这一步,自动播放策略、跨域问题、浏览器对视频格式的支持范围,都会在这一层暴露。

2. 先从本地把视频播起来:无桌面环境下的播放器选型

不管最终目标是网页播放还是本地输出,我都推荐先在服务器上把视频“播出声”一次。这么做不是为了追求播放本身,而是为了验证底层依赖缺失了哪些。比如编解码器、显卡驱动、音频服务,这些缺了任何一个,网页流程里迟早会给你脸色看。

2.1 三种播放器怎么选:ffplay、mpv、Chromium

在无桌面环境下常用的本地播放工具有三个,我分别给你它们的定位和典型使用场景:

  • ffplay:FFmpeg 自带的播放器,参数简单,适合快速验证一个视频能不能正常解码。它不做任何界面美化,输出直接刷新到命令行窗口,配合 SDL 渲染画面。在服务器场景里,它是调试第一工具。
  • mpv:更现代的命令行播放器,支持硬件解码、各种滤镜、脚本扩展。它也有自己的 OSC 界面,比 ffplay 好用,而且对 H.265 的支持更好。需要输出到真实显示器时首选。
  • Chromium 无头模式或 kiosk 模式:这不是用来“播放本地视频文件”的,而是用来“显示网页”的。你可以让 Chromium 启动后自动打开一个指向本机 nginx 的页面,页面里嵌一段视频,最终效果就是服务器接的显示器上出现了一个自动播放视频的网页。这个方案常被用在数字标牌、信息发布屏上。

另外还有一个容易混淆的点:Node.js 本身不能播放视频,但可以用它快速起一个 HTTP 服务,把视频文件从磁盘流传出去,浏览器拿到流自己解码。所谓“nodejs播放视频”本质上是“nodejs搭建视频服务”。它跟 nginx 静态文件服务的区别在于,Node.js 方案更容易嵌入业务逻辑,比如按用户权限过滤视频、动态拼接视频列表,但性能和稳定性不如 nginx。

2.2 本地播放实测:从装包到出画面的每一步

我在一台干净的 Ubuntu Server 22.04 上做了完整实测。这台机器没有安装任何桌面环境,只有一个 4K 显示器通过 HDMI 接着,这个条件在服务器场景里已经算“豪华”了,很多人连显示器都不接。

第一步是安装基础工具。apt install ffmpeg mpv vlc一条命令装上 FFmpeg、mpv 和 VLC 备用。装完后先用一个测试视频验证解码链路:

ffprobe /data/videos/sample.mp4

这个命令输出视频的编码格式、分辨率、码率、音频轨道信息。如果输出里出现Video: h264 (High)或者Video: hevc,说明文件本身没问题。如果报错找不到解码器,说明你装的 FFmpeg 版本太老或缺少对应扩展仓库。

第二步是试着播放。直接执行:

ffplay -fs /data/videos/sample.mp4

这个场景下,如果屏幕没有反应,先别急着怀疑播放器。大概率原因有两个:一是当前用户没有权限访问显卡驱动节点/dev/dri,二是没有初始化图形会话。服务器初始状态连DISPLAY变量都不存在,播放器根本不知道往哪输出画面。

解决办法是给当前用户加入 video 组,并设置自动登录和图形会话。在/etc/gdm3/custom.conf或者/etc/lightdm/lightdm.conf里启用自动登录,然后安装一个轻量窗口管理器:

apt install lightdm xserver-xorg-video-intel

重启后如果显示器能出现登录界面,再切换到 tty 终端执行export DISPLAY=:0,然后重新运行 ffplay。这次应当能看到视频窗口。这一步实测中最大的坑是:即使你装了轻量桌面,startx在部分服务器内核上也会因为缺少 firmware 文件报错,干脆用 lightdm 的自动登录最省事。

2.3 无显示器时怎么验证播放成功

如果服务器没有接显示器,也不用灰心。可以用 Xvfb 建立虚拟屏幕,再用 VNC 远程查看画面。这套组合是服务器排障的经典方案,我验证码率、字幕加载、颜色空间这些细节时经常用。

apt install xvfb x11vnc mpv Xvfb :1 -screen 0 1280x720x24 & export DISPLAY=:1 mpv --vo=x11 /data/videos/sample.mp4 & x11vnc -display :1 -forever -shared -rfbauth ~/.vnc/passwd

用 VNC 客户端连上 5900 端口,就能看到 mpv 渲染出来的画面了。这一步的意义在于:它验证了视频解码、音频输出、颜色渲染这条链路是完整的,后面网页播放环节无论出什么问题,你都能确认问题不在源文件和解码器层。

3. 网页显示的核心环节:让浏览器能把视频拉起来

“显示网页”这件事,落到实际操作上就是:服务器上跑一个 Web 服务,浏览器访问某个 URL,回车,页面上出现一个视频播放器,点播放按钮,画面出来。这里面有三个关键点:静态文件服务怎么配、视频流怎么给、浏览器策略怎么绕过。

3.1 最简单的方案:nginx 静态目录 + HTML video 标签

如果你视频文件是 mp4 且编码为 H.264,浏览器原生就能播放,不需要任何转码。此时 nginx 只做一件事:把视频目录暴露出去。

server { listen 80; server_name video.example.internal; root /data/videos; autoindex on; autoindex_exact_size off; autoindex_localtime on; location /videos/ { alias /data/videos/; add_header Accept-Ranges bytes; add_header Cache-Control "no-transform"; } }

这里有两个细节容易踩坑。第一个是alias的路径末尾必须带/,否则 nginx 会把 URL 路径直接拼在 alias 后面,导致文件查找失败。第二个是Accept-Ranges bytes响应头,nginx 默认就会加,但如果你用了add_header覆盖了全局配置,要确保没有把它挤掉。Range 请求是浏览器拖进度条的根基,没有它,视频只能从头播到尾,用户一拖进度条整个播放器就卡死。

前端页面极度简单,一个文件搞定:

<!DOCTYPE html> <html> <body> <video controls autoplay muted width="1280" height="720"> <source src="/videos/sample.mp4" type="video/mp4"> </video> </body> </html>

把这段存成/data/www/index.html,浏览器打开http://服务器IP/就能看到播放器。这里有个规律:muted属性加上后 autoplay 才能生效,这是 Chrome 的自动播放策略。如果你不加 muted,页面打开后视频是不动的,必须手动点一下播放按钮,很多新手在这里误以为 nginx 没配对。

3.2 需要拖进度条和兼容老格式时:HLS 切片方案

mp4 直接播放解决不了两个问题:一是视频文件特别大,比如几个 GB 的超清资源,浏览器需要支持 Range 请求才能随机拖动,od HTML5 播放器对这个支持还算好,但部分播放器插件不支持;二是视频编码不是 H.264,比如很多设备拍出来的是 H.265,Chrome 和 Firefox 默认都不支持,点开页面直接黑屏。

这时候要用 HLS 协议。HLS 的原理简单说就是把视频切成一小段一小段的 ts 文件,一般每段两到十秒,再生成一个 m3u8 播放列表文件。播放器拿到 m3u8,一个一个地拉取 ts 分段来播。这样做的另一个好处是支持“直播式”的视频流,很多监控摄像头的流就是这个格式,你用播放器打开 CCTV 之类的直播 m3u8 地址时,画面花屏往往就是切片参数和你播放器不对付。

手动切片的命令是这样的:

ffmpeg -i /data/videos/sample.mp4 \ -codec: copy -start_number 0 -hls_time 10 \ -hls_list_size 0 -hls_segment_filename /data/www/hls/segment_%04d.ts \ /data/www/hls/playlist.m3u8

如果不想每次手动切片,可以装 nginx 的 rtmp 模块或者用 ffmpeg 常驻服务实时转码。但小规模自用场景,我更推荐一次性切片到位,因为切片后的目录结构固定,nginx 配置简单,访问压力也小。切片完成后,网页里把 video 标签的 src 指向.m3u8文件即可。如果浏览器不支持 m3u8 原生播放,需要引入 hls.js 播放器库,在页面里写几行 JavaScript 加载它,具体代码网上很多,不多赘述。

3.3 跨域、端口、文件权限:三个最隐蔽的坑

网页显示视频时,最常见的三个隐蔽问题,我逐个说清楚。

跨域问题。前端页面在 80 端口,视频文件在 8080 端口,浏览器会认为这是两个不同的源。如果 nginx 默认不返回Access-Control-Allow-Origin,播放器在拉取分片时会被 CORS 策略拦下来,表现就是视频转圈圈但不播放。解决办法是在 nginx 配置里加一行:

add_header Access-Control-Allow-Origin *;

端口问题。如果只监听 80 端口,一切正常;如果你为了调试临时用了 8080 或者其他端口,记得防火墙放行。Ubuntu Server 默认 ufw 状态可能是开着的,不开端口怎么都访问不到。

ufw allow 80/tcp ufw allow 443/tcp

文件权限问题。nginx 以 www-data 用户运行,视频目录权限必须保证该用户可读。我见过很多次chmod 777依然打不开的,因为父目录的x权限丢了。快速排障命令:

namei -l /data/videos/sample.mp4

输出每一级路径的权限归属,一眼看出哪一层卡住。

4. 升级做法:Jellyfin 媒体服务器解决“多格式、多端、转码”痛点

nginx 加 HTML 的方案适合视频文件不多、格式较统一、用户就是你自己。一旦家里或者团队里设备多了,有人用手机、有人用电视、有人用 iPad,不同设备对视频格式支持差异很大,你会被 H.265 和 H.264 之间谁是默认格式的问题搞得焦头烂额。这时直接上 Jellyfin 这类现成媒体服务器,能省下非常多时间。

4.1 Jellyfin 的部署和使用逻辑

Jellyfin 是开源免费的媒体服务器,它的核心价值在于:自动扫描你的视频目录,把视频信息整理成媒体库;自带 Web 管理界面和播放页面;内置 FFmpeg,能实时转码成目标设备支持的格式;还支持外挂字幕、多音轨、倍速播放这些细节功能。

安装不算复杂:

curl -fsSL https://repo.jellyfin.org/ubuntu/jellyfin_team.gpg.key | gpg --dearmor -o /etc/apt/trusted.gpg.d/jellyfin.gpg echo "deb [signed-by=/etc/apt/trusted.gpg.d/jellyfin.gpg] https://repo.jellyfin.org/ubuntu $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/jellyfin.list apt update apt install jellyfin

装完访问http://服务器IP:8096,跟着向导添加媒体库,把视频目录指过去,Jellyfin 会自动生成海报墙。之后所有设备访问同一个地址,服务器端根据设备类型决定是直接推流还是转码。

值得说明的是,Jellyfin 默认自带了一个精简版网页服务,不再依赖 nginx。但如果你的服务器前面还有一层域名和 HTTPS 证书,建议用 nginx 反向代理一下 8096 端口,这个属于常规操作。

4.2 为什么我推荐小规模自用先跑 Jellyfin

我给朋友部署过多次家庭媒体中心,经验是:如果就一台 Ubuntu Server,视频文件就几十部电影,直接 Jellyfin 起步,别从 nginx 静态文件方案开始折腾。原因有三点:

第一,Jellyfin 自动转码解决格式兼容问题。你下载一部 H.265 10bit 的片子,用 nginx 方案投到电视上,电视播放器大概率黑屏没声音。Jellyfin 检测到设备不支持 H.265,会自动转成 H.264,虽然 CPU 占用高一点,但至少能看。

第二,Jellyfin 的播放进度同步功能其实挺实用。你在客厅看了一半,回卧室打开同一部电影,问你“继续观看还是从头播放”,这个体验对比静态页面的裸播差距太明显。

第三,它自带多用户管理。家里人多的情况下,可以给每个人开账号,控制谁能看哪些内容。静态 nginx 方案做不到这层控制。

4.3 用 Node.js 快速搭一个极简播放页的场景

有一种需求介于“静态 nginx”和“完整 Jellyfin”之间:你有一个业务系统,本身基于 Node.js 开发,现在要在某个页面上嵌入一段视频。这种情况再起一个 nginx 服务很笨,直接在 Node.js 里用express.static挂载视频目录就行:

const express = require('express'); const path = require('path'); const app = express(); const port = 3000; app.use(express.static(path.join(__dirname, 'public'))); app.use('/videos', express.static('/data/videos', { setHeaders: (res) => { res.setHeader('Accept-Ranges', 'bytes'); res.setHeader('Cache-Control', 'no-transform'); } })); app.listen(port, () => { console.log(`Media web server running at http://0.0.0.0:${port}`); });

这个方案能满足动态鉴权需求,比如只允许登录用户访问视频。原理上依然是静态文件服务,只是从 nginx 换成了 Node.js。别再搜什么“nodejs播放视频”的库了,Node.js 不参与解码,它只负责把文件流传出去。

5. 硬解、软解、转码:服务器端最容易被忽略的瓶颈

网页播放方案部署完成后,最常见的性能问题是 CPU 占用率飙高。这里面的根本原因需要分角色看:如果视频直接以原始文件形式发给浏览器,那么解码工作全部在客户端设备,服务器只承担文件传输,CPU 占用几乎可以忽略。如果客户端设备不支持某种编码格式,服务器需要先转码再发送,这才会消耗大量 CPU。

5.1 软解与硬解的适用边界

FFmpeg 转码默认走软件解码和软件编码,纯靠 CPU 算。一台普通的四核服务器,转 1080p H.265 到 H.264 时 CPU 占用基本 100%,而且可能只有十几帧的实时转码速度,播放会卡。如果服务器有 Intel 核显并支持 Quick Sync,可以开启硬解硬编,转码速度能快很多倍,CPU 占用大幅下降。

启动硬解需要装对应驱动,以最常见的 Intel Quick Sync 为例:

apt install intel-media-va-driver-non-free vainfo vainfo

看到输出里有H264和HEVC编码支持,说明硬解路径已就绪。Jellyfin 里配置转码时勾选硬件加速即可。nginx 方案的转码一般用 ffmpeg 命令行,示例如下:

ffmpeg -hwaccel vaapi -hwaccel_output_format vaapi \ -i input.mp4 -c:v h264_vaapi -b:v 2M -c:a aac output.mp4

从实践看,硬解不是没有代价。首先是稳定性,部分驱动版本在转码长视频时可能崩溃,表现为输出文件突然中断或花屏;其次是画质,硬编码的压缩效率在同等码率下比软件编码略差,新闻资讯类视频无所谓,纪录片、球赛这种高动态画面能看出区别。所以我的经验是:服务器 CPU 强就软编,CPU 弱就硬编,画质优先级低于流畅度。

5.2 浏览器端的硬解与服务器无关

很多文章讲“Chrome 视频硬解”,那是客户端浏览器的事,跟服务器端没有任何关系。浏览器能不能硬解取决于用户设备的显卡、浏览器设置、以及视频编码是否匹配。服务器唯一能做的就是选择浏览器兼容性最好的视频编码。H.264 是全设备的“公约数”,H.265 虽然体积小一半,但 Safari 支持、Chrome 部分版本支持、Firefox 默认不支持,所以做分享场景时优先 H.264。

5.3 转码参数怎么给才不卡

转码不是参数越多越好,我提供一组经过多次实测的保守参数组合,适合大多数 1080p 视频转码:

ffmpeg -i input.mp4 \ -c:v libx264 -preset veryfast -crf 23 \ -vf scale=-2:720 \ -c:a aac -b:a 128k \ -movflags +faststart \ -threads 0 output.mp4

-preset veryfast牺牲一点压缩率换速度;-crf 23是 H.264 的默认质量档,画质损失不明显;-vf scale=-2:720把视频压到 720p 播放,码率需求降低,网页加载更快;-movflags +faststart把 moov 原子信息挪到文件头部,浏览器打开视频时不用等待整个文件加载就能快速起播。最后这条对网页播放体验的影响是最直观的,不加的话,大文件在浏览器里点开往往要转圈很久才能出现画面。

6. 从零到网页播放的完整部署流程:一台全新 Ubuntu Server 的实操记录

理论部分讲了不少,下面把我最近一次在干净环境下部署的完整过程呈现出来。这是一台 Ubuntu Server 24.04 LTS,1G 内存、单核 CPU 的云服务器,视频文件放在/data/videos目录下。因为机器性能和存储都很弱,我选择 nginx 静态方案而非 Jellyfin。

6.1 环境准备与依赖安装

登录服务器后第一步是更新软件源和安装必要的包:

apt update && apt upgrade -y apt install -y nginx ffmpeg

nginx 装完默认会自动启动并监听 80 端口。用systemctl status nginx确认状态为 active。ffmpeg 是为了验证视频信息和后续可能的转码操作。

然后创建目录并放入测试视频。这里刻意用了一个中文文件名测试视频.mp4来验证中文字符在 URL 中的表现。实际经验是:中文文件名在浏览器和 nginx 之间容易出现编码不一致的问题,轻则无法访问,重则 404,更稳妥的做法是统一用拼音或者数字命名。操作中我将文件重命名成了test.mp4。

检查文件完整性:

ls -lh /data/videos/ ffprobe /data/videos/test.mp4

正常输出里能看到Duration: 00:02:13.14和Video: h264 (High)这类信息。

6.2 nginx 配置与目录权限

nginx 的默认站点配置文件在/etc/nginx/sites-available/default,我直接修改它:

server { listen 80 default_server; listen [::]:80 default_server; root /data/www; index index.html; server_name _; location /videos/ { alias /data/videos/; autoindex on; } }

注意这里 root 指向的是/data/www,视频访问走/videos/子路径,通过 alias 映射到真实视频目录。创建前端页面/data/www/index.html:

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>视频演示站</title> </head> <body> <h2>测试播放</h2> <video controls width="640" height="360"> <source src="/videos/test.mp4" type="video/mp4"> 你的浏览器不支持 video 标签。 </video> </body> </html>

检查语法并重载服务:

nginx -t systemctl reload nginx

权限方面,/data目录本身如果是 root 创建的,nginx 的 www-data 用户需要至少拥有r-x权限。我习惯的做法是给/data设置755权限,视频文件设644,然后立即用curl验证:

curl -I http://localhost/videos/test.mp4

看到返回200 OK且响应头包含Content-Length,说明文件可以被正常访问。如果返回 403,多半是目录权限问题;返回 404,多半是 alias 路径配置错误。

6.3 防火墙和远程访问验证

服务器在云环境时,安全组和系统防火墙都要放行 80 端口。Ubuntu 自带的 ufw 如果启用,执行:

ufw allow 80/tcp ufw status

从另一台电脑的浏览器访问http://服务器IP/,页面打开,视频可以播放,标题这就算跑通了。要提醒的是,如果你用 HTTPS 访问服务器,需要把视频服务也配置到 443 端口并挂证书,否则浏览器会因混合内容拦截视频加载。

这一环节我顺手验证了自动播放策略:页面里的 video 标签没加 muted 属性时,Chrome 会忽略 autoplay,视频处于暂停状态;加上 muted 后,打开页面即自动播放。这是浏览器层面的规则,和服务器无关,但你做“数字标牌”类项目时一定要知道。

7. 实测中遇到的花屏、无声和 CPU 飙升:排障经验与根治办法

部署完成不是结束,恰恰是踩坑的开始。我把自己在 Linux 服务器播放和网页播放场景里踩过的三类问题整理一遍,每个都给出排查路径和根因分析。

7.1 播放 m3u8 直播流时画面花屏

这个坑的典型表现为:网页播放器能加载,画面却是一块块破碎的绿色和灰色色块,声音正常。很多人在打开 CCTV 之类的直播地址时遇到过这个问题。

根因通常是视频源输出的视频帧编码格式和你播放器期望的不一致。直播流大多是 H.264,但部分源会用 B 帧和参考帧数量较多的配置,而低端播放器或者浏览器解码器没有正确处理,导致参考帧缺失、画面花屏。另外 ts 分片边界如果和 GOP 边界不对齐,也可能导致关键帧缺失。

排障流程是先用 ffprobe 查看流的编码参数:

ffprobe -show_streams http://example.com/live/stream.m3u8

重点看codec_name、profile、level三个字段。如果 profile 是 High 而 level 是 4.0 以上,老设备花屏概率大。解决办法有两个:一是在服务端转码成 Baseline profile 再输出,二是前端播放器强制设置软解。Jellyfin 里可以在转码设置中指定 h264 baseline profile;纯前端 hls.js 场景可以设置hls: { enableSoftwareMSE: true }尝试。

7.2 网页播放器没有声音

这个问题的排查范围比很多新手想象中大。如果是“本地点开 ffplay 有声音,但网页里没声音”,那问题处在浏览器自动播放策略和音频上下文未激活上。Chrome 要求页面在用户点击页面任意位置以后,媒体元素才能输出声音。如果你希望打开页面就能直播有声视频,最佳做法是页面加载后显示一个“点击进入”按钮,用户点击后自动播放。

如果是“所有播放方式都没声音”,则要检查系统音频服务。服务器版默认没有安装 PulseAudio,我因为没声卡这个细节排查过挺长时间。装法如下:

apt install pulseaudio pulseaudio --start --exit-idle-time=-1

然后用speaker-test验证声音输出。服务器接显示器但没接音箱,自然没有声音输出,这属于最容易被忽略的环境因素。

7.3 CPU 占用飙升与转码瓶颈

nginx 直接推流模式几乎不消耗 CPU。如果你发现 CPU 占用从正常 5% 跳到 90%,肯定走转码通路了。常见原因是你配置了 HLS 实时切片,而 ffmpeg 是常驻转码进程。判断方法:

top -c

找出 CPU 占用高的进程,如果进程名是 ffmpeg,确认它在转码哪个视频。解决思路是:把视频预先转码成 H.264 主流的 mp4,避免实时转码。你真的需要实时转码的场景只有两个:直播流转发,或者多设备同时访问且源文件编码过于特殊。

还有一个经常被忽略的因素:如果视频文件存储在网络盘或机械硬盘上,读取速度跟不上也会造成播放卡顿,表现为播放器转圈但 CPU 不高。这个问题的排查方法是看iostat -x 1,r/s 和 w/s 数值异常高时,考虑把视频文件迁移到本地 SSD。

7.4 远程访问时常断流的问题

网页播放时断时续,第一反应是网络带宽不够,但有时候服务器带宽明明很大,WiFi 也满格。我的实测经验是,问题往往出在 TCP 拥塞控制和 MTU 上。部分云服务器的默认 MTU 是 1500,而内网环境实际 MTU 小于这个值,出现分片丢包导致播放器缓冲不稳。

排查命令:

ping -M do -s 1472 网关IP

如果报错,说明 MTU 需要调整,改为 1400 即可。云服务器一般在控制台修改网络配置,物理机可以修改/etc/network/interfaces或者 netplan 文件。这个坑排查成本低但收益高,很多人断流排查根本不看 MTU,导致一直找不到原因。

8. 写在最后:根据实际场景选方案,别被“高大上”带偏

整个流程跑下来,我的体会是:Ubuntu Server 上“播放视频显示网页”这件事,真正难的不是某个技术点,而是先想清楚自己的场景。如果只是自己家里一两台设备看,装 Jellyfin 一个服务完事;如果是临时演示给同事看某个视频文件,nginx 静态目录加一个 HTML 页面最简单;如果是业务系统集成,Node.js 静态挂载或者 Nginx 子路径顺手就能接进去。

一个容易被忽略却影响体验的地方是视频文件的预处理。无论你选哪种方案,装完 FFmpeg 之后先把所有视频检查一遍:

for f in /data/videos/*.mp4; do echo "检查: $f"; ffprobe -v error -show_entries stream=codec_type,codec_name "$f" 2>/dev/null | paste - -; done

列出每个文件的编码格式。假如你要批量播放一批老视频,编码可能是 MPEG-2 或者 DivX,直接丢到网页里必然黑屏,提前用 FFmpeg 转成 H.264 格式能省掉后面所有烦恼:

for f in /data/videos/*.avi; do ffmpeg -i "$f" -c:v libx264 -c:a aac "${f%.avi}.mp4"; done

个人经验告诉我,不要盲目追求“一劳永逸”的万能方案,因为媒体生态太分裂:设备差异、浏览器差异、编码差异,每一层都能折腾出问题。先把最小可用的链路跑通,再根据实际需要决定是否引入 Jellyfin、是否开启硬解、是否需要 HLS 切片,这才是 Ubuntu Server 上做视频应用最务实的路径。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 11:13:48

Linux内核内存分配机制全解析:伙伴系统、slab与vmalloc实践指南

1. 先搞清楚内核内存分配到底在解决什么问题做内核开发和嵌入式Linux的老哥&#xff0c;应该都有过这样的经历&#xff1a;用户态程序内存不够了&#xff0c;malloc一个NULL回来&#xff0c;你能清晰感受到问题出在哪。但内核不一样&#xff0c;内存分配失败的后果往往不是返回…

作者头像 李华
网站建设 2026/10/8 11:12:29

HarmonyOS NEXT端侧大模型部署:五大工程决策与内存功耗优化实践

1. 为什么要在 HarmonyOS NEXT 上跑大模型&#xff0c;而不是调云端 API先把结论摆在前面&#xff1a;在 HarmonyOS NEXT 上接入开源大模型&#xff0c;绝大多数团队真正要解决的不是“能不能跑起来”&#xff0c;而是“跑起来之后&#xff0c;端侧算力、内存、功耗、包体积这四…

作者头像 李华
网站建设 2026/10/8 11:11:32

AI旅游Agent技术栈拆解:从对话到支付的全链路工程实践

1. 为什么我要拆这个 AI 旅游 Agent 的技术栈 去年下半年开始&#xff0c;身边做旅游、做本地生活、做 SaaS 的朋友几乎都在问同一件事&#xff1a;能不能做一个 AI 旅游 Agent&#xff0c;用户说一句"帮我安排五一去成都三天&#xff0c;预算三千&#xff0c;带老人"…

作者头像 李华
网站建设 2026/10/8 11:10:55

AI漫剧量产全攻略:零基础用AI工具做短视频副业赚钱

先聊个让我很意外的现象&#xff1a;我一个完全不会画画、连PS都不太熟的朋友&#xff0c;靠着AI漫剧这个形式&#xff0c;两个月做出了三条数据还不错的短剧视频。他用的工具全是免费或廉价方案&#xff0c;流程就是网上东拼西凑学来的。这件事让我意识到&#xff0c;AI漫剧可…

作者头像 李华
网站建设 2026/10/8 11:10:15

开源雷达周刊:每周精选10个能跑通的自动化工具

1. 为什么我要做这个开源雷达周刊 先说清楚这个周刊到底是个什么东西。简单讲&#xff0c;它是我每周花几个小时&#xff0c;把过去七天里在开源社区里冒出来的、跟自动化沾边的工具筛一遍&#xff0c;挑出十个真正能跑起来、能解决具体问题的项目&#xff0c;然后整理成一份可…

作者头像 李华