🎬 第三章 FFmpeg三大常用工具及应用选项详解
📄 一句话概括

ffplay 比另外两个多要三样东西:SDL2、图形界面、声卡。 少了任何一样,它就连窗口都开不起来。

📝 本节和前面几节的关系

3.1 讲了三个工具的分工,这一节专门讲那个「要窗口」的。 3.2.1 到 3.2.4 分别讲它的常用参数、高级参数、可视化与外部服务器。

一、它比另外两个多要什么

同样是链接那七个库,ffplay 还额外要三样系统层面的东西:

依赖 ffmpeg 要吗 ffplay 要吗


libav* 七个库 要 要 SDL2 不要 要 图形界面 不要 要 声卡设备 不要 要

这张表解释了一个非常常见的现象:服务器上 ffmpeg 跑得好好的,ffplay 一敲就报 SDL 错。 不是装坏了,是那台机器本来就没有图形环境——SDL 起来找不到窗口系统。

那种场合要做的是「把流转出去」而不是「在本地看」,也就是第八章的推流。 所以「ffplay 起不来」不是故障,是选错了工具。

二、三种启动方式

区别只在输入是什么,参数一个都不用改:

输入 命令 要注意什么


本地文件 ffplay 片子.mp4 最常用,直接开 网络流 ffplay rtmp://… 或 http://… 要等缓冲,起播慢 采集设备 ffplay -f dshow -i video=… 平台相关,要先列设备

第二行的「等缓冲」是可以调的:默认会先攒一段再开始放。 想快就 -fflags nobuffer,但代价是网络一抖就卡;想稳就 -infbuf,代价是吃内存。

第三行的 -f dshow 是必须的:设备没有扩展名,ffmpeg 猜不出来。 这也是 3.11.4 那一节要专门讲设备的原因——它是 demuxer 里最特殊的一类。

三、窗口里那几个键

参数表背不下来没关系,这几个键更常用:

按键 作用 什么时候用


q 或 Esc 退出 随时 空格 或 p 暂停/继续 想看清某一帧 s 单帧步进 逐帧检查画面 f 全屏切换 看画质细节 ← → 快退/快进十秒 跳着看

第三行那个 s 是排查画面问题的第一把工具。 一帧一帧往前走,能看清哪一帧开始花屏、哪一帧偏色——反复重播是看不出这个的。

还有一个没写在表上的:按 a 切换音轨。 多语言素材里这条键比参数好用,因为它不用重开文件。

四、动手 Demo:它比另外两个多要三样东西

沙箱起不了播放窗口,但可以验证它「要吃的那份数据」是通的。 这一段确认解码链能走通,并明确标出哪一层测不到。

import os
import av
import numpy as np

# 造一份 5 秒素材,就是 ffplay 要吃的东西
c = av.open(u"src.mp4", u"w")
s = c.add_stream(u"libx264", rate=25)
s.width, s.height, s.pix_fmt = 160, 90, u"yuv420p"
for i in range(125):
    a = np.zeros((90, 160, 3), dtype=np.uint8)
    a[:, :, 0] = (i * 2) % 256
    f = av.VideoFrame.from_ndarray(a, format=u"rgb24")
    for pk in s.encode(f):
        c.mux(pk)
for pk in s.encode(None):
    c.mux(pk)
c.close()

# 验证解码链(ffplay 的第一半工作)
c = av.open(u"src.mp4")
st = c.streams.video[0]
n = sum(1 for _ in c.decode(video=0))
c.close()
print(u"文件 %d 字节" % os.path.getsize(u"src.mp4"))
print(u"解出 %d 帧  分辨率 %dx%d" % (n, st.width, st.height))

实跑输出:

--------------------------------------------------------------------
ffplay 工具简介——它比另外两个多要三样东西
--------------------------------------------------------------------

**① ffmpeg 只用库,ffplay 还要用系统的东西**

  依赖              ffmpeg 需要吗     ffplay 需要吗
  -----------------------------------------------------
  libav* 七个库     要                要
  SDL2              不要              要
  图形界面          不要              要
  声卡设备          不要              要

**这张表解释了一个常见现象:服务器上 ffmpeg 跑得好好的,ffplay 一敲就报 SDL 错。**
**不是装坏了,是那台机器本来就没有图形环境。**

**② 三种启动方式,区别只在「输入是什么」**

  输入         命令                           注意
  --------------------------------------------------------
  本地文件     ffplay 片子.mp4                最常用
  网络流       ffplay rtmp://… / http://…     要等缓冲
  采集设备     ffplay -f dshow -i video=…     平台相关

**第二种要留意缓冲:默认会先攒一段再开始放,表现是「敲下去要等几秒才出画面」。**
**调 `-fflags nobuffer` 或者 `-probesize` 能把这个等待压短。**

**③ 播放窗口里那几个键,比参数表更好用**

  按键          作用                 什么时候用
  ---------------------------------------------------
  q 或 Esc      退出                 随时
  空格 或 p     暂停/继续           想看清某一帧
  s             单帧步进             逐帧检查画面
  f             全屏切换             看画质细节
  ← →           快退/快进 10 秒     跳着看

**`s` 那个键是排查画面问题的第一把工具:一帧一帧看,比反复重播有用得多。**

**④ 沙箱里没有 ffplay.exe,但可以确认它的数据源是通的**

  项             值            说明
  -------------------------------------------------------
  素材存在       9606 字节     ffplay 要吃的东西
  能解出帧       125 帧        说明解码链通
  分辨率         160x90        窗口初始大小
  ffplay.exe     没有          沙箱只装了库,没装外壳

**最后一行是关键:这一段证明的是「解码链通」,不是「窗口能开」。**
**窗口那一层要 SDL 和桌面,沙箱给不了,所以文案里不写「实测播放成功」。**

这一段证明的是「解码链通」,不是「窗口能开」。 窗口那一层要 SDL 和桌面环境,沙箱给不了,所以文案里不写「实测播放成功」。

这个区分不是文字游戏:很多「ffplay 放不了」的问题,原因是权限、显卡驱动、 远程桌面会话没有 3D 加速——这些都在窗口那一层,跟解码一点关系都没有。

判断到底是哪一层出问题,有个简单办法:先跑 ffprobe。 ffprobe 能打出流信息,说明文件和解码器都没问题,锅在窗口那一层。

30 秒实验

  1. 放一次:ffplay 片子.mp4,然后按 s 步进、按 p 暂停,体会「一帧一帧」是什么感觉。
  2. 关掉一路:ffplay -vn 片子.mp4 只听不看,-an 则只看不听。两个字母分别对应 video 与 audio。
  3. 看时间戳:ffplay -debug_ts 片子.mp4,它会打出每一帧的 pts,同步问题一眼可见。

常见误区

  1. 在无桌面的服务器上用 ffplay。它依赖 SDL,需要图形界面。那种场合该推流,不是本地播放。
  2. 以为「ffplay 打不开」就是文件坏了。先跑 ffprobe,它能读说明文件没问题,锅在窗口层。
  3. 把 ffplay 当日常播放器。它没播放列表、没设置界面,定位是「验证文件」的工具。
自测三问(点开对答案) 1. ffplay 需要而 ffmpeg 不需要的三样东西是什么? —— SDL2、图形界面、声卡设备。前两个决定能不能开窗口,第三个决定有没有声音。 2. 为什么「ffplay 起不来」在服务器上是正常现象? —— 因为没有图形环境,SDL 找不到窗口系统。这不是故障,是工具选错了——该用推流而不是本地播。 3. 播放时想逐帧检查画面,按哪个键? —— `s`。按一次前进一帧,配合 `p` 暂停可以停在任意一帧上细看。

相关笔记