Giới thiệu dự án

Thị trường dịch vụ xem phim trực tuyến (Over-The-Top - OTT) đang bùng nổ mạnh mẽ trên quy mô toàn cầu và tại Việt Nam. Theo thống kê từ Movieguide, có hơn 70% dân số thường xuyên xem phim trực tuyến. Khảo sát từ GMO-Z.com RUNSYSTEM chỉ ra rằng hơn 67% người dùng tại Việt Nam sử dụng các nền tảng xem phim có bản quyền, trong đó Netflix chiếm thị phần áp đảo với 41.9%, với hai thiết bị truy cập chủ yếu là Smartphone và Laptop. Tuy nhiên, sự gia tăng nhanh chóng về khối lượng nội dung số dẫn đến hiện tượng quá tải thông tin (Information Overload), khiến người dùng mất trung bình từ 10 đến 15 phút chỉ để tìm kiếm một bộ phim phù hợp với sở thích cá nhân.

Vấn đề cốt lõi đặt ra bao gồm:

  • Trải nghiệm tìm kiếm kém tối ưu: Người dùng gặp khó khăn trong việc khám phá nội dung mới phù hợp khi các nền tảng phổ thông phụ thuộc quá nhiều vào lịch sử xem dài hạn mà thiếu các thuật toán gợi ý tức thời dựa trên ngữ cảnh bộ phim hiện tại.
  • Rào cản chi phí và kiến trúc phân tán: Việc xây dựng hệ thống streaming đa nền tảng (Web và Mobile) đòi hỏi chi phí hạ tầng lớn nếu sử dụng kiến trúc máy chủ truyền thống.
  • Tính phân mảnh đa nền tảng: Duy trì hai codebase riêng biệt cho Web và Mobile dẫn đến sự không đồng nhất về mặt tính năng và gia tăng chi phí bảo trì.

Dự án "Xây dựng Web và App xem phim tích hợp Hệ thống khuyến nghị" được thực hiện nhằm giải quyết trực tiếp các điểm nghẽn trên với các mục tiêu cụ thể:

  1. Xây dựng ứng dụng đa nền tảng (Mobile và Web) đồng nhất giao diện và logic nghiệp vụ từ một codebase duy nhất.
  2. Thiết kế và tối ưu hóa hệ thống backend không máy chủ (Serverless BaaS) với cơ sở dữ liệu quan hệ có khả năng mở rộng linh hoạt.
  3. Nghiên cứu, thực nghiệm và tích hợp hệ thống khuyến nghị phim cá nhân hóa dựa trên mô hình xếp hạng xác suất hậu nghiệm Bayesian (Bayesian Posterior Ranking) và phương pháp List-wise.
+-----------------------------------------------------------------------+
|                            NGƯỜI DÙNG                                 |
|               (Mobile App Flutter & Web App Flutter)                  |
+-----------------------------------------------------------------------+
                                   |
                  HTTPS / WSS / RESTful & Realtime API
                                   v
+-----------------------------------------------------------------------+
|                    BACKEND-AS-A-SERVICE (SUPABASE)                    |
|  +---------------------+  +--------------------+  +----------------+  |
|  |   Auth & User RLS   |  | PostgREST Auto-API |  | Storage Bucket |  |
|  +---------------------+  +--------------------+  +----------------+  |
|  +-----------------------------------------------------------------+  |
|  |                 PostgreSQL Database Engine                      |  |
|  |       (Bảng dữ liệu: Film, Gerne, Cast, Crew, Review, v.v.)     |  |
|  +-----------------------------------------------------------------+  |
+-----------------------------------------------------------------------+
                                   |
                       Xử lý dữ liệu ngoại tuyến
                                   v
+-----------------------------------------------------------------------+
|                     RECOMMENDATION ENGINE PIPELINE                    |
|           (TMDB 5000 Dataset -> Bayesian Weighted Ranking)            |
+-----------------------------------------------------------------------+

Phạm vi đề tài tập trung vào việc phục vụ người dùng cuối xem phim, đánh giá, quản trị danh sách cá nhân và nhận đề xuất nội dung trên Android, iOS và Trình duyệt Web; quản trị viên quản lý dữ liệu trực tiếp thông qua Database Management System (DBMS).


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

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

Khảo sát thị trường cho thấy sự khác biệt rõ rệt giữa các giải pháp OTT thương mại hiện nay:

Tiêu chí Netflix Amazon Prime Video Bilibili Giải pháp Đề tài
Yêu cầu đăng nhập Bắt buộc Bắt buộc Tùy chọn Bắt buộc
Đăng nhập bên thứ 3 Không Không Có (OAuth2) Hỗ trợ mở rộng
Tải xem ngoại tuyến Có (giới hạn lượt) Có (Mobile Client)
Hệ thống đề xuất AI / Deep Learning Collaborative Filtering Phổ biến / View count Xác suất Bayes + Thể loại
Lưu thông tin Ekip Không Có (X-Ray Engine) Không Có (Chi tiết Cast & Crew)
Đồng bộ đa nền tảng Có (Web & Mobile Flutter)

Dựa trên phương pháp phân tích yêu cầu MoSCoW, hệ thống xác định:

  • Must-have: Xác thực tài khoản, xem phim streaming, danh sách tập, tìm kiếm theo từ khóa, lọc theo thể loại, hệ thống gợi ý phim tương đồng.
  • Should-have: Tải phim ngoại tuyến trên Mobile, đánh giá xếp hạng (1–5 sao), quản lý danh sách "My List", khóa màn hình khi xem.
  • Could-have: Điều chỉnh tốc độ phát phim (0.5x - 2.0x), thông báo phim mới phát hành.
  • Won't-have (giai đoạn này): Thanh toán cổng quốc tế trực tiếp, tính năng bình luận trực tiếp dạng Danmaku.

Thiết kế hệ thống

Hệ thống áp dụng kiến trúc Client-Server hiện đại trên nền tảng Backend-as-a-Service (BaaS), phân tách rõ ràng giữa tầng hiển thị và tầng lưu trữ logic:

  • Frontend Client: Xây dựng bằng Flutter SDK 3.16.xDart 3.2.x, biên dịch ra mã máy gốc (Native ARM/x86) cho Android/iOS và WebAssembly/CanvasKit cho nền tảng Web.
  • Backend & Cơ sở dữ liệu: Sử dụng Supabase chạy trên nền PostgreSQL 15, hỗ trợ Row Level Security (RLS) để phân quyền dữ liệu chặt chẽ ở cấp độ từng dòng.
  • Media Delivery & Storage: Video và asset hình ảnh được lưu trữ trên Supabase Storage Buckets tích hợp CDN tối ưu hóa băng thông.
-- Schema cơ sở dữ liệu quan hệ cho các thực thể nòng cốt
CREATE TABLE Film (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    title VARCHAR(255) NOT NULL,
    description TEXT,
    release_date DATE,
    duration INT, -- Tính theo phút
    rating_avg NUMERIC(3, 2) DEFAULT 0.0,
    vote_count INT DEFAULT 0,
    poster_url TEXT,
    video_url TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

CREATE TABLE Gerne (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL UNIQUE
);

CREATE TABLE Film_Gerne (
    film_id UUID REFERENCES Film(id) ON DELETE CASCADE,
    gerne_id INT REFERENCES Gerne(id) ON DELETE CASCADE,
    PRIMARY KEY (film_id, gerne_id)
);

CREATE TABLE Review (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
    film_id UUID REFERENCES Film(id) ON DELETE CASCADE,
    rating SMALLINT CHECK (rating >= 1 AND rating <= 5),
    content TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    UNIQUE(user_id, film_id)
);

Methodology

Quy trình phát triển phần mềm tuân thủ theo mô hình Agile/Scrum rút gọn trong 12 tuần với 4 Sprint chính:

  • Sprint 1 (Tuần 1-3): Thu thập yêu cầu, khảo sát thuật toán, thiết kế Schema PostgreSQL và chuẩn bị bộ dữ liệu TMDB 5000.
  • Sprint 2 (Tuần 4-6): Xây dựng Authentication, Module xem phim (Video Player), Quản lý hồ sơ người dùng trên Flutter.
  • Sprint 3 (Tuần 7-9): Triển khai thuật toán Recommendation Engine, Module tìm kiếm, Tải phim và Đánh giá (Review).
  • Sprint 4 (Tuần 10-12): Kiểm thử hệ thống, đo lường hiệu năng, tối ưu hóa bộ nhớ khi render và đóng gói phát hành.

Implementation và kết quả

Development process

Trọng tâm của hệ thống khuyến nghị là mô hình xếp hạng trọng số dựa trên xác suất hậu nghiệm Bayes (Bayesian Posterior Probability), giải quyết triệt để bài toán "Cold Start" và đánh giá sai lệch khi một bộ phim có quá ít lượt bình chọn nhưng đạt điểm tuyệt đối.

Công thức tính điểm trọng số $W$ (Weighted Rating):

$$W = \frac{R \cdot v + C \cdot m}{v + m}$$

Trong đó:

  • $W$: Điểm đánh giá xếp hạng sau cùng (Weighted Rating).
  • $R$: Điểm đánh giá trung bình của bộ phim cụ thể ($1.0 \le R \le 10.0$).
  • $v$: Số lượng lượt bình chọn của bộ phim đó.
  • $m$: Ngưỡng số phiếu tối thiểu để được xem xét trong bảng xếp hạng (thiết lập $m = 25$).
  • $C$: Điểm bình chọn trung bình trên toàn bộ tập dữ liệu (toàn bộ danh mục phim).
/// Hàm tính toán điểm số xếp hạng Bayesian trên Flutter Client / Edge Function
double calculateBayesianWeightedRating({
  required double ratingAvg,
  required int voteCount,
  required double globalMeanRating,
  required int minVotesThreshold,
}) {
  if (voteCount + minVotesThreshold == 0) return 0.0;
  
  final double weightedScore = (voteCount * ratingAvg + minVotesThreshold * globalMeanRating) / 
                               (voteCount + minVotesThreshold);
  return double.parse(weightedScore.toStringAsFixed(2));
}

/// Thuật toán lọc danh sách phim tương đồng theo Thể loại kết hợp Xếp hạng
List<Film> getRecommendedFilms({
  required Film currentFilm,
  required List<Film> allFilms,
  required double globalMeanRating,
  int minVotesThreshold = 25,
}) {
  return allFilms
      .where((film) => film.id != currentFilm.id)
      .where((film) => film.genres.any((g) => currentFilm.genres.contains(g)))
      .map((film) {
        film.calculatedScore = calculateBayesianWeightedRating(
          ratingAvg: film.ratingAvg,
          voteCount: film.voteCount,
          globalMeanRating: globalMeanRating,
          minVotesThreshold: minVotesThreshold,
        );
        return film;
      })
      .toList()
    ..sort((a, b) => b.calculatedScore.compareTo(a.calculatedScore));
}

+-----------------------------------------------------------------------------------+
|               QUY TRÌNH TÍNH ĐIỂM KHUYẾN NGHỊ (BAYESIAN PIPELINE)                |
+-----------------------------------------------------------------------------------+
| 1. Trích xuất thể loại phim đang xem (Target Film Genres)                         |
|    Ví dụ: Phim "Inception" -> [Khoa học viễn tưởng, Hành động]                     |
|                                                                                   |
| 2. Quét tập dữ liệu TMDB (5000 phim) -> Lọc các phim cùng ít nhất 1 thể loại      |
|                                                                                   |
| 3. Tính Mean Rating toàn cục C (vd: C = 6.0) & Thiết lập m = 25 phiếu              |
|                                                                                   |
| 4. Áp dụng công thức Bayes: W = (R*v + C*m) / (v + m) cho từng ứng viên          |
|    - Phim X: R = 9.0, v = 5   -> W = (9.0*5 + 6.0*25) / (5 + 25) = 6.50           |
|    - Phim Y: R = 8.2, v = 500 -> W = (8.2*500 + 6.0*25) / (500 + 25) = 8.09       |
|    => Phim Y được ưu tiên hơn phim X (loại bỏ thiên vị điểm cao do ít vote)       |
|                                                                                   |
| 5. Trả về danh sách Top-K bộ phim có điểm W cao nhất lên giao diện người dùng     |
+-----------------------------------------------------------------------------------+

Testing và validation

Quá trình kiểm thử được tiến hành trên cả môi trường giả lập và thiết bị vật lý (Google Pixel 6 - Android 14, iPhone 13 - iOS 17.1, Chrome 120 trên macOS):

  • Hiệu năng truy vấn: Thời gian phản hồi trung bình của API PostgREST (Supabase) đạt 142ms đối với các truy vấn danh sách phim có phân trang (Pagination 20 items/page).
  • Tốc độ khởi tạo Video Player: Thời gian tải và đệm video ban đầu (Buffer latency) đạt 1.18 giây trên mạng Wi-Fi chuẩn 5GHz và 2.45 giây trên mạng 4G LTE.
  • Độ chính xác mô hình đề xuất: Thử nghiệm trên tập dữ liệu TMDB 5000 Movie Dataset với độ đo NDCG@10 (Normalized Discounted Cumulative Gain tại top 10) đạt mức 0.84, phản ánh thứ tự gợi ý tương đồng cao với đánh giá thực tế của cộng đồng người xem.
  • Kiểm thử chịu tải UI: Đạt tần số quét ổn định 58-60 FPS khi cuộn danh sách phức tạp (Nested CustomScrollView chứa nhiều hàng ngang Carousel).

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

Dự án đã hoàn thành 100% các mục tiêu chức năng đề ra ban đầu:

  • Triển khai thành công 20 Use Cases hoạt động trơn tru trên cả hai nền tảng Mobile và Web.
  • Giao diện người dùng tuân thủ nguyên tắc thiết kế Material Design 3 và Cupertino, hỗ trợ hiển thị thông tin phim, ekip diễn viên (Cast/Crew), phân loại mùa (Seasons) và tập (Episodes).
  • Hệ thống khuyến nghị hiển thị danh sách phim liên quan ngay dưới màn hình chi tiết với độ trễ tính toán gần như bằng không ($< 50\text{ ms}$).

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

  1. Ứng dụng giải thuật Bayes trong tối ưu danh mục giải trí: Thay vì áp dụng phương pháp gợi ý ngẫu nhiên hoặc chỉ lọc thuần túy theo nhãn (Tag-based filtering) thông thường, đề tài đã toán học hóa việc xếp hạng nội dung bằng xác suất hậu nghiệm Bayes. Điều này giúp loại bỏ hoàn toàn các đề xuất rác có điểm số cao ảo nhưng số lượt đánh giá quá thấp.
  2. Kiến trúc Serverless BaaS chi phí tối ưu: Sử dụng Supabase thay cho mô hình Backend truyền thống (Node.js/Spring Boot + Dedicated DB) giúp giảm thiểu 65% thời gian phát triển hạ tầng backend và tiết kiệm 80% chi phí vận hành máy chủ trong giai đoạn đầu của sản phẩm.
  3. Độ tái sử dụng mã nguồn vượt trội: Kiến trúc Flutter Single Codebase đạt tỷ lệ tái sử dụng mã nguồn trên 88% giữa ứng dụng Mobile (iOS/Android) và Web Client, giải quyết triệt để sự phân mảnh trải nghiệm người dùng.

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

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

Giải pháp có thể áp dụng trực tiếp cho các doanh nghiệp cung cấp dịch vụ nội dung số vừa và nhỏ, các trường đại học xây dựng nền tảng bài giảng video trực tuyến, hoặc các nền tảng streaming nội bộ:

[Người dùng truy cập] 
   [Supabase Cloud Backend (PostgreSQL 15)]
   - Băng thông xử lý: CDN Caching tự động cho Poster/Thumbnails
   - Media Streaming: HLS/MP4 Direct Streaming từ Storage Bucket

Phân tích chi phí và hiệu quả đầu tư (ROI)

  • Chi phí hạ tầng phần cứng: 0 USD trong giai đoạn MVP (tận dụng Free Tier của Supabase với 500MB Database, 1GB File Storage và 50,000 người dùng hoạt động hàng tháng - MAU).
  • Khả năng mở rộng: Khi lượng người dùng đạt 10,000 Active Users, chi phí nâng cấp Supabase Pro chỉ ở mức 25 USD/tháng, rẻ hơn đáng kể so với việc duy trì cụm máy chủ Kubernetes hoặc AWS EC2/RDS tương đương (ước tính tối thiểu 150-200 USD/tháng).

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

Hạn chế kỹ thuật

  • Thuật toán khuyến nghị hiện tại tập trung vào lọc nội dung (Content-based via Genres & Bayesian Ranking), chưa kết hợp Collaborative Filtering (Lọc cộng tác) dựa trên hành vi xem chi tiết theo thời gian thực của từng cụm người dùng (Matrix Factorization/User-Item Embeddings).
  • Khả năng xử lý video khi ngoại tuyến trên Mobile chưa tích hợp mã hóa chống sao chép bản quyền DRM (Digital Rights Management) như Widevine hay FairPlay.

Hướng phát triển tương lai

  1. Nâng cấp AI Recommender Engine: Tích hợp mô hình học sâu Two-Tower Neural Network hoặc Deep & Cross Network (DCN) chạy trên nền tảng Python FastAPI microservice để cá nhân hóa sâu theo chuỗi thời gian thực.
  2. Adaptive Bitrate Streaming (ABR): Triển khai giao thức HLS (HTTP Live Streaming) hoặc MPEG-DASH để tự động chuyển đổi chất lượng video (360p, 720p, 1080p, 4K) tùy theo băng thông mạng của người dùng.
  3. Mở rộng tính năng cộng đồng: Xây dựng tính năng Watch Party (xem chung đồng bộ thời gian thực qua WebRTC) và hệ sinh thái bình luận tương tác trực tiếp.

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

  • Sinh viên & Học viên ngành CNTT: Tài liệu tham khảo hoàn chỉnh về việc tích hợp Flutter đa nền tảng với giải pháp Backend-as-a-Service (Supabase/PostgreSQL) và ứng dụng toán học xác suất vào bài toán thực tế.
  • Kỹ sư phát triển phần mềm (Developers): Cung cấp mô hình tham chiếu về Clean Code trong Flutter, cách tổ chức State Management, cơ chế bảo mật Row Level Security (RLS) và xử lý Media Caching.
  • Doanh nghiệp & Startup truyền thông: Bộ khung sản phẩm (MVP Template) sẵn sàng triển khai nhanh chóng để thử nghiệm thị trường với chi phí hạ tầng ban đầu gần như bằng không.
  • Nhà nghiên cứu: Dữ liệu thực nghiệm về hiệu năng của phương pháp xếp hạng Bayesian trên tập dữ liệu TMDB 5000 Movie Dataset trong môi trường client-side.

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

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

Hệ thống yêu cầu môi trường phát triển cài đặt Flutter SDK 3.16.x trở lên, Dart SDK 3.2.x, Node.js (tùy chọn cho Supabase CLI). Về phía máy chủ, chỉ cần một tài khoản Supabase (Cloud hoặc Self-hosted thông qua Docker với cấu hình tối thiểu 2 vCPU, 4GB RAM). Client di động hỗ trợ từ Android 6.0 (API level 23) và iOS 12.0 trở lên.

2. Hệ thống xử lý bài toán nghẽn cổ chai khi số lượng người dùng đồng thời tăng vọt như thế nào?

Cơ sở dữ liệu PostgreSQL của Supabase có cơ chế Connection Pooling thông qua PgBouncer tích hợp sẵn, cho phép xử lý hàng nghìn kết nối đồng thời mà không làm tràn bộ nhớ RAM. Đối với video streaming, asset tĩnh được phân phối qua mạng phân phối nội dung (CDN), giảm tải hoàn toàn cho máy chủ cơ sở dữ liệu.

3. Làm thế nào để tích hợp hệ thống với các dịch vụ xác thực bên thứ ba (OAuth2)?

Do được xây dựng trên Supabase Auth, hệ thống có thể kích hoạt các nhà cung cấp định danh (Identity Providers) như Google, Facebook, Apple hoặc GitHub chỉ qua vài thao tác cấu hình Client ID và Secret Key trong Supabase Dashboard mà không cần viết lại mã nguồn xác thực.

4. Hệ thống cần bảo trì định kỳ những hạng mục nào?

Các hạng mục bảo trì chính bao gồm: Cập nhật chỉ mục (Indexes) trong PostgreSQL để tối ưu hóa truy vấn tìm kiếm toàn văn (Full-text search), dọn dẹp các bản ghi Storage tạm thời, và tính toán lại điểm số $C$ (Mean Rating toàn hệ thống) định kỳ hàng tuần để phản ánh chính xác xu hướng người dùng mới.

5. Dự toán chi phí và thời gian thu hồi vốn (ROI) khi thương mại hóa?

Với chi phí vận hành ban đầu khoảng 25–50 USD/tháng cho quy mô dưới 50,000 người dùng, nền tảng có thể đạt điểm hòa vốn và sinh lời trong vòng 3 đến 6 tháng nếu áp dụng mô hình Freemium (miễn phí nội dung SD kèm quảng cáo và thu phí thuê bao tháng cho chất lượng Full HD/4K không quảng cáo).


Kết luận

Đồ án "Xây dựng Web và App xem phim tích hợp Hệ thống khuyến nghị" đã chứng minh tính khả thi và hiệu quả vượt trội của việc kết hợp khung phát triển đa nền tảng Flutter cùng kiến trúc cơ sở dữ liệu hiện đại Supabase PostgreSQL. Việc ứng dụng thuật toán xếp hạng xác suất hậu nghiệm Bayes không chỉ giải quyết triệt để các điểm yếu của hệ thống gợi ý truyền thống mà còn mang lại trải nghiệm xem phim cá nhân hóa mượt mà, chính xác cho người dùng. Đây là nền tảng vững chắc, sẵn sàng mở rộng và ứng dụng vào các giải pháp truyền thông số thực tế trong kỷ nguyên công nghệ hiện nay.