みかづきの色々

デバイス(スマホからキャンプ用品まで)とかプログラミングとか中心のいろいろ試験的なブログ。

epub文書を自力で作る話

Android+epub読み上げの便利さ

私がスマホを何に最も多用しているのかというと、間違いなくGoogle Playブックスアプリを使った小説の読み上げだろう。同アプリのAndroid版には本文読み上げの機能があり、移動中に読み上げをBGM代わりに聴くのであるが……唯一問題があるのは、epub3レベルのやつを自作できてなかたことだ。以前は epub2 レベルのを自作ツールで生成させていたが、これは実は構成的に誤りだったらしい事がわかっているし。反省。

ところがepubを吐けるエディタは意外に少なく、またそれらの機能をもつものになると読み上げとは無関係の機能ばかりで、肝心の部分は使いづらくて困ってたんですよね……。

あのね、読み上げという観点からいくと、文書構造を正しく吐いてくれればソレでいいんですよ。Webだって、デザインは出力してからCSSでやるもんでしょ。変換ツールでいいのよ。なぜそれをやってくれないかなぁ。

そんなことを考えていたら、pandoc に出会いました。簡単な規則で作ってくれます。ありがたや

pandocのインストール

これはOS環境によるので、ぐぐればいいでしょう。うちの Debian GNU/Linux なら、 apt install pandoc で一発です。

pandoc の使い方

Markdownテキスト本体を作る

方法はいくつかある。たとえば以下。

  1. CherryTreeのテキスト出力はmd形式のようだ。
  2. vscodeでmd形式のファイルを書く。(やればわかるが、#で章立てすると左のペインにちゃんとリアルタイムで認識される)
  3. Other:他にもいくつか対応エディタがあるようだ。

メタデータを作る

別に本文に混ぜてもいいが、別にしたほうがよさげ。名前は metadata.md で内容は以下。

---  
title:  
- type: main  
  text: 文書タイトル  
creator:  
- role: author  
  text: 作者  
page-progression-direction: rtl  
---  

directionはrtlにしないと、個人的にはいやかな。

pandocで変換する。

うちなら、こんな感じになる。

pandoc --metadata title=タイトル 文書ファイル.md metadata.md -o 出力.epub --css=tategaki.css  --toc

tocは、 Table of contents(目次) といえば、章立てテキストを扱ったことのある人なら説明不要でしょう。

tategaki.css の中身はこんなものです。

html {  
  -webkit-writing-mode: vertical-rl;  
  -epub-writing-mode: vertical-rl;  
  writing-mode: vertical-rl;  
}

どこかのサイトでもらってきた単純なやつですけど、スマホで読む縦書きにはきっと充分。

おまけ・文書整形

これで最低限のepub変換はできるけど、日本語を扱ってきた人なら、ルビはどうやってふるのって話が出るでしょう。
そういう話です。

ルビのふりかた

結論から言いますと、epub変換する前にHTMLのルビ使って埋め込めばバッチリです。

ですけど、手書きでHTMLのルビタグなんて、地の文書書いてる時にやりたくないですよね?

この場合の変換器は自分で考えてみてください。私は青空文庫形式に近い「 |漢字(かんじ) 」な書き方をするので、以下のようなフィルタを書いています。もちろん好きにやってください。

rubyfilter.pl (perl)

#!/usr/bin/env perl
while(<>){
  # ルビタグ用調整
  s/\|([^\(]+)\(([^\)]+)\)/\<ruby\>$1<rp>(<\/rp><rt>$2<\/rt><rp>\)<\/rp><\/ruby>/g;
  print
}

段落の処理

うちは小説なので、段落ごとの字下げをしつつもカギカッコは例外とか、そういうテキスト処理をすることがあります。

また、拾った誰かのネット小説を手持ちのデバイスにあわせて変換するのは、それこそ電子端末の歴史と同じくらい長いです。昔話をゴテゴテ語るつもりはありませんが、それくらい普通の事と思ってください。

そんなわけで、上に書いたウチの変換スクリプトを書いてみます。これもルビ同様、pandocにかける前にやります。

なお、rubyタグと別のスクリプトでやっていたり、ルビがPerlなのにこっちはPythonなのは単に歴史的な事情ですが、単に「この文書はルビだけ処理しよう」というケースがあり、別にしておいたほうが便利だからってのもあります。そのあたりの事情は人それぞれなので、お好きになさるのがよいでしょう。

#!/usr/bin/env python

import re

fn = "/dev/stdin"

with open(fn) as f:
    l99 = f.read()
    y = re.sub(r'\t+','\t',l99)
    y = re.sub(r'\n+','\n',y)
    y = re.sub(r'\r','',y)
    y = re.sub(r'\n','\n\n',y)
    y = re.sub(r'^ +','',y, flags=re.MULTILINE)
    y = re.sub(r'^',' ',y, flags=re.MULTILINE)
    y = re.sub(r'^ \n','\n',y, flags=re.MULTILINE)
    #y = re.sub(r'^ 「','「',y, flags=re.MULTILINE)
    y = re.sub(r'^ (「|『|#)','\\1',y, flags=re.MULTILINE)
    print(y)

総合処理

とりまとめはシェルでやってます。まぁun*x生活者なので。

~/bin/md2epub.sh 

#!/bin/sh

if [ "$1" != "" ];then
    _T=$1
    cat ${_T}.md | ~/bin/rubyfilter.pl | seikei.py > ${_T}_a.md
    pandoc --metadata title=${_T} ${_T}_a.md metadata.md -o ${_T}.epub --css=$HOME/bin/tategaki.css  --toc
fi

使い方は、以下のようになります。なお、タイトルとタイトル.md のようにタイトルとファイル名は一致させています。

$ md2epub.sh 二年間の休暇

↑のやりかたで、 二年間の休暇.md がルビ処理や調整をして 二年間の休暇_a.md に変換され、 pandoc を経由して 二年間の休暇.epub が作成されます。