Last active
November 17, 2021 10:58
-
-
Save themerius/e92cd767340d11d2b80276e48c397e30 to your computer and use it in GitHub Desktop.
Generate a simple epub file with scala / java containing video and images
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package services | |
| import java.io._ | |
| import java.nio.charset.StandardCharsets | |
| import java.util.zip.{ZipEntry, ZipOutputStream} | |
| object EPubGenerator extends App { | |
| // based on examples found here https://idpf.github.io/epub3-samples/30/samples.html | |
| val zipFile = File.createTempFile("ecard-epub-", ".epub") | |
| val zipOut = new ZipOutputStream(new FileOutputStream(zipFile)) | |
| addFileToZip(zipOut, "application/epub+zip", "mimetype") | |
| addFileToZip(zipOut, containerXml.toString(), "META-INF/container.xml") | |
| addFileToZip(zipOut, packageOpf.toString(), "EPUB/package.opf") | |
| addFileToZip(zipOut, coverHtml.toString(), "EPUB/xhtml/package.xhtml") | |
| addFileToZip(zipOut, tocHtml.toString(), "EPUB/xhtml/toc.xhtml") | |
| addFileToZip(zipOut, p30Html.toString(), "EPUB/xhtml/p30.xhtml") | |
| // add multimedia files | |
| //addFileToZip(zipOut, new File("path/to/video.mp4"), "EPUB/video/shared-culture.mp4") | |
| //addFileToZip(zipOut, new File("path/to/image.jpg"), "EPUB/images/326261902_3fa36f548d.jpg") | |
| zipOut.close() | |
| println("generated zip file") | |
| println(zipFile.getAbsolutePath) | |
| // upload or whatever ... | |
| // zipFile.delete() | |
| def addFileToZip(zipOut: ZipOutputStream, content: String, fileName: String) = { | |
| val stream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)) | |
| addFileToZip(zipOut, stream, fileName) | |
| } | |
| def addFileToZip(zipOut: ZipOutputStream, content: File, fileName: String) = { | |
| val stream = new FileInputStream(content) | |
| addFileToZip(zipOut, stream, fileName) | |
| } | |
| def addFileToZip(zipOut: ZipOutputStream, content: InputStream, fileName: String) = { | |
| try { | |
| val zipEntry = new ZipEntry(fileName) | |
| zipOut.putNextEntry(zipEntry) | |
| var reading = true | |
| while (reading) { | |
| content.read() match { | |
| case -1 => reading = false | |
| case data => zipOut.write(data) | |
| } | |
| } | |
| zipOut.closeEntry() | |
| } finally { | |
| content.close() | |
| } | |
| } | |
| def xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" | |
| def htmlHeader = "<!DOCTYPE html>" | |
| def containerXml = <container xmlns="urn:oasis:names:tc:opendocument:xmlns:container" version="1.0"> | |
| <rootfiles> | |
| <rootfile full-path="EPUB/package.opf" media-type="application/oebps-package+xml"/> | |
| </rootfiles> | |
| </container> | |
| def packageOpf = <package xmlns="http://www.idpf.org/2007/opf" version="3.0" xml:lang="en" unique-identifier="uid" prefix="cc: http://creativecommons.org/ns#"> | |
| <metadata xmlns:dc="http://purl.org/dc/elements/1.1/"> | |
| <dc:title id="title">...</dc:title> | |
| <dc:creator>...</dc:creator> | |
| <dc:identifier id="uid">...</dc:identifier> | |
| <dc:language>en-US</dc:language> | |
| <meta property="dcterms:modified">2012-01-20T12:47:00Z</meta> | |
| <dc:publisher>....</dc:publisher> | |
| <dc:contributor>...</dc:contributor> | |
| <dc:description>...</dc:description> | |
| <dc:rights>...</dc:rights> | |
| <link rel="cc:license" href="https://...."/> | |
| </metadata> | |
| <manifest> | |
| <item id="img1" href="images/326261902_3fa36f548d.jpg" media-type="image/jpeg" properties="cover-image"/> | |
| <item id="video1" href="video/shared-culture.mp4" media-type="video/mp4"/> | |
| <item id="cover" href="xhtml/cover.xhtml" media-type="application/xhtml+xml"/> | |
| <item id="toc" properties="nav" href="xhtml/toc.xhtml" media-type="application/xhtml+xml"/> | |
| <item id="p30" href="xhtml/p30.xhtml" media-type="application/xhtml+xml"/> | |
| </manifest> | |
| <spine> | |
| <itemref idref="cover" linear="no"/> | |
| <itemref idref="toc"/> | |
| <itemref idref="p30"/> | |
| </spine> | |
| </package> | |
| def coverHtml = <html xmlns="http://www.w3.org/1999/xhtml"> | |
| <head> | |
| <meta charset="utf-8"/> | |
| </head> | |
| <body style="text-align: center;"> | |
| <hgroup id="covertitle"> | |
| <h1>lorem ipsum</h1> | |
| <h2>lorem ipsum</h2> | |
| </hgroup> | |
| <img id="img-cover" src="../images/326261902_3fa36f548d.jpg" alt="the description"/> | |
| </body> | |
| </html> | |
| def tocHtml = <html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops"> | |
| <head> | |
| <meta charset="utf-8"/> | |
| </head> | |
| <body> | |
| <section class="base" id="toc"> | |
| <h1>lorem ipsum</h1> | |
| <nav epub:type="toc"> | |
| <h2>table of contents</h2> | |
| <ol> | |
| <li> | |
| <a href="p30.xhtml"> | |
| <span class="toc-label">lorem ipsum</span> | |
| <span class="toc-desc">Unscripted autoplay video in mp4</span> | |
| </a> | |
| </li> | |
| </ol> | |
| </nav> | |
| <nav epub:type="landmarks"> | |
| <h2>guide</h2> | |
| <ol> | |
| <li> | |
| <a epub:type="toc" href="#toc">Table of Contents</a> | |
| </li> | |
| <li> | |
| <a epub:type="bodymatter" href="p30.xhtml">Begin Reading</a> | |
| </li> | |
| </ol> | |
| </nav> | |
| </section> | |
| </body> | |
| </html> | |
| def p30Html = <html xmlns="http://www.w3.org/1999/xhtml"> | |
| <head> | |
| <meta charset="utf-8"/> | |
| </head> | |
| <body> | |
| <section class="base"> | |
| <h2>lorem ipsum</h2> | |
| <p>lorem ipsum</p> | |
| <video id="video1" autoplay="" role="button" aria-controls="video1" controls=""> | |
| <source src="../video/shared-culture.mp4" type="video/mp4"/> | |
| <div class="errmsg"> | |
| <p>Your Reading System does not support (this) video.</p> | |
| </div> | |
| </video> | |
| <p>Lorem ipsum</p> | |
| </section> | |
| </body> | |
| </html> | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment