出力されたEPUBファイルがJava版よりサイズが大きいなと思ったら、JSZIPの圧縮率が低かった。圧縮率を上げてもJavaよりもサイズが大きいのでこれ以上は無理かな。
You:
JSZipの圧縮率が低い this.zos = new JSZip(); // mimetypeは非圧縮 this.zos.file("mimetype", "application/epub+zip"); const content = await this.zos.generateAsync({ type: "nodebuffer" }); await fs.promises.writeFile(epubFile, content); LogAppender.println(epubFile + "に出力されました。");
ChatGPT:
JSZip は デフォルトでは圧縮しません(STORE)。
そのため、generateAsync() に compression オプションを指定しないと圧縮率が低くなります。
EPUBの場合は mimetypeだけ無圧縮、他はDEFLATE圧縮にするのが一般的です。
修正例
JavaScript
this.zos \= new JSZip();
// mimetypeは非圧縮
this.zos.file("mimetype", "application/epub+zip", {
compression: "STORE"
});
// 他のファイルはDEFLATE圧縮
this.zos.file("OEBPS/content.xhtml", htmlData, {
compression: "DEFLATE",
compressionOptions: { level: 9 }
});
const content \= await this.zos.generateAsync({
type: "nodebuffer",
compression: "DEFLATE",
compressionOptions: { level: 9 }
});
await fs.promises.writeFile(epubFile, content);
LogAppender.println(epubFile + "に出力されました。");
圧縮率を上げるポイント
compression: "DEFLATE" を指定
compressionOptions.level = 9(最大圧縮)
mimetypeだけSTORE
重要(EPUB仕様)
EPUBでは
mimetypeZIPの先頭
無圧縮
でないと一部リーダーでエラーになります。
JSZipでは以下にすると安全です。
JavaScript
this.zos.file("mimetype", "application/epub+zip", {
compression: "STORE"
});
さらに圧縮率を上げたい場合
JSZipは そこまで圧縮率が高くないので、Node.jsなら
archiver や yazl を使うと改善することがあります。
もし AozoraEpub3互換でEPUBを作っているなら、
JSZipの**EPUB用の最適ZIP生成コード(Java版と同じ構造)**も出せます。
これを使うと Calibreと同じ圧縮率にかなり近づきます。