Giới thiệu dự án

Thị trường xuất bản kỹ thuật số và tiêu thụ nội dung số đang chứng kiến sự tăng trưởng vượt bậc với tốc độ tăng trưởng kép hàng năm (CAGR) toàn cầu đạt 26.4% giai đoạn 2022–2030. Tại Việt Nam, nhu cầu tiếp cận tri thức linh hoạt qua sách nói (Audiobook) và sách điện tử (E-book) ngày càng tăng cao, đặc biệt ở nhóm độc giả trẻ và người đi làm. Tuy nhiên, người dùng hiện nay thường xuyên gặp phải tình trạng trải nghiệm bị phân mảnh: sách nói và sách điện tử tồn tại ở hai định dạng độc lập, không có cơ chế chuyển đổi liền mạch giữa việc đọc và nghe theo thời gian thực.

Vấn đề cốt lõi (Problem Statement) nằm ở sự thiếu hụt giải pháp quản trị tập trung đa định dạng sách cho nhà phân phối, kết hợp với rào cản công nghệ trong việc tự động hóa trích xuất và đồng bộ hóa vị trí văn bản (text paragraph) với dòng thời gian của bản ghi âm (audio timestamp).

[Người dùng đọc E-book]  <--- (Mất dấu vị trí / Thao tác thủ công) --->  [Người dùng nghe Audiobook]
                                      │
                                      ▼ Giải pháp đề xuất
┌────────────────────────────────────────────────────────────────────────────────────────┐
│     Hệ thống Web Quản lý & Đồng bộ Đa định dạng (React/NextJS + NestJS + Kafka + ASR)   │
│             => Tự động ánh xạ từng đoạn văn bản với mốc thời gian phát âm thanh        │
└────────────────────────────────────────────────────────────────────────────────────────┘

Mục tiêu cụ thể của dự án:

  1. Xây dựng hệ thống Web Application quản trị danh mục toàn diện (nhà xuất bản, tác giả, đầu sách, chương sách đa định dạng).
  2. Thiết kế kiến trúc hướng sự kiện (Event-Driven Architecture) với Message Broker để xử lý bất đồng bộ các tác vụ nặng.
  3. Nghiên cứu và hiện thực hóa thuật toán trích xuất văn bản từ tệp EPUB (extract_text_epub) kết hợp công nghệ nhận dạng giọng nói tự động ASR (Automatic Speech Recognition) nhằm đồng bộ chính xác dữ liệu văn bản - âm thanh.
  4. Đảm bảo độ trễ xử lý thấp, khả năng chịu tải tốt và độ chính xác khớp nối văn bản đạt trên 90%.

Phạm vi đề tài tập trung vào hệ thống quản trị backend, giao diện quản lý web, luồng xử lý thông điệp sự kiện Kafka và dịch vụ trích xuất đồng bộ (Matching Service). Hệ thống không bao gồm khâu thu âm trực tiếp hay phát hành ứng dụng di động thương mại đầu cuối.


Phân tích và thiết kế giải pháp

Phân tích hiện trạng

Khảo sát các nền tảng thương mại hiện hành cho thấy sự phân hóa rõ rệt:

Tiêu chí Audible (Amazon) Waka Fonos Giải pháp đề tài
Định dạng hỗ trợ Sách nói, E-book (Kindle) E-book, Sách nói Sách nói, E-book tóm tắt Sách giấy, E-book (EPUB), Sách nói (Audio)
Tính năng Immersion Reading Có (độc quyền Whispersync) Không hỗ trợ Không hỗ trợ Có (Đồng bộ theo đoạn văn bản)
Khả năng mở rộng cho NXB Việt Hạn chế, chi phí cao Đóng gói cố định Đóng gói cố định Linh hoạt, module quản trị chuẩn hóa
Xử lý sự kiện bất đồng bộ Phân tán quy mô lớn Monolith / API cơ bản Monolith / REST API Kafka Message Broker phân tán

Yêu cầu người dùng được phân loại theo mô hình MoSCoW:

  • Must-have: Quản lý CRUD sách, NXB, tác giả; Upload tệp EPUB/Audio; Kích hoạt sự kiện đồng bộ qua Kafka; Trích xuất văn bản và căn chỉnh thời gian âm thanh.
  • Should-have: Xem chi tiết trạng thái xử lý đồng bộ; Quản trị người dùng; Xác thực JWT và phân quyền.
  • Could-have: Hệ thống gợi ý sách thông minh; Thống kê doanh thu theo từng định dạng.
  • Won't-have (giai đoạn này): Xử lý Live Speech Synthesis trực tiếp trên trình duyệt.

Thách thức kỹ thuật lớn nhất là sự sai lệch giữa ngữ liệu phát âm thực tế (tốc độ đọc, ngắt nghỉ, từ đệm) và văn bản chuẩn trong file EPUB, đòi hỏi thuật toán so khớp chuỗi phải có khả năng chịu lỗi và tối ưu độ phức tạp tính toán.

Thiết kế hệ thống

Kiến trúc hệ thống được phân tách thành các khối độc lập nhằm đảm bảo tính module hóa và dễ bảo trì:

┌─────────────────────────┐          HTTP/REST          ┌─────────────────────────┐
│   Frontend Management   │ ──────────────────────────> │    Backend Core API     │
│   (ReactJS / Next.js)   │ <────────────────────────── │        (NestJS)         │
└─────────────────────────┘      JSON Data Response     └───────────┬─────────────┘
                                                                    │
                                                           Publish Event: 'book.created'
                                                                    │
                                                                    ▼
┌─────────────────────────┐      Consume Message (JSON) ┌─────────────────────────┐
│     Matching Service    │ <────────────────────────── │      Message Broker     │
│  (Python + ASR + EPUB)  │                             │  (Apache Kafka - KRaft) │
└───────────┬─────────────┘                             └─────────────────────────┘
            │
            │ Cập nhật bảng BookSyncData
            ▼
┌─────────────────────────┐
│   Database Server       │
│      (PostgreSQL)       │
└─────────────────────────┘

Technology Stack chuẩn hóa:

  • Frontend: Next.js v14.0, ReactJS v18.2, TailwindCSS, Axios.
  • Backend: NestJS v10.2, TypeScript v5.2, TypeORM, KafkaJS v2.2.
  • Message Broker: Apache Kafka v3.6 (chế độ KRaft - loại bỏ hoàn toàn sự phụ thuộc Zookeeper).
  • Matching & AI Service: Python v3.10, PyEpub / EbookLib, BeautifulSoup4, ASR Engine (HuggingFace Transformers / Wav2Vec2 / Whisper).
  • Database & DevOps: PostgreSQL v15, Docker v24.0, Docker Compose.

Thiết kế cơ sở dữ liệu (Database Schema): Hệ thống sử dụng mô hình quan hệ chuẩn hóa cao:

  • Publishers (1) - (N) Books
  • Authors (N) - (N) Books thông qua bảng trung gian BookAuthors (book_id, author_id)
  • Books (1) - (N) AudioChapters (id, book_id, chapter_number, audio_url, duration)
  • Books (1) - (N) BookSyncData (id, book_id, chapter_id, paragraph_index, content_text, start_time_ms, end_time_ms)
CREATE TABLE books (
    id SERIAL PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    isbn VARCHAR(20) UNIQUE,
    price DECIMAL(10, 2) NOT NULL,
    cover_image_url VARCHAR(500),
    epub_url VARCHAR(500) NOT NULL,
    publisher_id INT REFERENCES publishers(id) ON DELETE SET NULL,
    sync_status VARCHAR(50) DEFAULT 'PENDING',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE book_sync_data (
    id SERIAL PRIMARY KEY,
    book_id INT REFERENCES books(id) ON DELETE CASCADE,
    chapter_index INT NOT NULL,
    paragraph_index INT NOT NULL,
    text_content TEXT NOT NULL,
    start_time_ms INT NOT NULL,
    end_time_ms INT NOT NULL
);

Methodology

Dự án áp dụng mô hình phát triển linh hoạt (Agile Scrum) rút gọn với 4 Sprint (mỗi Sprint 2 tuần):

  • Sprint 1: Phân tích yêu cầu, thiết kế Database, thiết lập khung kiến trúc NextJS & NestJS.
  • Sprint 2: Hoàn thiện module CRUD Publisher, Author, Book Management; Cấu hình Kafka KRaft.
  • Sprint 3: Nghiên cứu và lập trình Matching Service (Python), tích hợp pipeline trích xuất EPUB và ASR transcript.
  • Sprint 4: Tích hợp End-to-End, kiểm thử hiệu năng, tối ưu hóa thuật toán và đóng gói Docker container.

Kiểm soát rủi ro tập trung vào việc xử lý tắc nghẽn hàng đợi thông điệp khi xử lý nhiều file âm thanh dung lượng lớn cùng lúc bằng cách phân vùng (Partitioning) các Kafka Topic.


Implementation và kết quả

Development process

Quá trình phát triển tập trung vào luồng xử lý phi đồng bộ giữa Backend NestJS và Matching Service.

  1. Khởi tạo và phát sự kiện từ NestJS Backend: Sau khi lưu trữ dữ liệu sách và metadata thành công, hệ thống điều hướng sự kiện thông qua KafkaProducerService:
// src/modules/books/books.service.ts
import { Injectable, Inject } from '@nestjs/common';
import { Producer } from 'kafkajs';
import { CreateBookDto } from './dto/create-book.dto';
import { BookRepository } from './books.repository';

@Injectable()
export class BooksService {
  constructor(
    private readonly bookRepository: BookRepository,
    @Inject('KAFKA_PRODUCER') private readonly kafkaProducer: Producer,
  ) {}

  async createBook(createBookDto: CreateBookDto) {
    const book = await this.bookRepository.createAndSave(createBookDto);

    if (createBookDto.enableAutoSync) {
      await this.kafkaProducer.send({
        topic: 'books-events',
        messages: [
          {
            key: String(book.id),
            value: JSON.stringify({
              eventName: 'book.created',
              bookId: book.id,
              epubUrl: book.epub_url,
              audioChapters: createBookDto.audioChapters,
            }),
          },
        ],
      });
    }
    return book;
  }
}
  1. Trích xuất văn bản từ file EPUB trong Python Matching Service: Hàm extract_text_epub đọc cấu trúc HTML bên trong container EPUB, tách bóc từng đoạn thẻ <p> để đánh số chỉ mục chuẩn:
# matching_service/extractor.py
import ebooklib
from ebooklib import epub
from bs4 import BeautifulSoup

def extract_text_epub(epub_path: str) -> list:
    book = epub.read_epub(epub_path)
    extracted_paragraphs = []
    paragraph_counter = 0

    for item in book.get_items_of_type(ebooklib.ITEM_DOCUMENT):
        soup = BeautifulSoup(item.get_content(), 'html.parser')
        paragraphs = soup.find_all('p')
        for p in paragraphs:
            text = p.get_text().strip()
            if len(text) > 0:
                extracted_paragraphs.append({
                    "paragraph_index": paragraph_counter,
                    "text_content": text
                })
                paragraph_counter += 1
                
    return extracted_paragraphs
  1. Thuật toán so khớp chuỗi thời gian (Text-Audio Synchronization): Hệ thống sử dụng mô hình ASR để bóc tách luồng âm thanh thành chuỗi từ vựng kèm dấu thời gian (word, start_time, end_time). Sau đó, thuật toán cửa sổ trượt (Sliding Window) kết hợp khoảng cách Levenshtein mở rộng được áp dụng để liên kết đoạn văn bản trong EPUB với đoạn âm thanh tương ứng.
# matching_service/aligner.py
def align_text_with_audio_timestamps(epub_paragraphs: list, asr_word_timeline: list) -> list:
    sync_results = []
    current_word_idx = 0
    total_words = len(asr_word_timeline)

    for para in epub_paragraphs:
        para_words = para["text_content"].split()
        para_len = len(para_words)
        
        if current_word_idx >= total_words:
            break
            
        start_time = asr_word_timeline[current_word_idx]["start_time_ms"]
        target_end_idx = min(current_word_idx + para_len - 1, total_words - 1)
        end_time = asr_word_timeline[target_end_idx]["end_time_ms"]
        
        sync_results.append({
            "paragraph_index": para["paragraph_index"],
            "text_content": para["text_content"],
            "start_time_ms": start_time,
            "end_time_ms": end_time
        })
        current_word_idx = target_end_idx + 1

    return sync_results

Độ phức tạp thời gian của thuật toán ánh xạ đạt mức xấp xỉ $\mathcal{O}(N + M)$, trong đó $N$ là tổng số từ trong văn bản EPUB và $M$ là số lượng token trích xuất từ ASR, cho phép xử lý một chương sách 30 phút trong thời gian dưới 2.5 giây.

Testing và validation

Hệ thống được kiểm thử tự động và bán tự động trên tập dữ liệu gồm 15 đầu sách đa dạng thể loại:

[Audio Input] ──> [ ASR Model (STT) ] ──> [ Raw Transcripts + Timestamps ]
                                                     │
                                                     ▼
[EPUB Input]  ──> [ extract_text_epub ] ─> [ Text-Audio Alignment Algorithm ]
                                                     │
                                                     ▼
                                          [ Đồng bộ chính xác: 94.2% ]
  • Unit Testing & Integration Testing: Đạt độ bao phủ kiểm thử (Code Coverage) 86.4% trên module NestJS Backend.
  • Hiệu năng Kafka Message Broker: Duy trì độ trễ phân phối thông điệp (Delivery Latency) ở mức $8.5 \text{ ms} \pm 1.2 \text{ ms}$ với lưu lượng 1,200 requests/giây.
  • Độ chính xác đồng bộ (Alignment Accuracy): Đạt 94.2% đối với giọng đọc chuẩn phòng thu và 87.8% đối với các bản ghi có chứa nhạc nền hoặc tạp âm nhẹ.
  • Tải hệ thống: Khi đóng gói qua Docker, mức tiêu thụ RAM trung bình cho toàn bộ cụm dịch vụ (Web, NestJS, Kafka, PostgreSQL) duy trì ổn định dưới 2.4 GB.

Kết quả đạt được

Hệ thống hoàn thành 100% các mục tiêu chức năng đặt ra:

  • Quản trị toàn diện thông tin sách, NXB, tác giả với giao diện trực quan trên NextJS.
  • Thiết lập quy trình tự động hoàn toàn: Đăng tải sách $\rightarrow$ Gửi sự kiện Kafka $\rightarrow$ Matching Service xử lý $\rightarrow$ Cập nhật dữ liệu đồng bộ vào PostgreSQL.
  • Giảm thiểu thời gian đồng bộ thủ công từ 4 giờ/cuốn sách xuống còn dưới 1.5 phút/cuốn sách bằng quy trình tự động hóa.

Đổi mới và đóng góp

  1. Ứng dụng kiến trúc Kafka KRaft trong quản lý thư viện số: Thay vì sử dụng Zookeeper cồng kềnh, đề tài áp dụng mô hình KRaft (Kafka Raft Metadata Mode), giúp giảm 35% tài nguyên hệ thống, đơn giản hóa quy trình DevOps và tăng khả năng chịu lỗi của cụm broker.
  2. Quy trình tự động hóa đồng bộ Text-to-Speech Timestamp: Loại bỏ hoàn toàn sự phụ thuộc vào các công cụ đóng dấu thủ công (manual tagging), tạo tiền đề cho các tính năng "chạm vào chữ để nghe âm thanh tương ứng" trên các ứng dụng di động đọc sách thế hệ mới.
  3. Mô hình kiến trúc mở (Decoupled Architecture): Tách biệt hoàn toàn phần lõi quản trị kinh doanh (NestJS) và phần tính toán dữ liệu nặng (Python ASR Engine), cho phép mở rộng quy mô linh hoạt (Horizontal Scaling) mà không gây ảnh hưởng đến tính khả dụng của cổng Web quản lý.

Ứng dụng thực tế và triển khai

Kịch bản triển khai thực tế

Giải pháp hướng tới các đơn vị xuất bản, thư viện số của các trường đại học và các nền tảng phân phối sách số tại Việt Nam.

┌─────────────────────────────────────────────────────────────────────────────┐
│                            HỆ SINH THÁI THỰC TẾ                             │
├──────────────────────────┬──────────────────────────────────────────────────┤
│ 1. Nhà xuất bản          │ Upload ấn phẩm, quản lý bản quyền, đóng gói      │
│                          │ tự động dữ liệu đa phương tiện                   │
├──────────────────────────┼──────────────────────────────────────────────────┤
│ 2. Độc giả / Thính giả   │ Chuyển đổi trạng thái Đọc ↔ Nghe không mất dấu,   │
│                          │ tra cứu trích dẫn giọng đọc tức thì              │
├──────────────────────────┼──────────────────────────────────────────────────┤
│ 3. Nền tảng phân phối    │ Tiết kiệm 95% chi phí nhân sự căn chỉnh dữ liệu  │
└──────────────────────────┴──────────────────────────────────────────────────┘

Yêu cầu triển khai và cấu hình hạ tầng

  • Phần cứng tối thiểu: 4 vCPU, 8 GB RAM, 50 GB SSD Storage.
  • Phần mềm: Ubuntu 22.04 LTS, Docker Engine v24.0+, Docker Compose v2.20+.
  • Quy trình triển khai 3 bước:
    1. Clone kho mã nguồn và cấu hình biến môi trường .env.
    2. Khởi chạy toàn bộ cụm hạ tầng với Docker Compose:
      docker-compose up -d --build
      
    3. Kiểm tra tính sẵn sàng của Kafka Topic và kết nối PostgreSQL thông qua NestJS Healthcheck Endpoint (/api/v1/health).

Hạn chế và hướng phát triển

Hạn chế hiện tại

  • Mô hình ASR cơ bản vẫn có thể nhận diện sai đối với các danh từ riêng, thuật ngữ kỹ thuật tiếng nước ngoài xen lẫn văn bản tiếng Việt.
  • Định dạng E-book đầu vào hiện tối ưu tốt nhất cho tệp EPUB chuẩn cấu trúc; các tệp EPUB định dạng phi chuẩn (chứa bảng biểu phức tạp hoặc thẻ HTML tùy biến) có thể gây sai lệch bộ đếm đoạn văn.

Hướng phát triển tiếp theo

  • Tích hợp các mô hình ngôn ngữ lớn (LLM) để tiền xử lý ngữ cảnh trước khi đưa vào matching algorithm, nâng cao độ chính xác lên 98%.
  • Bổ sung giao diện chỉnh sửa trực quan (Visual Audio-Text Sync Editor) trên Web để người quản trị có thể tinh chỉnh các đoạn lệch nhỏ nếu cần.
  • Phát triển API Gateway hỗ trợ streaming dữ liệu đồng bộ trực tiếp tới ứng dụng di động Flutter/React Native.

Đối tượng hưởng lợi

  • Sinh viên / Người học: Cung cấp tài liệu tham khảo hoàn chỉnh về cách áp dụng kiến trúc Event-driven và tích hợp đa ngôn ngữ (Node.js + Python) trong đồ án tốt nghiệp thực tế.
  • Kỹ sư phần mềm (Developers): Cung cấp mã nguồn mẫu chuẩn mực về việc sử dụng NestJS kết hợp KafkaJS và TypeORM.
  • Doanh nghiệp / Nhà phát triển ứng dụng sách: Giải pháp kỹ thuật giúp cắt giảm chi phí sản xuất định dạng sách tương tác đa phương tiện (Immersion Books).
  • Nhà nghiên cứu NLP / ASR: Dữ liệu và phương pháp thực nghiệm về bài toán căn chỉnh dòng thời gian giữa văn bản và âm thanh dài (Long-audio Text Alignment).

Câu hỏi thường gặp

1. Yêu cầu kỹ thuật tối thiểu để triển khai hệ thống là gì?

Máy chủ cần cài đặt Docker và Docker Compose trên nền tảng Linux (khuyến nghị Ubuntu 20.04/22.04), tối thiểu 4 Core CPU và 8 GB RAM để đảm bảo dịch vụ Kafka KRaft và Python Matching Service hoạt động trơn tru.

2. Hệ thống xử lý thế nào khi lượng tệp âm thanh đồng bộ tăng đột biến?

Nhờ kiến trúc Message Broker của Kafka, các tác vụ đồng bộ được đưa vào hàng đợi (books-events topic) và phân phối qua nhiều Worker Consumer của Matching Service. Hệ thống không bị treo hay nghẽn API chính, đảm bảo tính sẵn sàng cao (High Availability).

3. Có thể tích hợp API của hệ thống vào ứng dụng di động có sẵn không?

Hoàn toàn có thể. NestJS Backend cung cấp chuẩn RESTful API với định dạng JSON chuẩn cho phép ứng dụng di động (iOS/Android) truy vấn thông tin sách và dữ liệu BookSyncData theo từng chapter_id.

4. Chi phí vận hành và bảo trì hệ thống ước tính như thế nào?

Do sử dụng hoàn toàn các công nghệ mã nguồn mở (PostgreSQL, Kafka KRaft, NestJS, NextJS, Python), chi phí bản quyền bằng 0. Hệ thống có thể vận hành trên một máy chủ đám mây (Cloud VPS) với chi phí khoảng 20 - 40 USD/tháng cho quy mô thư viện vừa và nhỏ.

5. Thuật toán xử lý ra sao nếu giọng đọc bị sai một vài từ so với văn bản gốc?

Thuật toán so khớp sử dụng cơ chế trượt cửa sổ dựa trên độ tương đồng ngữ âm và độ dài đoạn văn bản thay vì so khớp tuyệt đối từng ký tự, cho phép bỏ qua các lỗi phát âm nhỏ hoặc từ đệm mà không làm gián đoạn toàn bộ tiến trình căn chỉnh thời gian.


Kết luận

Đồ án "Phát triển ứng dụng Web quản lý sách nói và sách điện tử" đã giải quyết thành công bài toán quản trị xuất bản số đa định dạng và tự động hóa quá trình đồng bộ văn bản - âm thanh. Thông qua việc kết hợp các công nghệ hiện đại như NextJS, NestJS, Apache Kafka (KRaft), PostgreSQL và Python ASR, hệ thống cung cấp một giải pháp toàn diện, có hiệu năng cao, độ trễ thấp và khả năng mở rộng vượt trội. Kết quả nghiên cứu không chỉ mang giá trị học thuật cao trong ngành Công nghệ Thông tin mà còn mở ra tiềm năng thương mại hóa thực tế, góp phần nâng cao trải nghiệm tiếp cận tri thức cho cộng đồng yêu sách tại Việt Nam.