ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

LilyPond 输出简谱实战:结合 LaTeX 与 jianpu 宏包实现专业排版

2026/9/13 16:33:02 拓冰建站 浏览量
LilyPond 输出简谱实战:结合 LaTeX 与 jianpu 宏包实现专业排版 1. 从实际需求聊起LilyPond 做五线谱很顺手简谱却要单独想办法做音乐排版的人应该都有过这种感觉LilyPond 处理五线谱就像开了挂一样输入\relative c { c4 d e f }输出的 PDF 干净漂亮谱面规整得像是出版社直接出的。可一旦碰上简谱需求很多人第一反应是去网上搜“LilyPond 简谱 插件”然后搜出来一堆年份久远的帖子说“官方不支持建议转用某某软件”瞬间就蔫了。我当年接学校合唱团的总谱排版任务时就是这种情况。指挥要求每个声部给一份五线谱同时还要给一份简谱用于学生课后哼唱。当时我的主工具就是 LilyPond实在不想为了简谱单独换一套软件更不想在小节里截图贴图。后来花了两三天把几条路都试了一遍踩了不少坑才整理出一套相对顺手的方案。这篇博文就把我当时折腾出来的思路和做法完整写下来给有同样需求的人做个参考。先说清楚适用范围本文主要面向需要用 LilyPond 输出简谱、并且希望排版效果能接近专业出版物水平的用户。不管你是要排单声部旋律谱还是要做五线谱与简谱对照的合唱谱下面讲的方法都能覆盖。LilyPond 官方本身没有内置原生的简谱排版引擎这一点先说在前面免得大家抱着错误的期待去翻文档。但缺省支持不代表做不了核心思路无非两条要么在 LilyPond 内部把简谱的视觉元素“造”出来要么借助外部工具完成简谱排版后再与 LilyPond 输出整合。两条路各有优劣我后面会分别讲清楚原理和实操过程。2. 先搞懂简谱的本质再谈怎么实现2.1 简谱的记谱元素拆解简谱看起来简单数字 1 到 7 加加减减就完事但真要排版成规范的谱面字符层面的需求并不少。这里我把简谱的视觉组成拆开来看方便后面讲实现方案时大家能对上号。基本音符1 到 7 七个数字外加 0 表示休止符。数字本身用斜体还是正体不同出版社会有不同规范国内大多数出版物习惯用正体或稍带倾斜的数字。时值标记四分音符直接写数字八分音符在数字下方画一条横线十六分音符画两条横线。横线要精确对在数字正下方不能歪。附点音符在数字右侧加附点附点要贴近数字。高低音点高音在数字正上方加点低音在数字正下方加点。点的位置要和数字垂直对齐上下不能跑偏。延音线与连音线延音线是弧线连接同一音高的相邻音表示时值相加连音线是弧线连接不同音高的音表示圆滑奏。这两种线在简谱里都要画成曲线且要越过数字区域。小节线与终止线和五线谱类似小节线是单竖线终止线是细线加粗线。拍号与调号标记简谱的拍号通常写成分数形式比如 4/4 直接写成竖排的数字分数调号则用“1G”或“1bB”这类形式标注在第 1 行。这套体系本质上是在用文本符号加“附加标记”表达音乐信息跟五线谱的“音高位置 符头 符干”逻辑完全不同。LilyPond 默认的音乐字体和布局引擎是为五线谱设计的音符头是椭圆形的音高靠纵向位置体现简谱则是纯横向文本流加上下附加标记。这两个模型的差异就是为什么 LilyPond 不能直接“切换模式”输出简谱的根本原因。2.2 为什么 LilyPond 没能原生支持简谱LilyPond 的核心理念是“让音符自己找到合适的位置”它的内部间距算法围绕五线谱的线间距离、符头大小、声部对齐来设计。简谱的排版重心不在垂直音高关系上而在文本基线、下划线长度、附点位置这些“文字排版”维度上。强行用五线谱的布局引擎去排简谱就像用排版《辞海》的软件去排漫画对话框一样不是不能做是要做大量适配。另外简谱在全球范围内的使用群体高度集中在东亚LilyPond 的维护者以欧美用户为主他们对简谱的诉求并不强烈。GitHub 上确实有过相关 feature request但一直没有进入正式开发计划。我记得曾经有人写过一个简谱相关的 scheme 脚本但只是实验性质功能覆盖面有限离“开箱即用”差得很远。所以如果你想用 LilyPond 出简谱现实一点的态度是不指望官方自己去凑方案。2.3 社区常见的三条技术路线对比既然官方没有原生方案社区里逐渐形成了三种做法。我按照从易到难的顺序说一下你们可以根据自己的需求选。第一种是纯 LilyPond 内部实现利用\markup机制把每个音符数字、下划线、附点手工组合起来。优点是全流程不脱离 LilyPond输出 PDF 统一字体风格可控缺点是非常繁琐写一行旋律要敲一大堆 markup 代码效率偏低只适合短小的旋律片段。第二种是 LilyPond 与 LaTeX 混排用lilypond-book工具把 LilyPond 的谱例嵌入 LaTeX 文档简谱部分用 LaTeX 的简谱宏包或者自建文本排版。优点是简谱的文本排版质量高因为 LaTeX 本来就是搞文字排版的缺点是需要同时掌握 LilyPond 和 LaTeX 两套工具链环境配置略麻烦。第三种是用 LilyPond 出五线谱再配合其他专业简谱软件比如作曲大师、TTComposer 一类的工具或者图形编辑器手动排简谱最后合成 PDF。优点是简谱质量有保障缺点是两个软件的排版风格很难统一五线谱和简谱放在同一页里会显得很“拼接”而且后期修改时要同时改两个文件维护成本高。我个人的建议是如果只是偶尔出一两页简谱选第二种也就是 LilyPond LaTeX 混排性价比最高如果你需要长期在同一个工程里维护大量五线谱和简谱对照的谱例可以考虑用 Perl 或 Python 写个脚本来生成 LilyPond 代码把简谱音符自动转成 markup 形式进一步提升效率。下面我把第二条路线的详细实操过程写出来。3. 实操落地lilypond-book LaTeX 输出规范简谱3.1 环境准备与工具链安装先交代一下我用的环境Ubuntu 22.04 系统LilyPond 版本 2.24.xTeX Live 2023。如果你的系统不一样也没关系核心思路是通用的只要装上 LilyPond 和完整版 TeX Live 就行。LilyPond 的安装不多说官网下载对应系统的安装包即可。关键是要确保lilypond-book命令在终端里能用这个命令包含在 LilyPond 的安装包里不需要额外装。TeX Live 建议装完整版因为简谱宏包会依赖一些冷门宏包精简版经常缺东西。Ubuntu 上直接sudo apt install texlive-full最省心就是安装时间比较长我当年装完花了差不多半小时建议找个不用电脑的时间段操作。我用到的简谱宏包是 CTAN 上的jianpu宏包它是基于musixtex的。安装方式很简单在 LaTeX 文档里\usepackage{jianpu}即可前提是你的 TeX Live 里要有这个宏包。完整版 TeX Live 应该自带如果没有用tlmgr install jianpu装上。3.2 建立工程结构我建议把每个谱例单独放在一个目录里工程结构如下song/ ├── main.tex # LaTeX 主文档 ├── score.ly # LilyPond 五线谱源文件 └── build.sh # 编译脚本main.tex负责整体版式score.ly负责生成五线谱部分build.sh一键出 PDF。这个结构看起来简单但长期维护多个谱例时特别顺手换歌的时候复制整个目录改内容就行不会污染其他工程。3.3 五线谱部分用 LilyPond 输出先看score.ly的示例。假设我们要排一首 4/4 拍的简单旋律C 调前四个小节是 do mi sol do 这样递进的旋律。\version 2.24.0 \header { title 练习曲 composer 佚名 } melody \relative c { \key c \major \time 4/4 c4 e g c | b4 a g e | d4 f a d | c2 r2 | } \score { \new Staff \with { \remove Time_signature_engraver } \melody }注意我在\with里移除了拍号因为简谱部分已经标了拍号五线谱里再标一遍会重复。如果你希望五线谱保留拍号那就去掉这一行。这个文件编译后会生成独立的五线谱 PDF。但我们要做的是混排所以不用单独编译它而是把它嵌入 LaTeX。3.4 简谱部分用 LaTeX jianpu 宏包实现接下来是重头戏。jianpu宏包的基本用法是在jianpu环境里写简谱代码它的语法也很有意思每个音符由\n加数字加时值表示。看下面的例子\begin{jianpu} \par \song{练习曲} { 1C \meter{4}{4} } \begin{center} \begin{music} \par \generalmeter{\meter{4}{4}} \startextract \Notes \n1 \Dqbla \n3 \Dqblg \n5 \Dqblc | \Dqbh \n1 | \Notes \Dqblb \Dqbla \Dqblg \Dqble | \Notes \Dqbla \Dqblf \Dqblj \Dqbh | \Notes \Dqblc \en \zendextract \end{music} \end{center} \end{jianpu}看到\Dqbla这张牙舞爪的写法不要慌这是musixtex底层命令。\Dqbl表示八分音符D 是 double 的简写这里其实代表 eighth 类的命令前缀后面跟的音名小写字母。如果你用宏观视角来看这行的意思就是“一个八分音符 do、一个八分音符 mi、一个八分音符 sol、一个八分音符 do”。这里我直接使用宏包命令时会有一个学习成本所以更推荐的做法是写一个简单的映射表把常用的简谱记谱转成对应的 LaTeX 命令。我当时在博客里整理过一张速查表现在也放出来简谱记法jianpu 宏包写法含义1\n1do四分音符1 -\En或\qu类命令do二分音符具体情况看命令1 下方一横\Dqbl 音名do八分音符1 下方两横\qqbl 音名do十六分音符高音 1上方一点\n1高音 do四分音符上标点低音 1下方一点\n_1或类似命令低音 do四分音符下标点附点八分音符组合命令附点时值参考宏包文档说实话jianpu宏包的手册写得不算友好全是密密麻麻的命令表。我当时是打印了一份命令速查表边查边写。这个投入在前期有点痛苦但写了几个谱例之后就会形成肌肉记忆速度会快很多。3.5 用 lilypond-book 整合两类谱现在到了关键整合步骤。lilypond-book这个工具可以扫描 LaTeX 源文件中的\lilypondfile或\lilypond命令先单独编译 LilyPond 代码再把生成的图形插入 LaTeX 文档。这样我们就能在一个 LaTeX 文档里同时放五线谱和简谱。main.tex的核心内容如下\documentclass[12pt]{article} \usepackage{jianpu} \usepackage{graphicx} \usepackage{geometry} \geometry{a4paper, margin2cm} \begin{document} \section*{练习曲五线谱与简谱对照} \subsection*{五线谱部分} \lilypondfile{score.ly} \subsection*{简谱部分} \begin{jianpu} \song{练习曲} { 1C \meter{4}{4} } \begin{center} \begin{music} \startextract \Notes \n1 \Dqbla \n3 \Dqblg \n5 \Dqblc | \Dqbh \n1 | \Notes \Dqblb \Dqbla \Dqblg \Dqble | \Notes \Dqbla \Dqblf \Dqblj \Dqbh | \Notes \Dqblc \en \zendextract \end{music} \end{center} \end{jianpu} \end{document}然后写一个编译脚本build.sh#!/bin/bash lilypond-book --outputout main.tex cd out pdflatex main.tex pdflatex main.tex里面的--outputout表示把中间文件都生成到 out 子目录里保持根目录整洁。执行两次pdflatex是为了让交叉引用生效虽然我们这里没有涉及引用但养成习惯总没错。这里有一个非常重要的细节系统里可能同时存在pdflatex和lualatexjianpu宏包对lualatex的支持不是很好主要是底层字体编码处理不同容易出现数字显示异常的问题。所以编译时老老实实用pdflatex别折腾其他引擎。3.6 编译过程与输出检查执行bash build.sh之后正常情况下 out 目录里会出现main.pdf。打开看看你应该能看到五线谱和简谱两段内容各自排版风格统一。如果简谱数字没有出现而是显示一堆乱码大概率是字体路径没识别到后文会细说排查方法。如果编译过程中报错先定位是 LilyPond 报错还是 LaTeX 报错。LilyPond 报错会显示音符语法错误比如我最早把\Dqblg写成\Dqgbl就报了“unknown command”的错。LaTeX 报错则通常和宏包依赖缺失有关常见的提示是File jianpu.sty not found这就说明你的 TeX Live 缺宏包跑一遍tlmgr install jianpu就能解决。4. 进阶细节对齐、字体与混合排版4.1 五线谱与简谱的对齐策略上文的方案是“上下排”五线谱在上、简谱在下各自独立成块。这种排法大多数场景够用了。但如果你想要的是“互相对齐”的紧凑谱比如每行上方是五线谱、行内嵌简谱数字情况就复杂一些。我试过两种对齐思路。第一种是在 LilyPond 里把简谱数字作为“附加文本”标记挂到五线谱的每个音符头上用^\markup实现。比如c4^\markup { \override #(font-size . 0) \number 1 } e4^\markup { \number 3 } g4^\markup { \number 5 }这样数字会显示在对应音符上方。优点是对齐天然精确因为 LilyPond 会把 markup 和音符绑定在同一个 X 坐标上缺点是整首曲子下来标记代码冗长而且数字下方的时值线没法自动画只能再次用 markup 画线或加下划线符号。对于简单旋律可以接受复杂节奏型会把自己搞疯。第二种思路是在 LaTeX 里用表格或并排 minipage 的方式来对照。我在实际项目里用得比较多的是这种因为它能利用 jianpu 宏包的全部功能简谱部分能做到自动画时值线。做法是每行分成左侧五线谱、右侧简谱两个 minipage用\hfill填充间距。缺点是小节边界需要手动调整保证两边的乐句切分大致同步不可能做到逐音符像素级对齐。4.2 自制简谱字体的尝试与回归说到简谱排版绕不开字体。jianpu宏包默认用的是 musixtex 字体数字是西文衬线风格跟国内常见的简谱出版物的“圆润黑体数字”风格有明显差异。我一度想替换成自制字体研究过用 FontForge 改 musixtex 的字体但那等于重新做一套简谱字体工作量远超需求。后来我找到一条折中路径如果只是想让数字更好看可以在jianpu环境里临时调整数字字体为 CTeX 提供的中文字体比如宋体或黑体。具体做法是在开头加\renewcommand{\jianpuNumberFont}{\songti}或\renewcommand{\jianpuNumberFont}{\heiti}这样简谱数字会变成中文字体风格整体观感更接近国内出版物。不过要注意这种替换可能会影响时值线的对齐因为不同字体的数字宽度不一样。实测下来黑体的数字宽度比较均匀对齐问题最少宋体的数字在某些字号下会出现间距不均需要手动用\hspace微调。4.3 导出的图像与矢量兼容问题有时候谱例不只是进入 PDF还要贴到公众号文章或者 PPT 里。LilyPond 支持-dbackendsvg直接输出 SVG 格式这个很好用。但lilypond-book生成的五线谱图形默认是嵌入在 PDF 里的想把它们单独捞出来需要额外处理。我的办法是在 LilyPond 源文件里单独编译一个 PDF 或 SVG 版本作为图片素材用lilypond -dbackendsvg score.ly lilypond -dbackendpdf score.ly这样会生成score.svg和score.pdf可以单独插入其他文档。注意 SVG 里的中文字体比如标题里的“练习曲”会依赖系统字体换一台电脑打开时可能字体缺失显示成乱码。如果需要跨平台传递 SVG最好把标题文本去掉或者转成路径曲线。Inkscape 可以批量完成这个操作打开 SVG选择文本对象Path - Object to Path然后保存。实测 SVG 文件体积会增加一些但换设备也不会乱码了。4.4 拍号与小节号的补充规则简谱的拍号要写成竖排分数形式不能像五线谱那样直接画两个数字叠起来。jianpu宏包已经处理了这个问题\meter{4}{4}会输出规范的分数字符。但如果你用纯 markup 方式在 LilyPond 里做简谱拍号就要自己拼\markup { \column { \line { 4 } \line { 4 } } }这样排出来的是一个上下居中的两行文本视觉上基本能达到简谱拍号的效果但间距比专业宏包略差。还有一个需要注意的是调号标记“1G”在jianpu宏包里直接写在音乐开始前的文本区域即可不需要特殊命令{ 1G \meter{4}{4} }这个写法在宏包文档里叫“歌曲头区”位置居中显示在歌名下方、乐谱上方。如果你需要同时显示作词作曲信息也可以在头区里自定义格式我一般写成{ 1G \meter{4}{4} \par \centerline {\small 词某某 曲某某} }实测效果还不错视觉上不会太挤。5. 常见问题与排查技巧实录5.1 jianpu 宏包安装后依然报环境错误这个坑我印象非常深。有一台电脑上装好了完整版 TeX Live\usepackage{jianpu}这行也能顺利通过但编译到音乐环境时报错Undefined control sequence指向\generalmeter。原因是jianpu宏包依赖musixtex的较新版本而旧 TeX Live 自带的 musixtex 版本太老缺少这个命令。解决办法是手动更新宏包用tlmgr update musixtex jianpu命令把它俩升级到最新版。升级完了要清空编译临时目录再重新跑别直接在旧目录里叠加编译不然会碰到aux文件缓存导致新命令不生效的诡异问题。我后来养成了一个习惯凡是改了宏包版本必删out目录重来。5.2 LilyPond 音符和简谱音符对不上这是最让人头疼的一个问题。LilyPond 源文件里的\relative c模式很容易让人把音高写错尤其是跨八度的时候。比如我上面谱例里的d4 f a d如果少写一个变成d4 f a d旋律整体就低了八度但简谱部分写的还是高八度的\Dqbh两边一对照听起来和看起来全对不上。排查方法很简单先把 LilyPond 单独编译成 MIDI用播放器听一遍确认旋律走向符合原谱再对着简谱逐小节数音高。我一般会用\relative c或者干脆不写 relative直接用绝对音高模式c4、d4这样虽然输入繁琐但音高至少不会因为相对模式计算错误。对简谱敏感的场景我推荐用绝对模式出错率低很多。5.3 简谱数字溢出页面右边界当旋律跨度大、小节内音符密集时简谱的文本容易超出页面边界。jianpu宏包默认的\Notes环境不会自动换行需要手动在适当位置断开换成新的\Notes行。我在排版一首 16 小节的儿歌时遇到过这个问题后来总结出经验每行最多排 4 个小节3/4 拍的歌可以排 5 个小节2/4 拍的歌可以排 6 个小节。超过这个量就先换行。具体操作是在音乐环境里插入\bar或\en终止当前行再重新开始新行。虽然有点手动调节的意思但换行位置恰好可以自己控制在乐句断点效果反而比自动断行更符合音乐表达。5.4 编译时间过长怎么办大谱例用lilypond-book编译时会明显变慢主要是因为每插入一个 LilyPond 谱例就要单独启动一次 LilyPond 进程。如果一首合唱曲里有七八个声部谱例编译时间轻松超过两三分钟。我的优化办法是开发阶段只保留当前在改的谱例其他谱例先用\iffalse注释掉等所有内容都改完再把注释去掉做最终编译。另外可以给 LilyPond 加-dno-point-and-click参数这个参数的作用是不在 PDF 里嵌入点源文件跳转信息能省一点编译时间和文件体积lilypond-book --outputout --lilypond-option-dno-point-and-click main.tex实测对于大文档这个选项能减少 10%-20% 的编译时间不算很多但积少成多。5.5 快速排查流程总结我把平时排查问题的流程整理成下面这个顺序遇到问题按序检查基本能定位九成以上的毛病先查 LilyPond 部分单独跑lilypond score.ly确认五线谱没有报错。有错先改 LilyPond。再查 LaTeX 基础环境把main.tex里的\lilypondfile先注释掉只编译简谱部分确认 jianpu 宏包环境可用。最后查整合把五线谱加回来用lilypond-book --verbose模式跑看详细日志里 LilyPond 和 LaTeX 各自的编译状态。如果 PDF 输出不对但日志没有报错多半是缓存问题删掉out目录重来一次。6. 一些该说透的经验总结整套流程走下来我对 LilyPond 输出简谱这件事情的结论是能做但需要接受“手动拼装”的现实不能指望像五线谱那样“写完即所得”。如果你只是偶尔排一页简谱花一个下午搭好 LilyPond LaTeX jianpu 的环境后面每次只是填音符内容速度还是能接受的。我在排一首 30 小节的单旋律简谱时从拿到谱子到输出 PDF大约花 30 到 40 分钟其中一半时间在打简谱命令另一半在调整每行小节数和排版细节。如果换成纯手工绘图软件一首歌至少两三个小时起步还不算后续修改。另一个心得是如果你在团队里协作最好把 LilyPond 源文件和 LaTeX 源文件都纳入版本管理比如 Git。这比保存最终 PDF 有用得多因为谱子总有修改的时候。我见过不少同事直接改 PDF改完没法回溯版本几次迭代下来自己都忘了哪个版本是最终版。用源码工程加 Git 管理每次改动都留痕返工成本低很多。这个内容后续还可以扩展的方向是把简谱的映射规则脚本化。比如用 Python 写一个转换器输入一段类似“C4 E4 G4 C5”这样的音符序列自动生成对应的 jianpu 宏包命令这样就能把五线谱内容批量转成简谱大幅减少手工录入的出错概率。我已经在自己项目里写了第一版后续如果整理稳定了再写一篇专门讲这块的文章。