制作 Kindle 电子书
在看一般的书的时候,Kindle 相比纸质书有压倒性的优势。之前我一直误认为 Amazon 对 Kindle 电子书的制作并不提供官方的公开支持,而是选择和大出版商合作。事实上,Kindle 电子书的文件格式相当开放,Amazon 也提供制作需要的工具链,而且用起来也非常方便。
1. 准备源文件和工具
源文件方面,只需要准备文本和插图就可以。如果书的内容比较复杂,可能还会有视频、声音等素材。
工具方面,Amazon 提供了 kindlegen
,用它就可以把源文件打包成 Kindle 可用的格式。kindlegen
可以在 Amazon 的对应页面下载。顺便,也建议准备好这些官方的样例,一会儿一些文件直接在样例基础上修改就行。
2. 处理文本
Kindle 书的文本、排版实际上是用 HTML(和 CSS)描述的,因此首要的就是把排版、文本都处理好,转换成 HTML。这一步怎么做要看源文件的格式。比如源文件是普通的 text,那需要在每一段加上 <p></p>
。图片这个时候也要插进去,就像写一个简单的网页一样。Kindle 支持不少 HTML 和 CSS 的特性,例如图片可以用 width="100%"
修饰,实现类似单页插图的效果;再例如可以规定字体、文字大小之类的。完成之后可以用一般的浏览器预览下,预览的效果如何,基本在 Kindle 就会显示成那样。一本 Kindle 书可以用很多 HTML 组成,后面会有地方规定这些 HTML 出场的顺序。
需要注意的是,对于中文文本(和所有希望用 UTF-8 编码的文本),要在文件开头用 <?xml version="1.0" encoding="UTF-8" ?>
注明编码。在 <head>
里用 <meta charset="utf-8" />
规定编码,Kindle 是不理的。
下面是 Kindle 书中一个 HTML 文件的例子。可以看到,章节标题、图片位置之类的都是人工设定的格式和位置。之前我以为这些 metadata 会有专门地方去写,然后 Kindle 自动排版,看来并不是这样。一个 Kindle 和一个 HTML 描述的页面没有本质上的区别,只是需要制作者对 Kindle 的屏幕(黑白、大小)做优化。
<?xml version="1.0" encoding="UTF-8" ?>
<!doctype html>
<html lang="zh">
<head>
<meta charset="utf-8"/>
<title>第六·五章</title>
<link rel="stylesheet" href="text.css" type="text/css"/>
</head>
<body>
<h1>第六·五章 从毕业典礼经过三天后</h1>
<p>blah blah</p>
<img src="images/9.jpg" width="100%">
<p>blah blah</p>
<p>「感觉,你是不是,完全,弄错了呢……!」</p>
<div class="pagebreak"></div>
</body>
</html>
3. 目录
Kindle 书的目录有两种,一个就是普通的 HTML,这个 HTML 和正文也没有本质的区别。还有一个是。.ncx
文件,事实上是个 XML,用来存放元数据,提供给 Kindle 用于在阅读界面中显示目录(章节、位置索引),就像下图就是根据 .ncx
来的。
.ncx
文件里面会包含书名和一个个 navPoint
,每个 navPoint
会包含条目的显示文字(<text>
)、源文件位置(<content>
)和顺序(playOrder
)。下面是一个 .ncx
文件的例子。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN"
"http://www.daisy.org/z3986/2005/ncx-2005-1.dtd">
<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1">
<head>
</head>
<docTitle>
<text>路人女主的养成方法:第七卷</text>
</docTitle>
<navMap>
<navPoint id="toc" playOrder="1"><navLabel><text>目录</text></navLabel><content src="toc.html#toc"/></navPoint>
<navPoint id="pr" playOrder="2"><navLabel><text>序章</text></navLabel><content src="62257.htm"/></navPoint>
<navPoint id="ch1" playOrder="3"><navLabel><text>第一章 咦?照这样看,这次是不是走进个别剧情线了?</text></navLabel><content src="62258.htm"/></navPoint>
<navPoint id="au" playOrder="15"><navLabel><text>后记</text></navLabel><content src="69021.htm"/></navPoint>
</navMap>
</ncx>
HTML 目录,写起来就自由很多,可以随意控制目录的显示效果。它也是不涉及任何 metadata 的,甚至不做这个目录也行。像下面这个例子,就只是用 <ul>
简单弄了一个。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>目录</title>
</head>
<body>
<h1 id="toc">目录</h1>
<ul>
<li><a href="62257.htm">序章</a></li>
<li><a href="62258.htm">第一章 咦?照这样看,这次是不是走进个别剧情线了?</a></li>
<li><a href="69021.htm">后记</a></li>
</ul>
</body>
</html>
3. Metadata
Metadata 是存放在 .opf
文件里的。里面可以包含的 metadata 非常多。这个文件主要包含以下几块
<metadata>
,放有关作品的 metadata,比如作品名、作者名<manifest>
,列出整个电子书涉及的文件,主要是 HTML、.ncx
,CSS 和图片列不列都没关系<spine>
,描述显示给用户的时候,一个个 HTML 按什么顺序出现<guide>
,会列整本书关键的位置,例如正文的开始之类的,用于确定在上面图片中的“开始”标记
下面是一个 .opf
文件的例子,
<?xml version="1.0" encoding="utf-8"?>
<package unique-identifier="uid" xmlns:opf="http://www.idpf.org/2007/opf" xmlns:asd="http://www.idpf.org/asdfaf">
<metadata></metadata>
<manifest></manifest>
<spine toc="ncx"></spine>
<guide></guide>
</package>
对于 <metadata>
,像这种做完自己看看,不去发布不去卖的书,放一个封面、作品名、作者名就可以了。这里支持的 metadata 其实挺多的,在 Open Package Format 的 spec 里有详细地列出。下面是一个 <metadata>
的例子。
<metadata>
<dc-metadata xmlns:dc="http://purl.org/metadata/dublin_core" xmlns:oebpackage="http://openebook.org/namespaces/oeb-package/1.0/">
<dc:Title>路人女主的养成方法:第七卷</dc:Title>
<dc:Language>zh</dc:Language>
<dc:creator opf:role="aut">丸户史明</dc:creator>
<x-metadata>
<EmbeddedCover>images/cover.jpg</EmbeddedCover>
</x-metadata>
</dc-metadata>
</metadata>
可以看到列出了书名、作者、封面图片位置。
对于 <manifest>
,只要列出重要的正文文件即可。
<manifest>
<item id="content" media-type="text/x-oeb1-document" href="toc.html"></item>
<item id="ncx" media-type="application/x-dtbncx+xml" href="toc.ncx"/>
<item id="t1" media-type="text/x-oeb1-document" href="62257.htm"></item>
<item id="t2" media-type="text/x-oeb1-document" href="62258.htm"></item>
<item id="t3" media-type="text/x-oeb1-document" href="62259.htm"></item>
</manifest>
这里对每个文件都加了个 ID。这个 ID 一会儿 <spine>
中会用于 ref 这个文件。
下面是 <spine>
,和 <guide>
。在 <spine>
中只需要把文件按希望出现的顺序,用 <manifest>
设置的 ID 列一下就可以了。<guide>
里列了目录和正文开头的位置。
<spine toc="ncx">
<itemref idref="content"/>
<itemref idref="t1"/>
<itemref idref="t2"/>
<itemref idref="t3"/>
</spine>
<guide>
<reference type="toc" title="目录" href="toc.html"/>
<reference type="text" title="正文" href="62257.htm"/>
</guide>
4. 生成
这一步非常简单。执行
kindlegen your.opf
就可以了。过程中如果出现 warning,最好一一解决,以免显示效果出错。生成出来的 .mobi
文件可以直接拷贝进 Kindle 里看。