Spec-Zone.ru › Web APIs

Обработка видео с помощью холста

Комбинируя возможности элемента video с холстом canvas, вы можете в реальном времени обрабатывать данные видео, чтобы добавить различные визуальные эффекты к отображаемому видео. Этот учебник демонстрирует, как выполнить хрома-кейинг (также известный как эффект «зеленый экран») с помощью кода JavaScript.

Содержание документа

HTML-документ, используемый для отображения этого контента, показан ниже.

<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>Video test page</title>
    <style>
      body {
        background: black;
        color: #cccccc;
      }
      #c2 {
        background-image: url(media/foo.png);
        background-repeat: no-repeat;
      }
      div {
        float: left;
        border: 1px solid #444444;
        padding: 10px;
        margin: 10px;
        background: #3b3b3b;
      }
    </style>
  </head>

  <body>
    <div>
      <video
        id="video"
        src="media/video.mp4"
        controls
        crossorigin="anonymous" />
    </div>
    <div>
      <canvas id="c1" width="160" height="96"></canvas>
      <canvas id="c2" width="160" height="96"></canvas>
    </div>
    <script src="processor.js"></script>
  </body>
</html>

Основные моменты, которые следует запомнить:

  1. В этом документе создаются два элемента canvas с идентификаторами c1 и c2. Холст c1 используется для отображения текущей кадра исходного видео, а c2 используется для отображения видео после применения эффекта хрома-кейинга; c2 предварительно загружен неподвижным изображением, которое будет использоваться для замены зеленого фона в видео.
  2. Код JavaScript импортируется из скрипта под названием processor.js.

Код JavaScript

Код JavaScript в processor.js состоит из трех методов.

Инициализация игрока хрома-ключа

Метод doLoad() вызывается при первоначальной загрузке HTML-документа. Задача этого метода — подготовить переменные, необходимые для обработки кода хрома-кейинга, и настроить обработчик событий, чтобы мы могли обнаружить, когда пользователь начинает воспроизведение видео.

const processor = {};

processor.doLoad = function doLoad() {
  const video = document.getElementById("video");
  this.video = video;

  this.c1 = document.getElementById("c1");
  this.ctx1 = this.c1.getContext("2d");

  this.c2 = document.getElementById("c2");
  this.ctx2 = this.c2.getContext("2d");

  video.addEventListener(
    "play",
    () => {
      this.width = video.videoWidth / 2;
      this.height = video.videoHeight / 2;
      this.timerCallback();
    },
    false,
  );
};

Этот код получает ссылки на элементы в HTML-документе, которые представляют особый интерес, а именно элемент video и два элемента canvas. Он также получает ссылки на контексты графики для каждого из двух холстов. Они будут использоваться, когда мы фактически будем выполнять эффект хрома-кейинга.

Затем вызывается addEventListener(), чтобы начать отслеживание элемента video, чтобы получать уведомления, когда пользователь нажимает кнопку воспроизведения на видео. В ответ на начало воспроизведения пользователем этот код получает ширину и высоту видео, делит каждую пополам (мы будем уменьшать размер видео при выполнении эффекта хрома-кейинга), затем вызывает метод timerCallback(), чтобы начать отслеживание видео и вычисление визуального эффекта.

Обратный вызов таймера

Обратный вызов таймера вызывается первоначально при запуске видео (когда происходит событие «воспроизведение»), а затем берет на себя ответственность за вызов периодически, чтобы запускать эффект ключения для каждого кадра.

processor.timerCallback = function timerCallback() {
  if (this.video.paused || this.video.ended) {
    return;
  }
  this.computeFrame();
  setTimeout(() => {
    this.timerCallback();
  }, 0);
};

Первое, что делает обратный вызов, — это проверяет, воспроизводится ли видео; если нет, обратный вызов возвращается немедленно, ничего не делая.

Затем он вызывает метод computeFrame(), который выполняет эффект хрома-кейинга на текущем кадре видео.

Последнее, что делает обратный вызов, — это вызов setTimeout() для повторного планирования вызова как можно скорее. В реальном мире вы, вероятно, запланируете это на основе знаний о частоте кадров видео.

Обработка данных кадра видео

Метод computeFrame(), показанный ниже, отвечает за фактическое извлечение кадра данных и выполнение эффекта хрома-кейинга.

processor.computeFrame = function () {
  this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
  const frame = this.ctx1.getImageData(0, 0, this.width, this.height);
  const data = frame.data;

  for (let i = 0; i < data.length; i += 4) {
    const red = data[i + 0];
    const green = data[i + 1];
    const blue = data[i + 2];
    if (green > 100 && red > 100 && blue < 43) {
      data[i + 3] = 0;
    }
  }
  this.ctx2.putImageData(frame, 0, 0);
};

Когда эта процедура вызывается, элемент видео отображает последний кадр данных видео, который выглядит так:

A single frame of the video element. There is a person wearing a black t-shirt. The background-color is yellow.

Этот кадр видео копируется в контекст графики ctx1 первого холста, указав в качестве высоты и ширины значения, которые мы ранее сохранили, чтобы отобразить кадр в уменьшенном размере. Обратите внимание, что вы можете передать элемент видео в метод drawImage() контекста, чтобы нарисовать текущий кадр видео в контексте. Результат:

A single frame of the video element. There is a person wearing a black t-shirt. The background-color is yellow. This is a smaller version of the picture above.

Вызов метода getImageData() на первом контексте извлекает копию исходных данных графики для текущего кадра видео. Это предоставляет сырые данные изображения в формате 32 бита, которые мы можем затем обрабатывать. Затем мы вычисляем количество пикселей в изображении, разделив общий размер данных изображения кадра на четыре.

Цикл for сканирует пиксели кадра, извлекая значения красного, зеленого и синего для каждого пикселя и сравнивая их с предопределенными числами, используемыми для обнаружения зеленого экрана, который будет заменен неподвижным фоновым изображением, импортированным из foo.png.

Каждый пиксель в данных изображения кадра, который определяется как часть зеленого экрана, имеет значение альфа заменено нулем, что указывает на то, что пиксель полностью прозрачен. В результате конечное изображение имеет всю область зеленого экрана на 100% прозрачным, так что при отрисовке в целевом контексте с помощью ctx2.putImageData результатом является наложение на статический фон.

Полученное изображение выглядит так:

A single frame of the video element shows the same person wearing a black t-shirt as in the photos above. The background is different: it is the Firefox logo.

Это повторяется по мере воспроизведения видео, так что каждый кадр обрабатывается и отображается с эффектом хрома-кейинга.

Просмотреть полный исходный код этого примера.

См. также

  • Веб-технологии для работы со средствами массовой информации
  • Руководство по типам и форматам медиа в веб-среде
  • Учебный раздел: HTML-видео и аудио

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Manipulating_video_using_canvas

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API