📑 EPUB Parser for Flutter 📑
Pub Version

Flutter Package to parse EPUB files (EBooks), with support for Media Overlays!

If you found this package useful, star this repo and drop a like in pub.dev! 🌟.

Features

✅ Read EPUB from bytes
✅ Read EPUB from dart:io file
✅ List metadata: title, authors, language, etc. (with support for EPUB2)
✅ List resources: audio, images, text, etc.
✅ List sections (also commonly named "chapters") in default reading order
✅ Get section audio (if exists)
✅ Get text-audio synchronization info for each section
✅ Get text segment given a time for each section

Work in progress

  • Direct getters for relevant attributes (such as title, authors, etc.)
  • Read navigation definition
  • Support for bindings

Getting started

Install epub_decoder as a dependency.

Usage

Start by instancing an Epub from an Epub file:

import 'package:epub_decoder/epub_decoder.dart';

// Creating an EPUB from an asset transformed to bytes
final epubFile = await rootBundle.load('assets/example.epub');
final epub = Epub.fromBytes(epubFile.buffer.asUint8List());

And then, access its properties:

  • Retrieving Metadata: epub.metadata

    Expand for example result

    Please note that this is actually a List<Metadata> object (here you are seeing its .toString() representation).

    [
        {
            key: identifier,
            id: pubID,
            value: urn:uuid:8a5d2330-08d6-405b-a359-e6862b48ea4d,
            refinements: [
                {
                    id: null,
                    value: uuid,
                    refinesTo: pubID,
                    property: identifier-type,
                    schema: null,
                    name: null,
                    content: null,
                    refinements: []
                }
            ]
        },
        {
            key: title,
            id: title,
            value: [DEMO] How To Create EPUB 3 Read Aloud eBooks,
            refinements: []
        },
        {
            key: creator,
            id: aut,
            value: Alberto Pettarin,
            refinements: [
                {
                    id: null,
                    value: aut,
                    refinesTo: aut,
                    property: role,
                    schema: null,
                    name: null,
                    content: null,
                    refinements: []
                },
                {
                    id: null,
                    value: Pettarin, Alberto,
                    refinesTo: aut,
                    property: file-as,
                    schema: null,
                    name: null,
                    content: null,
                    refinements: []
                }
            ]
        },
        {
            id: null,
            value: portrait,
            refinesTo: null,
            property: rendition:orientation,
            schema: null,
            name: null, content: null, refinements: []
        },
        {
            id: null,
            value: 0:00:53.320,
            refinesTo: s001,
            property: media:duration,
            schema: null,
            name: null,
            content: null,
            refinements: []
        }
    ]
    
    
  • Retrieving resources/items: epub.items

    Expand for example result

    Please note that this is actually a List<Item> object (here you are seeing its .toString() representation).

    [
        {
            id: toc,
            href: Text/toc.xhtml,
            mediaType: ItemMediaType.xhtml,
            properties: [ItemProperty.nav],
            mediaOverlay: null,
            refinements: []
        },
        {
            id: cover,
            href: Text/cover.xhtml,
            mediaType: ItemMediaType.xhtml,
            properties: [],
            mediaOverlay: null,
            refinements: []
        },
        {
            id: c001,
            href: Styles/style.css,
            mediaType: ItemMediaType.css,
            properties: [],
            mediaOverlay: null,
            refinements: []
        },
        {
            id: p001,
            href: Text/p001.xhtml,
            mediaType: ItemMediaType.xhtml,
            properties: [],
            mediaOverlay: {
                id: s001,
                href: Text/p001.xhtml.smil,
                mediaType: ItemMediaType.mediaOverlay,
                properties: [],
                mediaOverlay: null,
                refinements: [{
                    id: null,
                    value: 0:00:53.320,
                    refinesTo: s001,
                    property: media:duration,
                    schema: null,
                    name: null,
                    content: null,
                    refinements: []
                }]
            },
            refinements: []
        }
    ]
    
    
  • Retrieving reading sections: epub.sections

    Expand for example result

    Please note that this is actually a List<Section> object (here you are seeing its .toString() representation).

    [
        {
            content: {
                id: cover,
                href: Text/cover.xhtml,
                mediaType: ItemMediaType.xhtml,
                properties: [],
                mediaOverlay: null,
                refinements: []
            },
            readingOrder: 1,
            audioDuration: null,
            smilParallels: []
        },
        {
            content: {
                id: p001,
                href: Text/p001.xhtml,
                mediaType: ItemMediaType.xhtml,
                properties: [],
                mediaOverlay: {
                    id: s001,
                    href: Text/p001.xhtml.smil,
                    mediaType: ItemMediaType.mediaOverlay,
                    properties: [],
                    mediaOverlay: null,
                    refinements: [{
                        id: null,
                        value: 0:00:53.320,
                        refinesTo: s001,
                        property: media:duration,
                        schema: null,
                        name: null,
                        content: null,
                        refinements: []
                    }]
                },
                refinements: []
            },
            readingOrder: 2,
            audioDuration: 0:00:53.320000,
            smilParallels: [
                {
                    id: p000001,
                    clipBegin: 0:00:00.000000,
                    clipEnd: 0:00:02.680000,
                    textFileName: p001.xhtml,
                    textId: f001
                },
                {
                    id: p000002,
                    clipBegin: 0:00:02.680000,
                    clipEnd: 0:00:05.480000,
                    textFileName: p001.xhtml,
                    textId: f002
                },
                {
                    id: p000003,
                    clipBegin: 0:00:05.480000,
                    clipEnd: 0:00:08.640000,
                    textFileName: p001.xhtml,
                    textId: f003
                },
                {
                    id: p000004,
                    clipBegin: 0:00:08.640000,
                    clipEnd: 0:00:11.960000,
                    textFileName: p001.xhtml,
                    textId: f004
                }
            ]
        }
    ]
    
    
  • Retrieving text segment from a certain time

    final section = epub.sections[1];
    final targetTime = Duration(seconds: 10);
    print(section.getParallelAtTime(targetTime)));
    
    Expand for example result

    Please note that this is actually a SmilParallel object (here you are seeing its .toString() representation).

    {
        id: p000004,
        clipBegin: 0:00:08.640000,
        clipEnd: 0:00:11.960000,
        textFileName: p001.xhtml,
        textId: f004
    }
    
    

Additional information

To understand EPUB3 specification and therefore plan the structure of this package, the following page was taken as reference: Package and Metadata | EPUB3 Best Practices.

However, you can learn more about in the EPUB3 official specification documentation and EPUB Media Overlays documentation.

Contributing

  • If you have any request or find some bug, feel free to open a new issue.
  • if you want to contribute, open a new issue with your proposal and if approved, continue with a pull request 😉.