0

Từ ảnh sang video miễn phí: hiển thị ảnh tĩnh trước, để người dùng chủ động phát

Bạn đã có một clip minh họa ngắn. Việc tiếp theo trên frontend không nhất thiết là đặt nó chạy vòng lặp ngay đầu trang. Người đọc cần hiểu nội dung trước khi quyết định xem chuyển động.

Bài này dùng ba thẻ nội dung làm ví dụ: ảnh tĩnh đã cho thấy bố cục, còn video chỉ thêm nhịp chuyển động. Mã chạy trên trang của bạn bằng HTML/JavaScript tiêu chuẩn, không phải trình phát hay API của một công cụ tạo video.

Để ảnh tự làm được việc của nó

Chọn một ảnh có ích ngay cả khi video không chạy. Viết alt mô tả nội dung và một chú thích giải thích vai trò của chuyển động. Nếu clip chứa lời nói hoặc thông tin quan trọng mà ảnh không thể thay thế, cần bổ sung nội dung tương đương phù hợp, chẳng hạn phụ đề hoặc bản chép lời.

Ở trạng thái đầu, ví dụ chỉ hiện ảnh, chú thích và nút. Khi không có JavaScript, nút vẫn ẩn và người đọc vẫn xem được phần tĩnh.

Ảnh chụp ví dụ HTML tự viết hiển thị ảnh ba thẻ nội dung, mô tả và nút Phát video trước khi có chuyển động.

Ảnh chụp ví dụ chạy cục bộ của bài viết. Hình và clip kiểm tra được dựng bằng mã; đây không phải giao diện hay video đầu ra của HeyDream.

Markup nhỏ, không tự phát

Thay poster.svg và clip.webm bằng tài nguyên bạn có quyền sử dụng. Đặt script ở cuối phần markup, hoặc tải bằng defer.

<style>
  [hidden] {
    display: none !important;
  }
  img, video {
    display: block;
    max-width: 100%;
    height: auto;
  }
</style>
<figure>
  <img id="still" src="poster.svg"
       width="960" height="540"
       alt="Ba thẻ nội dung.">
  <video id="clip"
         data-src="clip.webm"
         poster="poster.svg"
         controls playsinline
         preload="none" hidden
         aria-label="Video ba thẻ">
    Trình duyệt không hỗ trợ video.
  </video>
  <figcaption>
    Ba thẻ nội dung;
    chuyển động chỉ để minh họa.
  </figcaption>
</figure>
<button id="toggle"
        type="button" hidden>
  Phát video
</button>
<p id="status" role="status">
  Ảnh tĩnh vẫn có đủ nội dung.
</p>

controls giữ bộ điều khiển của trình duyệt; playsinline yêu cầu phát trong vùng trang khi được hỗ trợ. Không thêm thuộc tính autoplay: viết autoplay="false" vẫn là có thuộc tính Boolean ấy. Theo MDN về video, preload chỉ là gợi ý, không phải cam kết không tải dữ liệu.

Ở đây, URL media nằm trong data-src; mã chỉ gán src sau thao tác của người dùng. Ảnh và poster vẫn là các tài nguyên cần tải riêng.

Có đường lui cho cả Promise và sự kiện lỗi

play() trả về Promise và có thể bị từ chối, ví dụ do chính sách phát hoặc định dạng không được hỗ trợ. Vì vậy phải xử lý kết quả thay vì coi một lần gọi là đã phát thành công. Tài liệu play() giải thích ranh giới này.

const v =
  document.querySelector("#clip");
const still =
  document.querySelector("#still");
const button =
  document.querySelector(
    "#toggle"
  );
const status =
  document.querySelector(
    "#status"
  );

function fallback() {
  v.pause();
  v.hidden = true;
  still.hidden = false;
  button.disabled = false;
  button.textContent =
    "Thử phát lại";
  status.textContent =
    "Không phát được video. " +
    "Bạn vẫn có thể xem ảnh.";
}
v.addEventListener(
  "error", fallback
);
v.addEventListener(
  "playing", () => {
  button.textContent =
    "Tạm dừng video";
});
v.addEventListener("pause", () => {
  if (!v.hidden) {
    button.textContent =
      "Phát video";
  }
});
button.addEventListener(
  "click", async () => {
    if (!v.paused) {
      v.pause();
      return;
    }
    button.disabled = true;
    if (!v.getAttribute("src")) {
      v.src = v.dataset.src;
    }
    if (v.error) v.load();
    v.hidden = false;
    still.hidden = true;
    try {
      await v.play();
      status.textContent = "";
    } catch {
      fallback();
    } finally {
      button.disabled = false;
    }
  }
);
if (typeof v.play === "function") {
  button.hidden = false;
}

Nút HTML dùng được với bàn phím; nhãn của nó cập nhật theo sự kiện phát và dừng. Người dùng cũng có thể tạm dừng bằng controls gốc.

catch xử lý lần yêu cầu phát thất bại, còn error xử lý lỗi media được trình duyệt báo. Cả hai đưa ảnh trở lại và đặt thông báo trong role="status". Chữ bên trong thẻ video chủ yếu dành cho trình duyệt không hỗ trợ phần tử; nó không tự thay thế xử lý lỗi tải. Kết nối bị treo có thể cần chính sách thời gian chờ riêng.

Sơ đồ từ ảnh tĩnh đến thao tác người dùng, gọi play và phát video; nhánh lỗi quay về ảnh và thông báo.

Sơ đồ hành vi của ví dụ: thao tác phát và đường lui khi play() bị từ chối hoặc có sự kiện error được xử lý riêng.

Chuyển động vẫn là một lựa chọn

Cách này không tự phát cho bất kỳ ai, kể cả người bật prefers-reduced-motion. Người dùng vẫn có thể chủ động chọn xem. Đừng biến tùy chọn đó thành lý do ép phát hoặc tuyên bố cả trang đã đạt chuẩn.

W3C về pause/stop/hide nêu các điều kiện cụ thể của chuyển động tự bắt đầu. Có nút dừng không thay cho việc đánh giá toàn bộ nội dung, phụ đề, tương phản hay các yêu cầu truy cập khác.

Chỉ dùng công cụ tạo clip ở bước chuẩn bị tài nguyên

Nếu cần làm một clip từ hai ảnh gốc tương thích, có thể cân nhắc công cụ tạo video từ ảnh miễn phí HeyDream. Công khai: Tôi là người sáng lập HeyDream.

Quy trình hiện tại yêu cầu ảnh đầu, ảnh cuối, mô tả chuyển động/camera và tỷ lệ khung hình. Trang sản phẩm mô tả xem trước và tải kết quả; chưa có thử nghiệm tạo clip cho bài này. Bạn vẫn tự chuẩn bị ảnh, kiểm tra quyền sử dụng, âm thanh và định dạng media. Phần HTML/JS phía trên hoàn toàn tách khỏi bước tạo tài nguyên.

Kiểm tra cả khi không phát được

Ví dụ đã được kiểm tra cục bộ trong Chrome bằng clip tổng hợp từ Canvas/MediaRecorder, không phải đầu ra HeyDream: ảnh ban đầu, phát/dừng bằng bàn phím, Promise bị từ chối có chủ đích, nguồn media404, tắt JavaScript và thiết lập giảm chuyển động.

Ảnh chụp thực tế của ví dụ sau khi nguồn video trả HTTP404, ảnh tĩnh và thông báo Không phát được video vẫn hiện.

Kiểm tra mã ví dụ bằng nguồn media404 trong Chrome cục bộ. Đây là fixture tổng hợp, không phải kiểm thử khả năng tạo video của HeyDream hay chứng nhận mọi trình duyệt.

Trước khi dùng thật, hãy thử trên trình duyệt và thiết bị mục tiêu với chính tệp bạn định phục vụ. Kiểm tra ảnh khi chưa nhấn nút, khi pause, khi URL hỏng và khi mạng chậm. Đừng chỉ xem đường chạy thành công: nếu phần minh họa vẫn hiểu được khi video vắng mặt, bạn đã giữ được lý do để nội dung tồn tại.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí