電書部技術班、電子書籍配信サーバーに挑む

第5回電書原稿からEPUBをつくりだす

電書部EPUB

今回は電書部版EPUB作成の要件と入出力、そしてEPUB生成について説明します。EPUBそのものについて詳しくは説明しませんが、流れの中で必要なことにはふれていきます。

要件

ターゲット

EPUBリーダは世の中にいろいろあります。第1回で説明したように、電書部ではまずはiPhoneアプリのStanzaをターゲットにしました。

図1 iPhone Stanzaで表示した電書
図1 iPhone Stanzaで表示した電書

変換処理

決められた原稿フォーマットからEPUBに変換するには、おおまかに次の処理が必要になります。

  • 本文をXHTMLに変換する
  • 適切なcssを用意する
  • EPUBの必須ファイルを用意する。特にopf/ncxを生成する
  • ファイルを適切に配置する
  • EPUBの規格にしたがったzipファイルをつくりだす

変換後のEPUB

変換後のEPUBは、電書部の配信サーバで処理できる構造になっている必要があります。特に、EPUBのどこかに購入者のe-mailアドレスを入れる必要があります。

入力される原稿

入力される原稿の形式については、前回説明しました。ここでは全体像のみ再掲します。

電書原稿の例
densho_sample/ # 任意のディレクトリ
  00_maegaki.txt  # 本文原稿
  01_genkou.txt
  02_genkou.txt
  03_atogaki.txt
  04_writers.txt
  cover.txt       # 表紙原稿
  cover.jpg       # 画像ファイル
  capture.jpg
  okuduke.txt     # 書籍情報
  toc.txt         # 目次情報

出力されるEPUB

EPUBファイルはzip圧縮されたファイルです。電書部原稿から生成したEPUBの中は次のようになります。

変換後EPUB内文書の例
mimetype
META-INF/container.xml
OEBPS/content.opf
OEBPS/toc.ncx
OEBPS/css/miraitext.css
OEBPS/img/cover.jpg
OEBPS/img/capture.jpg
OEBPS/text/cover.html
OEBPS/text/00_maegaki.html
OEBPS/text/01_genkou.html
OEBPS/text/02_genkou.html
OEBPS/text/03_atogaki.html
OEBPS/text/04_writers.html
OEBPS/text/04_writers.html
OEBPS/text/okuduke.html

okuduke.htmlを除くhtmlファイルは、原稿のテキストファイル(YDML)から生成されています。cssファイルは、YDMLに対応する固定のものを使います。EPUB仕様に関わるファイル(mimetype,container.xml, content.opf, toc.ncx)について、以下で説明します。

mimetype

mimetypeをEPUBのzipアーカイブ先頭に非圧縮で格納します。内容は固定です。

mimetype
application/epub+zip

container.xml

container.xmlは、EPUBの構成情報に関するメタデータをおさめたOPFファイルを指し示すファイルです。電書部EPUBではOPFファイルの場所を固定していますので、内容は電書によらず同じになります。

電書部EPUBのcontainer.xml
<?xml version="1.0" encoding="UTF-8"?>
<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>

content.opf

content.opfは、EPUBの構成情報をおさめます。

content.opfの例
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="BookID">
  <metadata xmlns:opf="http://www.idpf.org/2007/opf" xmlns:dc="http://purl.org/dc/elements/1.1/">
    <dc:language>ja</dc:language>
    <dc:publisher>電子書籍部(米光一成)</dc:publisher>
    <dc:creator>電子書籍部</dc:creator>
    <dc:date>2010-11-30</dc:date>
    <dc:title>サンプル電書</dc:title>
    <dc:identifier id="BookID" opf:scheme="URL">http://lv99.com/densho/ebooksdensho_sample2010/11/30</dc:identifier>
    <dc:contributor>構成・テキスト:XXX
グラフィックス:XXX
写真:XXX</dc:contributor>
    <meta name="cover" content="imgcover"/>
  </metadata>
  <manifest>
    <item id="imgcover" href="img/cover.jpg" media-type="image/jpeg"/>
    <item id="imgcapture" href="img/capture.jpg" media-type="image/jpeg"/>
    <item id="cover" href="text/cover.html" media-type="application/xhtml+xml"/>
    <item id="chap00_maegaki" href="text/00_maegaki.html" media-type="application/xhtml+xml"/>
    <item id="chap01_genkou" href="text/01_genkou.html" media-type="application/xhtml+xml"/>
    <item id="chap02_genkou" href="text/02_genkou.html" media-type="application/xhtml+xml"/>
    <item id="chap03_atogaki" href="text/03_atogaki.html" media-type="application/xhtml+xml"/>
    <item id="chap04_writers" href="text/04_writers.html" media-type="application/xhtml+xml"/>
    <item id="css" href="css/miraitext.css" media-type="text/css"/>
    <item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/>
    <item id="okuduke" href="text/okuduke.html" media-type="application/xhtml+xml"/>
  </manifest>
  <spine toc="ncx">
    <itemref idref="cover"/>
    <itemref idref="chap00_maegaki"/>
    <itemref idref="chap01_genkou"/>
    <itemref idref="chap02_genkou"/>
    <itemref idref="chap03_atogaki"/>
    <itemref idref="chap04_writers"/>
    <itemref idref="okuduke"/>
  </spine>
</package>

metadata要素に、okuduke.txtにほぼ対応する情報が入ります。<meta name="cover">が指定されていると、多くのEPUBリーダでは対応するイメージを表紙画像として扱います。

manifest要素に、EPUBを構成するファイルが記述されます。そしてspine要素に、表示順序が規定されます。

toc.ncx

toc.ncxには、目次へ反映される情報を含むナビゲーション情報が記述されます。次の例では、原稿のtoc.txtに対応した内容になっています。

toc.ncxの例
<?xml version="1.0" encoding="UTF-8"?>
<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1">
  <head>
    <meta name="dtb:uid" content="http://lv99.com/densho/ebooksdensho_sample2010/11/30"/>
    <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="chap00_maegaki" playOrder="1">
      <navLabel>
        <text> 前書き</text>
      </navLabel>
      <content src="text/00_maegaki.html"/>
    </navPoint>
    <navPoint id="chap01_genkou" playOrder="2">
      <navLabel>
        <text> この本に書かれていること</text>
      </navLabel>
      <content src="text/01_genkou.html"/>
    </navPoint>
    <navPoint id="chap04_writers" playOrder="3">
      <navLabel>
        <text> 執筆者プロフィール</text>
      </navLabel>
      <content src="text/04_writers.html"/>
    </navPoint>
  </navMap>
</ncx>

okuduke.html

okuduke.htmlは、原稿のokuduke.txtから自動的に生成します。

okuduke.htmlの例
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
  <head>
    <title>サンプル電書</title>
    <link rel="stylesheet" type="text/css" href="../css/miraitext.css"></link>
  </head>
<body>
<p class="backcover">
サンプル電書 <br />
電子書籍部 <br />
構成・テキスト:XXX<br />グラフィックス:XXX<br />写真:XXX<br /> 
2010/11/30 <br />
電子書籍部(米光一成) <br />
(this book is for !!!-mail-!!!)</p>

</body>
</html>

内容は、ほぼokuduke.txtに対応しているのが分かると思います。!!!-mail-!!!の部分は、配信サーバでの購入者のメールアドレスに置き換えられます。

そのほかのXTHMLファイルはYDMLからの変換によって生成されます。

入出力の対応

電書部のEPUBを構成するファイルは、原稿との対応から次のように分類できます。

  • 原稿のメタデータおよび、原稿ファイルの情報からつくられるメタデータ
  • 原稿テキストから変換して作られるテキスト
  • メタデータなどから生成されるテキスト
  • 原稿の中からそのままコピーされるデータ
  • 電書によらず内容が固定のデータ

入出力の概要は、次の通りです。

図2 入出力の対応
図2 入出力の対応

コンバータの構成

コンバータは次の要素から構成されています。

YDMLメタデータハンドラ

コンバータは、次のことを行います。

  • okuduke.txtを読みとる
  • toc.txtを読みとる
  • okuduke.htmlを生成する
  • EPUBライブラリに必要なメタデータを渡す

基本的には、必要な情報を構造化して持ち、必要な出力をするだけの単純な役割です。

YDML to HTML変換

cover.txtおよび本文のテキストをHTML変換を行います。前回説明したNoratextを利用しています。また、このモジュールでcssを生成します。cssの内容はYDMLからの変換に対応した固定のものです。

EPUB生成ライブラリ

最終的なEPUBを生成します。このライブラリがmimetype/content.opf/toc.ncxを生成し、与えられたxhtml/cssなどをパッケージしてzipファイルをつくります。開発開始時点ではrubyで書かれた適切なEPUB生成ライブラリがみあたらなかったため、新たに作りました。

そして、上記3つを適切に組み合わせて、呼び出すコマンドがあります。

具体的なライブラリとしてはEPUB生成ライブラリのgepubおよびYDML関連ユーティリティのydml_utils(執筆時点で未公開、http://github.com/skoji/以下で公開予定)からなります。ydml_utilsには、上記のメタデータハンドラ・YDML to HTML変換・そして変換コマンドが含まれます。

発生した問題

ここまでで説明したように、原稿からEPUBを生成するのはそれほど難しいことではありません。しかし、それでもいくつかの問題がありました。いくつか、例をあげます。

リーダのふるまい

EPUB仕様は標準化されているものの実際にどのような見た目になるのかはリーダ次第です。また、リーダがEPUB仕様を正しく実装しているとは限りません。

たとえばiPhone Stanzaでは、本文のマージンや右よせ・左よせ・センタリングなど、見た目の一部をユーザが設定することができます。ユーザが設定できない要素でも、たとえば<h1>などはデフォルトでセンタリングされます。Stanza側のアピアランス仕様・設定とEPUB内cssの関係がどのようになっているのかがわからないため試行錯誤せざるをえず、苦労しました。現状はすべてのスタイルに!important;をつけるという乱暴な方法をとっています。

また、PCでよく使われるEPUBリーダAdobe Digital Editionsでは、各XHTMLファイルにlang属性を指定しないと日本語のEPUBがうまく表示できません。しかしEPUBの仕様では、言語指定はcontent.opfで行い、各XHTMLでは指定してはいけないことになっています。現状の電書部EPUBでは、XHTMLファイルにlang属性を付加しています。

ルビ

原稿にルビがあった場合には、EPUB2.0で拡張モジュールとして定義されている<ruby>タグをXHTML内に埋め込んでいました。対応していないリーダではタグが無視され、ルビ文字が括弧にはいるようにしました。Stanzaは<ruby>タグに対応しておらず、ルビは括弧に入って表示されていました。

ところがiPhoneがiOS4になってから、Stanzaで<ruby>タグ部分の表示がくずれるようになりました。ルビ文字が小さなフォントで表示され、前後の改行がおかしくなるのです。<ruby>タグに対応したものの、表示にバグがあるという厄介な状態です。iOS4 Safariでも<ruby>タグを含むHTMLが同じように表示されるため、WebKitに起因するバグでしょう。

EPUBのメインターゲットをiPhoneとしている電書部では仕方なく、iOS4以降に変換した電書では<ruby>タグを出力しないようにしています。

今後の予定

現在は、前回説明したパーサをEPUB変換へ組み込む変更をしています。その後コードを公開して、rubyを動作させる環境さえあれば誰でも電書部フォーマットからEPUBへの変換が使えるようにします。電書部のEPUB変換はそこで一段落つくと考えています。

EPUBライブラリgepubは、汎用EPUBライブラリというには機能が不十分なので(特に、langがja固定というのは言語道断です⁠⁠、修正していきます。また、現在はEPUB生成しかできませんが、EPUBを読み取る機能も追加する予定です。

おすすめ記事

記事・ニュース一覧