Beamer

beamer 自己的用户手册对如何准备演讲只给了一条毫不客气的经验法则:帧数最多每分钟一张。同一份手册记载,Till Tantau 在 2003 年 2 月为自己的博士论文答辩写下了这个 LaTeX class 的第一版;在那之前它只是「一小堆让 seminar 类更好用的私人宏」。一个月后,在同事的建议下他把它放上了 CTAN。本页讲的不是怎么写 frame——那由 beamer class 那一页负责——而是写完的 .tex 文件与那间装着投影仪的房间之间的所有事情:用 aspectratio=169 把幻灯片改成 16:9、删掉没人需要的导航符号、加了备用幻灯片之后仍然诚实的页码、章节扉页、只有你看得见的备注,以及当一份 121 页的幻灯片每次编译要三秒半时该怎么办。

把 beamer 改成 16:9:aspectratio=169,以及默认值到底是什么

一个词就够了:\documentclass[aspectratio=169]{beamer}。而默认值至今仍是 4:3——无论 2026 年会场的投影仪是什么规格,不加设置的 beamer 给你的就是 4:3。用 TeX Live 2024 自带的 beamer 3.71 实际编译并用 pdfinfo 测量:默认页面为 362.835 × 272.126 pt(128 × 96 mm),aspectratio=169453.543 × 255.118 pt(160 × 90 mm)。容易被忽略的是,改成 16:9 不只是变宽:高度从 96 mm 缩到了 90 mm。在 4:3 下排到底边的 frame,一加 aspectratio=169 就会溢出。所以宽高比是最先要定的事,不是最后。

class 选项尺寸pdfinfo 实测值备注
aspectratio=43128 × 96 mm362.835 × 272.126 pt默认值,不写任何选项就是它
aspectratio=169160 × 90 mm453.543 × 255.118 pt当前投影仪的标准;高度少 6 mm
aspectratio=1610160 × 100 mm453.543 × 283.465 pt与许多笔记本屏幕相符
aspectratio=149140 × 90 mm396.85 × 255.118 pt没那么极端的宽屏
aspectratio=32135 × 90 mm382.677 × 255.118 pt3:2
aspectratio=141148.5 × 105 mm420.945 × 297.638 pt正好是 A6 横向,pdfinfo 甚至标注为「A6」
aspectratio=54125 × 100 mm354.331 × 283.465 pt5:4,用于较老的投影仪
aspectratio=2013140 × 91 mm396.85 × 257.953 pt20:13,数字本身就是比例

顺便弄清这些尺寸是怎么传到 PDF 里的,很划算。beamer.cls 把自己算出的宽高作为 papersize={...} 交给 geometry,再由 geometry 改写 \pdfpagewidth\pdfpageheight。这件事比看上去重要。在普通 LaTeX 里,即使写 \documentclass[letterpaper]{article}输出的 PDF 仍然是 A4(实测 595.276 × 841.89 pt),因为 TeX Live 的 pdftexconfig.tex 已经先设了 \pdfpagewidth = 210 true mm,而标准 class 从不去动它。beamer 自己重新做了这次覆盖,所以不会掉进这个坑。反过来说,如果你在导言区加了手动改 \pdfpagewidth 的代码,就只剩 beamer 自己的尺寸计算被落在后面,居中的图会偏。别去碰它。

latex
% decide this before you place a single figure
\documentclass[aspectratio=169]{beamer}

% inside a frame, always express sizes relative to the slide,
% never in absolute cm, so a later ratio change survives
\includegraphics[width=0.8\textwidth]{plot.pdf}
\includegraphics[height=0.6\textheight]{photo.jpg}

在导言区加一行 \setbeamertemplate{navigation symbols}{} 就没了。那排浅浅的符号不是装饰,而是由六个部件拼成的真链接。看 beamerouterthemedefault.sty 里的定义,它不过是把 \insertslidenavigationsymbol\insertframenavigationsymbol\insertsubsectionnavigationsymbol\insertsectionnavigationsymbol\insertdocnavigationsymbol\insertbackfindforwardnavigationsymbol 并排放着,而每个部件自带 2 到 4 条超链接。用 default 主题编译一份只有一帧的幻灯片来数:这一张幻灯片上就带着 20 个 /Link 注释。把模板置空后降为 0;只保留 {\insertframenavigationsymbol} 则降为 4。

部件链接目标条数
\insertslidenavigationsymbol前后幻灯片,以及阅读器的「转到页面」3
\insertframenavigationsymbol上一帧末尾、本帧首尾、下一帧开头4
\insertsubsectionnavigationsymbol小节的四个边界,形式与 frame 相同4
\insertsectionnavigationsymbol章节的四个边界4
\insertdocnavigationsymbol演示的首页与末页2
\insertbackfindforwardnavigationsymbol阅读器菜单命令 GoBack、Find、GoForward3

留还是删,取决于演讲的长度。beamer 的指南就是这么说的:越长的演讲越需要导航提示——90 分钟的课程适合用侧边栏标出当前位置,而十分钟的引言里放目录就显得可笑。落到实处:15 分钟的会议报告就删掉(没人会点,而且打印时也会印在纸上);一学期的课件就保留(学生会在座位上重读 PDF,想跳到某一节)。折中做法是只保留翻帧,即 {\insertframenavigationsymbol}。另外,有些主题(例如 \usetheme{metropolis})本来就把这些符号关掉了,所以要是删不掉,先怀疑主题。

preamble
% remove all six symbols
\setbeamertemplate{navigation symbols}{}

% or keep only the frame-stepping pair
\setbeamertemplate{navigation symbols}{\insertframenavigationsymbol}

显示幻灯片编号:\insertframenumber 与 \inserttotalframenumber

要自己排的话,就在 footline 模板里写 \insertframenumber/\inserttotalframenumber;但如果主题的页脚本来就有编号,更稳妥的做法是选用 beamer 自带的具名模板:写 \setbeamertemplate{page number in head/foot}[totalframenumber] 就得到「3 / 12」的形式(beamerbaseauxtemplates.sty 里定义了三个:framenumbertotalframenumberappendixframenumber)。很多人在这里栽跟头的是:编号数的是 frame,不是 PDF 页。含一个 \pause 的 frame 在 PDF 里是两页,可右下角两页都写着同样的「3 / 3」。按方向键时编号不动,并不是 bug。

第二个坑是第一次编译时总数是错的\inserttotalframenumber 只有在整份幻灯片排完之后才能确定,所以 beamer 把结果写进辅助文件 .nav——打开看看,里面就有 \headcommand {\gdef \inserttotalframenumber {3}} 这一行。删掉 .aux.nav 只跑一次,页脚就会出现 2/13/1 这样破碎的分数;跑第二次才终于变成 2/33/3演讲用的 PDF 一定要编译两遍,这是 beamer 的铁律。接着给标题页和备用幻灯片加上 [noframenumbering],总数就只数正片:实测中首张内容幻灯片原本是「2/3」,仅仅不数标题页就变成了「1/2」。若想让附录自成一套编号,就放上 \appendix 并选择 [appendixframenumber]:正片显示「2/2」,备用幻灯片显示「1/1」,各数各的。

latex
\documentclass[aspectratio=169]{beamer}
\usetheme{Madrid}
\setbeamertemplate{navigation symbols}{}
\setbeamertemplate{page number in head/foot}[appendixframenumber]

\begin{document}
% the title page should not eat frame number 1
\begin{frame}[plain,noframenumbering]\titlepage\end{frame}

\begin{frame}{Results}\end{frame}

% everything after \appendix is counted separately
\appendix
\begin{frame}{Backup: full derivation}\end{frame}
\end{document}

每节自动插入扉页:\AtBeginSection

在导言区放上 \AtBeginSection[]{...},里面写一个含 \tableofcontents[currentsection] 的 frame。仅此一步,每遇到 \section{...} 就会自动插入一张标出「你在这里」的扉页。方括号里的 [] 是给不编号的 \section* 用的参数,意思是「那时什么也不做」;忘了写,附录标题前面也会长出扉页。给插入的 frame 加 [noframenumbering,plain] 是惯例——如前一节所示,这样既不弄脏总数,也去掉了主题的边框装饰。想按小节插入就用 \AtBeginSubsection[]{...};要把 90 分钟的课程分成两大部分,则用 \part{...},每部分拥有各自的目录。

这个机关有个副作用,不知道的话会白白耗掉五分钟。\tableofcontents 是读 .toc 文件排出来的,所以第一次编译时一张扉页也不会出现。实测:一份两节四帧、且没有辅助文件的幻灯片,第一遍是 5 页,第二遍变成 7 页。在搜索「\AtBeginSection 不起作用」之前,先再跑一遍。

preamble
% the [] argument is what runs for \section*, i.e. nothing
\AtBeginSection[]{%
  \begin{frame}[noframenumbering,plain]
    \tableofcontents[currentsection]
  \end{frame}%
}

% same idea one level down
\AtBeginSubsection[]{%
  \begin{frame}[noframenumbering,plain]
    \tableofcontents[currentsection,currentsubsection]
  \end{frame}%
}

观众看幻灯片,自己看备注:演讲者屏幕的两条路

有两条路。第一条只靠 beamer 就够:\setbeameroption{show notes on second screen=right},它会把 PDF 本身横向变成两倍。用一帧的幻灯片实测,页面变为 725.669 × 272.126 pt(= 256 × 96 mm),而页数仍是 1——也就是说输出的是一张纸,左半给观众,右半给自己。改成 =bottom 则是纵向加倍(362.835 × 544.252 pt)。不需要专门软件,只要投影那一侧能裁出左半边即可。第二条路是 TeX Live 2024 自带的 pdfpc 宏包(v0.7.1,2023/10/21),它把备注和演讲时长写进 PDF 自身的元数据。写 \usepackage[overridenote]{pdfpc}\note{...} 的内容就变成 pdfpc 的备注;写 \pdfpcsetup{duration=20, lastminutes=3},二十分钟倒计时和剩余三分钟的提醒就随文件一起走。

这里得说句实话:PDF Presenter Console 本身并不在 TeX Live 里pdfpc 宏包只提供写入元数据的 LaTeX 一侧,负责双屏显示的应用程序(GPLv3+)需要另行安装。反过来说也成立:在无法临时安装软件的场地,show notes on second screen 生成的宽幅 PDF 用任何阅读器都能打开,所以顺手导出一份作为保险,成本为零。至于备注本身怎么写(\note{...} 的语法、用 show notes 插入专用备注页),由讲义那一页负责。

preamble
% route 1: one PDF, twice as wide, no extra software
\setbeameroption{show notes on second screen=right}

% route 2: notes and a countdown clock stored inside the PDF
\usepackage[overridenote]{pdfpc}
\pdfpcsetup{duration=20, lastminutes=3}

长幻灯片编译太慢:\includeonlyframes 与 draft

给正在改的那一帧加上 [label=cur],并在导言区写 \includeonlyframes{cur}。只有那一帧会被输出,其余照样排版但随即丢弃。来实测:一份 40 帧、每帧带三级 overlay 和一张 TikZ 图的幻灯片共 121 页,在这台 Mac 上(TeX Live 2024)每次 3.51 秒。加上 \includeonlyframes{cur} 后变成 3 页、1.39 秒。想到还要跑两遍,等待时间就从约七秒降到不到三秒。class 选项 draft 的作用方式不同:它把页眉、页脚和侧边栏换成灰色色块(这段替换写在 beamerbasemisc.sty 里)。页数仍是 121,用时 2.76 秒。调图的位置时用 draft,要把某一张的版式看上四十遍时用 \includeonlyframes

latex
% preamble: build only the frame you are working on
\includeonlyframes{cur}

% body: the label must match
\begin{frame}[label=cur]{The slide I am fighting with}
  \includegraphics[width=\textwidth]{big-figure.pdf}
\end{frame}

投影的 PDF 与分发的 PDF 是两回事:导出与打印

不要直接打印用于演讲的 PDF。原因出在尺寸上:16:9 的幻灯片是 160 × 90 mm,而 A4 是 210 × 297 mm,一页只印一张会让三分之二的纸留白;何况用了三次 \pause 的 frame 早已变成四页,于是三十分钟的演讲变成一叠 120 张纸。正规做法是用 \documentclass[handout]{beamer}pgfpages 另做一份 PDF,讲义那一页会详细讲。若完全不想改源文件,TeX Live 自带的 pdfjam 可以做后处理:跑一次 pdfjam --nup 2x2 --frame true --paper a4paper --landscape,实测把两张幻灯片放进了一页 A4 横向(841.89 × 595.276 pt)。

terminal
# four slides to an A4 sheet, without touching the source
pdfjam --nup 2x2 --frame true --paper a4paper --landscape \
       --outfile talk-4up.pdf talk.pdf

# check what you actually produced before you print 40 copies
pdfinfo talk-4up.pdf | grep -E "Pages|Page size"
  • 先锁定宽高比aspectratio=169 增加宽度的同时把高度从 96 mm 减到 90 mm。改得太晚,排满的 frame 都会溢出。
  • 一定编译两遍 — 总帧数和章节扉页都要经过 .nav.toc,第一遍会出现 2/1 这类坏掉的编号。
  • 给标题页和备用幻灯片加 [noframenumbering] — 总数就只数正片。想让附录自成一体,用 \appendix[appendixframenumber]
  • 15 分钟的报告就删掉导航 — 一行 \setbeamertemplate{navigation symbols}{}。长课程则相反,保留。
  • 到场前准备三份 PDF — 演讲用、用 show notes on second screen 做的保险版,以及分发用。第三份的做法见讲义那一页。
  • 确认字体已嵌入 — 拷进 U 盘前先用 pdfinfopdffonts 检查一遍。