2. VLC推流实操从文件到摄像头一步步走通2.1 最简单的推流把本地视频变成一个RTSP流先走一遍GUI操作流程因为很多读者一开始接触的是图形界面。打开VLC菜单栏点击“媒体”→“流...”打开流输出向导。第一步选择源。点击“添加”选中一个本地的mp4视频文件。这里我习惯用一段2分钟左右的测试视频既能看到效果又不会让推流压力太大。第二步点击“流”按钮进入流输出配置。第三步在“来源”页面直接点“下一个”来到“流输出”页面选择“新建目的地”。第四步下拉框选择RTSP然后点击右侧的“添加”按钮。第五步在弹出的配置框里“端口”填8554“路径”填stream勾选“激活转码”。转码参数先保持默认实际会用到H.264后面我再详细说。第六步一路点“下一个”最后点“流”按钮。到这一步VLC界面看起来没有任何变化但其实它已经在背后运行一个RTSP服务了。你可以打开另一个VLC窗口或者用同一台机器的命令行拉流验证vlc rtsp://127.0.0.1:8554/stream如果你能看到画面说明推流链路是通的。这是我在给局域网内测试监控方案时最常用的一招当模拟的RTSP源来用。再说了命令行推流一点也不难而且比GUI更容易写进脚本和定时任务。用命令行做同样的事长这样vlc /path/to/video.mp4 :sout#transcode{vcodech264,acodecmpga,ab128,channels2,samplerate44100}:rtp{sdprtsp://:8554/stream} :sout-keep解释一下这个命令的关键点冒号开头的是VLC的“advanced sout”参数跟GUI里一步步配置的效果完全一样。transcode{vcodech264}意思是强制把视频流转成H.264编码。为什么我要强调这个因为很多源视频是MPEG-4或MJPEG编码如果直接推流部分播放器可能不支持而H.264是兼容性最好的通用编码。rtp{sdprtsp://:8554/stream}表示通过RTP协议承载并生成一个RTSP的SDP描述文件。注意这里端口是8554路径是stream这是我自己习惯的约定IP地址留空表示默认绑定所有网卡接口。:sout-keep这个参数很关键。没有它VLC推流结束后整个进程会直接退出加上它VLC会保持运行每次循环推流不会中断。我在做7x24小时无人值守推流的时候必须加这个参数。还有一个细节要提醒你如果你推的是一个视频文件默认情况下文件播放完推流就会停止。想让视频循环播放、持续推流需要在命令行加上--loop参数vlc --loop /path/to/video.mp4 :sout#transcode{vcodech264,acodecmpga,ab128,channels2,samplerate44100}:rtp{sdprtsp://:8554/stream} :sout-keep加了--loop之后文件播完会从头继续推流不会断。这在做7x24小时的模拟信号源场景下特别有用。2.2 桌面实时推流把屏幕变成直播源文件推流是基础但实际工作中更多时候需要推的是屏幕、摄像头或采集卡画面。录屏推流其实非常实用比如临时给学员演示操作过程、把另一个客户现场的工控机画面传回本部都用得上。在VLC里桌面推流可以靠screen://这个伪协议来实现。直接用命令行vlc screen:// :screen-fps15 :sout#transcode{vcodech264,vb800,scale0.5,acodecnone}:rtp{sdprtsp://:8554/desktop} :sout-keep参数解读screen://告诉VLC源是屏幕。:screen-fps15设置采集帧率为15fps。别贪高屏幕采集本身就耗CPU特别是分辨率一旦到了1080P以上30fps会让CPU占用直接飙到50%以上。15fps在大多数场景下足够流畅。vb800是视频码率800kbps。码率太低画面会有块状马赛克太高又会增加网络压力。做内网演示的话1080P下码率建议控制在1500-2500kbps画质和带宽能平衡。scale0.5把分辨率减半。比如你的屏幕是1920x1080实际推出去就是960x540。这是降低CPU负载最有效的手段能明显减少卡顿。acodecnone表示不采集音频。如果你需要带系统声音推流VLC的桌面音频采集并不是强项这种情况我建议直接上OBS而不是硬用VLC。还有个比较隐蔽的坑屏幕采集时如果电脑锁屏了VLC采集到的画面可能是黑屏或登录界面。需要推流的主机最好把电源设置里的“关闭显示器”改成“从不”否则半夜推流看起来是一块纯黑画面排查的时候怎么都找不到原因。摄像头推流也是类似思路把源改成v4l2:///dev/video0Linux下摄像头设备文件vlc v4l2:///dev/video0 :v4l2-width640 :v4l2-height480 :v4l2-fps30 :sout#transcode{vcodech264,vb500,acodecnone}:rtp{sdprtsp://:8554/device0} :sout-keep注意先确认一下设备节点是不是/dev/video0有的机器摄像头是/dev/video1插个ls /dev/video*一看便知。2.3 推流参数选择的几个关键点推流参数这一步很多人直接默认然后发现画面模糊、卡顿或拉流端黑屏。其实参数就那么几个理解透了就不会瞎猜。先记住一个公式码率决定了画面清晰度帧率决定了画面流畅度分辨率决定了画面尺寸。三者相互制约而在资源有限的情况下优先保码率。具体到参数选择我用的经验值是这样场景分辨率帧率码率编码文件转RTSP测试原始分辨率原始帧率默认H.264录屏演示1920x1080或减半15fps1500-2500kbpsH.264摄像头监控640x480或1280x72015-25fps500-1500kbpsH.264移动端观看720x57615fps800kbpsH.264关于音频如果源文件有声音转码参数里建议保留音频否则拉流端会没有声音:transcode{vcodech264,acodecmpga,ab128,channels2,samplerate44100}ab128是音频码率128kbpschannels2是双声道samplerate44100是44.1kHz采样率这组参数基本是万金油任何播放器都能兼容。另外一个我经常被问到的问题为什么必须在转码参数里写vcodech264直接推原始编码行不行行但强烈不建议。原因有两个第一很多人手里的素材是MPEG2或者H.265编码拉流端不一定能硬解第二RTSP传输对编码的实时性有要求如果源编码是B帧特别多的视频拉流端会出现播放延迟越来越大的问题。统一转成H.264 baseline profile能最大程度保证兼容性和实时性。3. VLC拉流实操三种常见拉流方式推流是制造信号拉流是消费信号。这块的实操相对简单但坑在于拉流的场景千差万别——从RTSP摄像头拉流、从VLC推流地址拉流、从UDP组播拉流细节各不相同。3.1 拉取RTSP流最经典的场景从海康、大华或宇视的网络摄像机拉RTSP流。基本命令vlc rtsp://192.168.1.100:554/Streaming/Channels/101如果是命令行里临时拉流看一下直接用vlc rtsp://192.168.1.100:554/Streaming/Channels/101 --network-caching300这里有个关键参数--network-caching300单位是毫秒。意思是在VLC内部先缓冲300毫秒的数据再播放。默认值是1000毫秒1000也就是说默认情况下VLC会延迟1秒才显示画面。做实时监控预览时这个延迟很让人抓狂调到300毫秒会明显感觉画面跟手了很多。为什么我建议300而不是直接调成0因为0意味着不做缓冲网络稍微抖动一下画面就会中断、跳帧、花屏。300毫秒是在流畅度和实时性之间比较折中的数值。如果是局域网摄像头100-200毫秒也可以如果是跨公网拉流建议还是用1000左右否则卡顿会折磨到你怀疑人生。GUI方式就更简单了打开VLC按快捷键CtrlN在“打开媒体”对话框里切换到“网络”选项卡粘贴RTSP地址点“播放”就完事。不过GUI方式不方便带参数所以我平时直接用命令行。还有一个细节必须注意很多摄像头的RTSP地址包含了用户名和密码格式是vlc rtsp://admin:password192.168.1.100:554/Streaming/Channels/101注意密码里如果含有符号会跟URL里的冲突。这时候需要把做URL编码成%40否则解析地址的时候直接错乱。这个巨坑我踩过不止一次当时折腾了半小时才反应过来。3.2 拉取UDP/HTTP流除了RTSPVLC还能拉UDP单播/组播流。典型场景是设备直接把TS流打到一个UDP端口VLC负责收。vlc udp://:1234这个意思是监听本机1234端口接收UDP数据。注意不能丢它代表绑定所有网卡上的这个端口。如果只想收来自特定IP的流可以写成vlc udp://192.168.1.100:1234UDP推流在局域网内非常流行因为它没有TCP的三次握手和拥塞控制开销小、延迟低。但它的致命弱点是丢包不重传——网络不好画面就花屏或中断。同一路UDP流VLC还支持组播方式。组播地址一般是224.0.0.0到239.255.255.255这个网段vlc udp://239.255.42.99:1234组播的好处是无论局域网内有多少台机器同时在拉流数据都只有一份在网络上传网络压力与接收端数量无关。这在展会、多媒体教室里特别实用——几十台终端同时看一路视频用组播能把网络带宽省到极致。HTTP拉流就更平常了很多IP摄像头也支持HTTP方式输出视频流vlc http://192.168.1.100:8080/video老实说HTTP方式在VLC里兼容性比较一般如果摄像头或者服务器同时提供多种协议我优先用RTSP或UDPHTTP只作为兜底方案。3.3 拉流时怎么录制和转码拉流不只是看很多时候还要顺便录下来或者把拉到的流再转成别的格式存文件。拉流并保存成文件命令是vlc rtsp://192.168.1.100:554/Streaming/Channels/101 :sout#transcode{vcodech264,acodecmpga}:standard{muxmp4,dstrecording.mp4,accessfile} :sout-keep这里standard{muxmp4,dstrecording.mp4,accessfile}的意思是封装成MP4格式写入到本地文件。有个注意事项MP4封装必须先写文件头如果中途强制杀掉VLC进程生成的MP4文件可能是不完整的播放器打开会报错。所以录制时尽量优雅退出按CtrlC让VLC有机会收尾。如果录制时间很长我更推荐直接用TS封装而不是MP4vlc rtsp://192.168.1.100:554/Streaming/Channels/101 :sout#standard{muxts,dstrecording.ts,accessfile} :sout-keepTS流的好处是容错性极高就算写了一半断电前面已经写好的TS片段依然可以正常播放。在做监控录像保存这种场景下我全部用TS格式回头需要MP4再用ffmpeg转一下封装非常简单。4. Ubuntu系统无法拉流的排查实录这一章是重头戏。标题里说的“Ubuntu系统无法拉流”我实际排查下来真正原因是五花八门的——有版本问题、有防火墙问题、有路径问题、有IPv6问题还有编解码器问题。我按遇到频率从高到低一个个说每个都给出排查方法和解决方案。4.1 问题一自带VLC版本太老导致RTSP握手失败Ubuntu仓库里的VLC版本通常比较保守。比如Ubuntu 22.04自带的VLC是3.0.16看起来好像还行但实际上部分新版RTSP服务器尤其是一些嵌入式设备使用的RTSP实现较新老版本VLC握手时容易失败表现是VLC报错live555 error: Failed to connect with rtsp://...或者干脆一句话都不说窗口黑屏状态栏一直在转圈圈。这个问题的第一个排查手段是看VLC版本vlc --version如果版本低于3.0.20我建议直接升级。升级方式有三个添加VideoLAN官方仓库推荐sudo add-apt-repository ppa:videolan/master-daily sudo apt update sudo apt install vlc用Snap版sudo snap install vlc直接去官网下载AppImage或官方deb包。我个人的习惯是添加官方PPA。因为snap版本的VLC在某些无头服务器上可能起不来缺少X11依赖而且自动启动脚本也不太好处理。PPA版本跟系统集成度更高命令行启动行为跟老版本保持一致。升级完之后之前一直握手失败的RTSP地址可能就直接好了。我遇到过好几次这种情况客户先说“你们的流有问题”我远程一台Ubuntu机器一测试发现问题在他的VLC版本太老流本身好好的。4.2 问题二防火墙把数据通道挡了这是Ubuntu上最常见也最隐蔽的问题。RTSP协议默认有两个通道一个TCP 554端口用于控制数据则通过动态端口传输。很多工具比如VLC自己的RTSP推流默认用的是8554而非标准的554。Ubuntu自带的ufw防火墙默认情况下放行SSH和已建立的连接。如果你只允许了某些端口而忘了放行RTSP相关的端口拉流时会发现地址能解析、控制连接能建立但画面就是出不来。排查方法很简单sudo ufw status numbered看到类似这样输出Status: active To Action From -- ------ ---- 22/tcp ALLOW Anywhere如果Status: active说明防火墙开着。你自己推流的话至少需要放行以下端口sudo ufw allow 554/tcp sudo ufw allow 8554/tcp sudo ufw allow 1234/udp但如果觉得一个个开太麻烦在受信任的内网环境里直接把VLC相关通信全部放行也行sudo ufw allow in proto tcp to any port 554,8554 sudo ufw allow in proto udp to any port 1234放行之后重新拉流一般来说问题就解决了。再补充一个冷门情况如果你用的是云服务器做推流除了系统防火墙云控制台的“安全组”规则也要一并检查。有的云主机安全组默认只开80/443/22其他端口从外面全被堵死你系统防火墙配置得再对也没用因为流量根本进不了网卡。4.3 问题三IPv6优先级导致RTSP连接超时这个坑特别有意思。现象是同一台Ubuntu机器拉rtsp://192.168.1.100:8554/stream一直卡在“正在打开”状态但换成vlc rtsp://127.0.0.1:8554/stream又正常。一番排查下来发现VLC默认会尝试IPv6的::1和DNS解析到的IPv6地址。如果目标主机不响应IPv6大部分老设备没有IPv6协议栈连接就会因为超时被拖累。解决方案很简单强制VLC只用IPv4vlc --ipv4 rtsp://192.168.1.100:8554/stream如果是GUI模式下可以在“工具”→“偏好设置”→“界面”→“实例”里勾选“IPv4”。但命令行直接加参数更快。还有一种情况值得留意有些RTSP设备配置了双栈地址DNS把域名解析到IPv6地址VLC尝试走IPv6但网络路由器没有正确配置IPv6路由结果超时。这种情况用--ipv4也是最快解法。4.4 问题四编解码器缺失导致画面黑屏Ubuntu发行版因为版权问题默认不包含部分解码器。典型表现是拉流能建立连接、音频能听到声音但视频画面一直黑屏VLC状态栏也不报致命错误甚至有时候连报错都不给你。原因是你的源视频流是H.264/HEVC编码但系统缺少对应的解码插件。很多从Windows/macOS转过Ubuntu的用户会立刻踩到这个坑。解决方法是安装Ubuntu“受限制扩展包”sudo apt install ubuntu-restricted-extras这个包会安装VLC和GStreamer所需的H.264、H.265、MPEG-4、AAC等解码器。安装完后需要重启VLC黑屏问题基本上就能解决。另外如果你一直用Snap版VLC它的依赖是自包含的但有时候反而因为版权限制去掉了某些解码器。如果你发现ubuntu-restricted-extras装完还不行可以考虑卸载Snap版改回deb版sudo snap remove vlc sudo apt install vlc4.5 问题五路径里有空格和中文导致拉流报错这个问题不在网络层在应用层。很多人把视频文件放在像/home/user/Videos/我的视频 folder/这种目录下然后直接用带空格或中文的路径推流结果VLC要么报“无法打开文件”要么路径被默默截断。正确的做法是给路径加引号vlc /home/user/Videos/我的视频 folder/test.mp4 :sout...加引号之后空格和中文都能正确处理这跟Shell的解析规则有关系——不加引号时Shell会把路径按空格拆成多个参数VLC拿到的路径自然就错了。还有一个类似的坑文件名里有冒号或单引号比如video:test.mp4这类字符在RTSP配置里会被当成特殊字符。严格地讲最好在源头就避免这种命名直接把文件名改成简单的英文数字组合最省心。4.6 问题六AppArmor和用户权限的干扰Ubuntu从很早就默认启用AppArmor它会给一些软件套一层安全沙箱。某些版本的VLC和ffmpeg在访问特定路径时可能被AppArmor拦截。常见表现是VLC能启动但拉流时写入录制文件直接失败或者连读取文件都被拒绝。检查方法sudo aa-status然后看VLC相关条目。如果发现VLC的策略确实阻拦了可以在/etc/apparmor.d/下查看对应的profile文件。一般来说我们不建议直接禁用AppArmor更优雅的方式是给VLC增加允许访问的路径规则。但如果你是在自己家的个人电脑上折腾直接临时关闭也问题不大sudo aa-complain /usr/bin/vlcaa-complain会把强制模式切换为宽松模式只记录不阻止。发现确实是被AppArmor拦截之后再决定要不要修改profile。另外提一下用户权限有些v4l2://摄像头设备节点默认只允许root和video组访问。如果当前用户不在video组摄像头拉流会提示“No such device”。解决sudo usermod -aG video $USER添加完记得注销重新登录一次权限组才会生效。5. 进阶VLC推拉流的延迟优化与稳定性调优5.1 延迟优化参数很多人在用VLC做实时监控时对延迟忍无可忍。默认情况下VLC为了播放流畅内部设置了多级缓冲网络缓冲 解码缓冲 音视频同步缓冲加起来可能是1.5-2秒。对于监控场景这么大延迟没法接受。优化延迟的做法是调低几组核心参数。命令行拉流示例vlc rtsp://192.168.1.100:554/Streaming/Channels/101 --network-caching100 --live-caching100 --clock-jitter0 --clock-synchro0这几个参数的含义--network-caching100网络缓冲100ms默认1000ms。--live-caching100直播流专用缓冲100ms。--clock-jitter0时钟抖动容忍设为0不做多余缓存。--clock-synchro0关闭音视频强制同步减少等待时间。调完之后延迟能压到300-500ms左右。注意如果网络抖动较大太激进的缓冲参数会导致画面频繁卡顿要权衡。就我的经验来说内网用50-100ms都没事外网建议100-300ms。5.2 推流保活与自动重连做无人值守推流的时候VLC进程可能会因为源文件读取错误、网络闪断等挂掉。处理办法是写一个简单的Shell守护脚本让它在VLC退出后自动重启#!/bin/bash while true; do vlc --loop /path/to/video.mp4 :sout#transcode{vcodech264,acodecmpga,ab128,channels2,samplerate44100}:rtp{sdprtsp://:8554/stream} :sout-keep echo VLC exited, restarting in 3 seconds... sleep 3 done把上面内容存成vlc-keepalive.sh然后chmod x vlc-keepalive.sh ./vlc-keepalive.sh脚本逻辑很简单VLC进程只要退出不管是因为崩溃还是正常结束等3秒后自动重新运行。这里3秒的延迟是必要的防止网络端口还没释放就被立刻占用。如果要在后台运行整个脚本可以配合nohup或者systemd。用systemd管理更正规[Unit] DescriptionVLC RTSP Streamer Afternetwork.target [Service] ExecStart/home/user/vlc-keepalive.sh Restartalways Useruser [Install] WantedBymulti-user.target把上面的内容保存到/etc/systemd/system/vlc-stream.service然后sudo systemctl daemon-reload sudo systemctl enable vlc-stream.service sudo systemctl start vlc-stream.servicesystemd方式的优点是自启动顺序可控还能在开机时自动拉起推流服务。我自己实际部署过好多台这类小服务配合systemd之后基本不用再管它。还有一个值得提的技巧如果你推流的同时希望留一份录像做备份可以用:sout的并联输出。VLC的sout链支持同时输出到多个目的地用逗号分隔:sout#transcode{vcodech264,acodecmpga}:duplicate{dstrtp{sdprtsp://:8554/stream},dststandard{muxts,dst/path/to/backup.ts,accessfile}}duplicate模块会把流复制一份一份推到RTSP服务一份本地写文件。这个功能在旁路录制场景下特别好用。5.3 多路拉流与硬件加速如果一台Ubuntu机器上同时拉多路流比如拉了8个摄像头CPU占用会变得很可观。VLC默认是用软件解码8路720P 15fps的流就能让4核CPU命苦。这时候开启硬件解码是必须的。命令行方式vlc --avcodec-hwany rtsp://192.168.1.101/Streaming/Channels/101或者GUI模式下“工具”→“偏好设置”→“输入/编解码器”→硬件加速解码选“自动”。不过老实说我做多路拉流时一般不用VLC而用ffmpeg或GStreamerVLC更适合交互式使用而不是批量处理。但如果你只是临时想把4-5路流在一个屏幕里做监控墙VLC的多窗口也能凑合。真实的多路监控墙需求建议用ZoneMinder或Frigate这类专用软件VLC不是一个长久的方案。6. 写在最后的实操心得前面基本上把VLC推拉流的常用姿势和Ubuntu下的典型问题都过了一遍。最后说几个我在这些场景下反复体会到的经验供你参考。第一个经验永远先分清“推流端问题”还是“拉流端问题”。很多排查浪费在错误的方向上比如在拉流端折腾半天其实推流端压根没起来。我的习惯是第一件事用独立工具验证一下流是否活着比如用ffprobeffprobe rtsp://192.168.1.100:8554/stream几秒种内就能看到流的编码信息、帧率、分辨率。如果ffprobe也拿不到信息问题大概率在推流端或网络跟拉流端VLC无关。这个方法能帮你把排查范围缩小一半。第二个经验命令行永远比GUI更能暴露真相。GUI模式下VLC把很多错误信息吞掉了而命令行会把错误直接打印到终端。不管是排查路径问题、网络问题还是编码问题先用命令行拉一次流看它报什么。很多时候VLC自己已经把原因写在报错里了。第三个经验用版本管理的方式看待VLC。Ubuntu仓库里的VLC版本老旧是一个长期问题养成“装完系统先升级VLC”的习惯能避开很多莫名其妙的兼容性坑。尤其是在对接新的RTSP摄像头或流媒体服务器时VLC版本越新兼容性越好。最后再分享一个小技巧如果你有定时推流的任务比如每天早上9点推一段视频9点半停可以直接配合cron来做# crontab -e 0 9 * * * vlc --loop /path/to/morning.mp4 :sout... :sout-keep /dev/null 21 30 9 * * * pkill -f morning.mp4思路很简单定时启动推流定时杀掉对应进程。配合之前说的--loop和-f参数整个过程无需人工干预。推流的进程管理说白了就是“起一个进程、保活、到点清理”这三件事。VLC这个工具看起来简单但真正用好的关键在于对协议和参数的理解而不只是会点播放按钮。看完这篇文章你至少能从“能用VLC播视频”升级到“能指挥VLC干活”——不管是推流、拉流、录制还是无人值守都能有一套清晰的思路和可复现的命令行方案。遇到问题的时候分清层次、看准报错、对症下药基本没有搞不定的场景。