Flutter电子书解析插件epub_decoder的使用

发布于 1周前 作者 htzhanglong 来自 Flutter

Flutter电子书解析插件epub_decoder的使用

简介

epub_decoder 是一个用于解析EPUB文件(电子书)的Flutter插件,并且支持Media Overlays。


如果你觉得这个包对你有帮助,请给这个仓库点赞并在pub.dev上点个赞!🌟。

功能

  • ✅ 从字节读取EPUB文件
  • ✅ 从dart:io文件读取EPUB文件
  • ✅ 列出元数据:标题、作者、语言等(支持EPUB2)
  • ✅ 列出资源:音频、图片、文本等
  • ✅ 列出阅读顺序中的章节
  • ✅ 获取章节音频(如果存在)
  • ✅ 获取每个章节的文本与音频同步信息
  • ✅ 根据时间获取每个章节的文本片段

开发中

  • ❌ 读取导航定义
  • ❌ 支持绑定

开始使用

首先,在pubspec.yaml中安装epub_decoder作为依赖项。

dependencies:
  epub_decoder: ^x.x.x

使用方法

从EPUB文件实例化一个Epub对象:

import 'package:epub_decoder/epub_decoder.dart';

// 创建一个从资产文件加载并转换为字节的EPUB文件
final epubFile = await rootBundle.load('assets/example.epub');
final epub = Epub.fromBytes(epubFile.buffer.asUint8List());

然后访问其属性:

主要信息

print(epub.title); // 输出电子书的标题
print(epub.authors); // 输出电子书的作者
print(epub.cover); // 输出电子书封面

获取元数据

print(epub.metadata); // 输出电子书的元数据列表

示例结果

[
    {
        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: []
    }
]

获取资源/项目

print(epub.items); // 输出电子书的资源列表

示例结果

[
    {
        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: []
    }
]

获取阅读章节

print(epub.sections); // 输出电子书的章节列表

示例结果

[
    {
        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
            }
        ]
    }
]

根据时间获取文本片段

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

示例结果

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

更多关于Flutter电子书解析插件epub_decoder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter电子书解析插件epub_decoder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何使用Flutter电子书解析插件epub_decoder的示例代码。这个示例展示了如何加载一个EPUB文件并解析其内容,包括书籍的标题、作者和章节信息。

首先,确保你已经在pubspec.yaml文件中添加了epub_decoder依赖:

dependencies:
  flutter:
    sdk: flutter
  epub_decoder: ^latest_version  # 请替换为最新的版本号

然后,运行flutter pub get来安装依赖。

接下来,我们编写一个Flutter应用来演示如何使用epub_decoder

import 'package:flutter/material.dart';
import 'package:epub_decoder/epub.dart';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:path_provider/path_provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'EPUB Decoder Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: EpubDecoderScreen(),
    );
  }
}

class EpubDecoderScreen extends StatefulWidget {
  @override
  _EpubDecoderScreenState createState() => _EpubDecoderScreenState();
}

class _EpubDecoderScreenState extends State<EpubDecoderScreen> {
  EpubBook? _book;
  List<String?>? _chapters;

  @override
  void initState() {
    super.initState();
    _loadEpub();
  }

  Future<void> _loadEpub() async {
    // 假设你有一个EPUB文件作为资产,或者你可以从网络或其他来源加载它
    // 这里为了演示,我们从一个本地资产加载EPUB文件
    ByteData data = await rootBundle.load('assets/sample.epub');
    Uint8List bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);

    // 解析EPUB文件
    _book = await EpubReader().readBook(bytes);

    // 获取章节标题
    _chapters = _book?.toc?.map((tocEntry) => tocEntry.title).toList();

    // 更新UI
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('EPUB Decoder Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: _book == null
            ? Center(child: CircularProgressIndicator())
            : Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    'Title: ${_book!.title}',
                    style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
                  ),
                  SizedBox(height: 16),
                  Text(
                    'Authors: ${_book!.metadata!.authors.join(', ')}',
                    style: TextStyle(fontSize: 18),
                  ),
                  SizedBox(height: 16),
                  Text(
                    'Chapters:',
                    style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                  ),
                  SizedBox(height: 8),
                  Expanded(
                    child: ListView.builder(
                      itemCount: _chapters?.length,
                      itemBuilder: (context, index) {
                        return ListTile(
                          title: Text(_chapters![index] ?? 'Unknown Chapter'),
                        );
                      },
                    ),
                  ),
                ],
              ),
      ),
    );
  }
}

在上面的代码中,我们做了以下事情:

  1. 使用rootBundle.load加载一个本地的EPUB文件(这里假设EPUB文件位于assets文件夹中,名为sample.epub)。
  2. 使用EpubReader().readBook(bytes)方法解析EPUB文件。
  3. 从解析后的EpubBook对象中获取书籍的标题、作者和章节信息。
  4. 使用Flutter的UI组件显示这些信息。

请注意,你需要将EPUB文件放置在项目的assets文件夹中,并在pubspec.yaml中声明它:

flutter:
  assets:
    - assets/sample.epub

这个示例只是一个简单的演示,实际项目中你可能需要处理更多的边缘情况和错误处理。希望这个示例能帮助你理解如何使用epub_decoder插件来解析EPUB文件。

回到顶部