達人出版会日記

ITエンジニア向けの技術系電子書籍の制作と販売を行う達人出版会のブログです。

はじめてのEPUB:その1

世間では電子書籍の共通フォーマットはEPUBで決まり、といったような風潮があるので、EPUBについて調査中です。

サービスの立ち上げにはもろもろの事情によりもう少し時間がかかりそうなので、EPUBについて調べたことを小出しに書いていきます。

EPUBって何?

まずはじめに、予備知識のない方のため、EPUBについての説明をしておきます。

EPUBというのは、「IDPF」という電子書籍の開発と促進を進める標準化団体が提案というか提唱している電子書籍のフォーマットです。というとちょっと語弊がありそうで、EPUBというのは一個のフォーマットの「仕様」ではないのでした。Webで言えば、HTTPとHTMLとCSSの3つを合わせて(さらにはUnicodeとかURIとかも合わせて)「WWW」という一つの標準仕様です、といったような意味で、EPUBというのはOPS、OPF、OCFを合わせた(ついでにDTBのNCXも組み合わされた)一つの電子書籍標準仕様なのです。

そういう意味ではややこしいのですが、実際にEPUBのファイルを作った場合、1冊分の書籍コンテンツファイルとしては「.epub」という拡張子がついた1つのファイル、例えば「abc.epub」などのファイルになります。その点では分かりやすいかもしれません。つまり、こういう.epubなファイルを作ったり、そのファイルを読み込んだりするために必要な標準仕様(の集まり)、それがEPUBなのです。

さらに言うと、実際にはリーダー(Webで言うところのブラウザ)の実装状況も見逃せません。一つの.epubファイルも、リーダーで閲覧する際にどのように表示されるかは、リーダーによって微妙な差があります。すなわち、Webでおなじみの「ブラウザの互換性」のようなものが発生するのです。もっとも、これはリーダーのデバイスというか、ハードウェア自体がまちまちなのでどうしようもないところなのでしょうけど。

そのため、仕様からEPUBの実際を探っていくと、相当辛い目に合いそうです。なので、はじめてのEPUBとしては、とりあえず一個ファイルを作ってみましょう。

hello worldEPUB

プログラミング言語の学習においては、まず「Hello, World!」といった文字列を表示させることになっています。それにならって、まずはHello, World!と表示されるだけのEPUBファイルを作ってみましょう。

なお、この連載(になるはず)はちまちま進んでいきます。もうちょっとさくっと結果がほしい方は「電子書籍ファイルePubについて -ePubを自分で作成する-」を、いきなりデータがほしい方は「日本語Epubブックサンプル」を見られた方がよいでしょう。

前口上は済んだので、さっそくファイルの用意をはじめましょう。

まず必要となるのはコンテンツのファイルです。ここでは、「content001.xhtml」という名前にします。

<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
<head>
<title>サンプル文書001</title>
</head>
<body>
<h1>Hello, World!</h1>
<p>こんにちはこんにちは!</p>
</body>
</html>

見ての通り、ふつうにXHTMLなファイルです。ほんとに「Hello, World!」 だけではさみしいので、見出し以外に本文もつけてみました。しかも日本語なので、日本語に対応していないリーダーでは読めません。あしからず。

また、html要素にlang属性とxml:lang属性がついています。これがないと面倒なことになったことがあるので、念のためつけておいてみてます。それともう一つ、スタイルについてはCSSが指定できるのですが、ここでは省いています。

さて、実際に閲覧されるコンテンツはこのファイルだけでも十分なのですが、.epubなファイルを作るためには他にいくつかファイルが必要になります。最低限でも以下のようなファイルが必要となります。

  • mimetype ファイル
  • META-INF/container.xml ファイル
  • OEBPS/content.opf ファイル
  • OEBPS/toc.ncx ファイル

mimetypeとcontainer.xmlディレクトリも合わせて上記の場所にないといけないようです。content.opfとtoc.ncxは場所は決まっておらず、container.xmlから芋づる式に指定されます。

まずmimetypeファイルから見ていきましょう。中身は一行だけです。

application/epub+zip

中身もこれで決め打ちにしておけばいいようです。「+zip」というのが気になりますが、EPUBはzipで固めることになっています。

続いてcontainer.xmlです。

<?xml version="1.0"?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
  <rootfiles>
    <rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml" />
  </rootfiles>
</container>

こちらも何も考えずにこうしておけばいいようです。実際には、rootfileについてはfallbackの仕組みがあり、上記の場合、OPFを解釈できないリーダー用に別のrootfileを指定することも可能なのですが、それは考えなくてもいいでしょう。

さて、次はcontent.opfです。そろそろ山場です。

<?xml version="1.0"?>
<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="BookID" version="2.0">
    <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
        <dc:title>サンプル001</dc:title>
        <dc:creator opf:role="aut">高橋征義(達人出版会)</dc:creator>
        <dc:language>ja</dc:language>
        <dc:identifier id="BookID" opf:scheme="URL">http://example.com/epub/sample/sample1.epub</dc:identifier>
    </metadata>
    <manifest>
        <item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/>
        <item id="content001.xhtml" href="text/content001.xhtml" media-type="application/xhtml+xml"/>
    </manifest>
    <spine toc="ncx">
        <itemref idref="content001.xhtml"/>
    </spine>
    <guide>
        <reference type="cover" title="Cover Page" href="text/content001.xhtml"/>
    </guide>
</package>

ちょっと難しくなってきました。

このOPFファイルもXMLですが、全体がpackage要素でくくられています。package要素にはmetadata要素とmanifest要素、そしてspine要素にguide要素があります。これらはだいたい必要そうです。まああってそんはないでしょう。

metadata要素では、dcという名前空間とopfという名前空間が定義されています。そもそも全体がopfと同じ http://www.ipdf.org/2007/opf という名前空間に属しています。dcはDiblin Coreですね。metadataはダブリンコアボキャブラリを借りて定義されていきます。一つだけ、identifier要素の属性に、opf:scheme属性があります。ここではURLになっていますが、ISBNなどが使われる場合もあります。このidentifierはこのコンテンツのIDを示すもので、例えばリーダーでは、同一IDのファイルは同一コンテンツと見做し、IDが同じファイルが登録されようとした場合に上書きしたりすることがあります。

manifest要素はその.epubファイルで必要とされるファイルが参照されます。ここでは、ncxとコンテンツが参照されてます。

そしてguide要素では、トップページが指定されています。今回は特にトップ用のページはなく、最初にして最後のページがトップになります。


さて、最後にtoc.ncxファイルを見てみましょう。実はこのファイルは、IDPFの決めている仕様ではなく、DAISYコンソーシアムの定めるDigital Talking BookことDTBの仕様の一部となっているようです。ちなみにこの仕様はANSI/NISO Z39.86としても扱われているようです。この辺はまだあんまりはっきりしてませんが、仕様そのものはNISOのサイト内の文書で読めます。

<?xml version="1.0"?>
<!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>
        <meta name="dtb:uid"
              content="http://example.com/epub/sample/sample1.epub"/>
        <meta name="dtb:depth" content="1"/>
        <meta name="dtb:totalPageCount" content="0"/>
        <meta name="dtb:maxPageNumber" content="0"/>
    </head>
    <docTitle>
        <text>サンプル</text>
    </docTitle>
    <navMap>
        <navPoint id="navPoint-1" playOrder="1">
            <navLabel>
                <text>Start</text>
            </navLabel>
            <content src="text/content001.xhtml"/>
        </navPoint>
    </navMap>
</ncx>

んー、実はこのファイルはあんまりまだよく分かってなく……ドキュメントとサンプルを見ながら作ってみた感じです。
基本的な構造としては、rootがncx要素で、その下にhead要素とdocTitle要素、それにnavMap要素があればよさそう。navMap以下が全体のナビゲーションを決めているみたいなんだけど、ここでは1ファイルしかないのでnavLabel要素とcontent要素がそれぞれnavPoint要素内にあるだけ、というところです。

それではいよいよ.epubファイルにまとめてみましょう。

とその前に、ファイル構成を。特に決められているわけではないのですが、コンテンツはOEPBSディレクトリに、さらにテキストはOEBPS/textディレクトリにおさめます。なので、sample1というディレクトリ内のファイルを置いた場合、全体としては以下のようになります。

sample1/META-INF/container.xml
sample1/mimetype
sample1/OEBPS/content.opf
sample1/OEBPS/text/content001.xhtml
sample1/OEBPS/toc.ncx

これをzipで固めて、.epubにリネームします。

$ cd sample1
$ zip -q0X sample1.zip mimetype
$ zip -qXr9D sample1.zip *
$ cp sample1.zip sample1.epub

zipを2回に分けて実行しています。これは、mimetypeというファイルが、圧縮ファイルの最初に、非圧縮のかたちで保存されていなければいけない、という仕様上の要請があり、そのためにこうするとよいようです。

また、zipのオプションがいろいろ出てきました。ざっと説明すると、-qはメッセージ出力の抑制、-0は非圧縮でアーカイブのみ、-Xはファイル属性を保存しないようにする、-rはディレクトリを再帰的に圧縮、-9は圧縮率の向上、-Dはディレクトリを保管しないようにするためのものです。

こうして、sample1.zipを作った後、sample1.epubに名前を変えてコピーしています。これでsample1.epubというEPUBなファイルができました。おめでとうございます。

EPUBの閲覧

せっかく作ったので、リーダーで表示してみましょう。EPUB電子書籍専用端末もいくつか出ているようですが(少なくとも海外では)、PCでも対応したソフトがいろいろあります。

PC向けEPUBリーダーの一つであるStanzaで見てみると以下のようになります。

また、EPUBにも対応した電子書籍管理ツールであるCalibreで表示させると以下のようになります。

…なんか全然違いますね。EPUBの表現は今のところこの程度の差異はあって当然のようです。

とりあえず、なんとか表示までできたので今回はこんなところで。

2010/03/25追記:

もう少しサンプルを追加しておきます。ブラウザベースのリーダーで閲覧した画面を2つほど。ブラウザとしてはSafariを使っています。

まずはオライリーのBookwormから。

そしてibis readerも。これはブラウザ以外もあるのですが、まだブラウザ版しか試していません。

ブラウザベースのものは環境によって違いがありそうですが、正直なところ、ただのWebページとあまり区別がつかないので、例えば有料のコンテンツを読むとがっかり感が漂いそうです。