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

У меня есть веб-приложение, созданное на NextJS. Я собираюсь использовать прозрачное видео, которое в настоящее время у меня есть как MOV и WEBP, WEBP прекрасно работает в Chrome (на рабочем столе), а MOV отлично работает на Safari (на рабочем столе). Но я сталкиваюсь с проблемами, когда дело касается Chrome (IOS), у Chrome (Android) проблем нет. Однако Chrome (IOS) не отображает альфа-каналы, а показывает небольшой фон. Как я могу это исправить? Каков наилучший подход для этого или есть ли другой тип файла, который мне следует использовать?

Я помню, как некоторое время назад, когда я пытался реализовать что-то подобное, не было универсальной поддержки альфа-канала. Лучший способ сделать это — замаскировать два видео (черно-белую маску для альфа-канала и само видео) на холсте с помощью globalCompositeOperation.

somethinghere 07.06.2024 12:22

Можете ли вы рассказать подробнее?

Umar Uzman 07.06.2024 15:22

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

somethinghere 07.06.2024 15:25
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
3
179
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Существует несколько подходов к этому.

Первый вариант — использовать другой формат видео. Вы говорите об использовании webP, но посмотрите на VP9/WebM. Посмотрите на его возможную реализацию . Сам Google также говорит о использовании и недостатках webP.

В качестве второго варианта, как уже упоминали некоторые комментаторы, можно использовать два видео. Один из них — маска, а другой — цвета. Для этого вы можете увидеть следующий пример, в котором используется холст HTML.

Важное примечание. Нажмите кнопку «Полная страница», чтобы правильно увидеть фрагмент в действии. В противном случае прокрутите вниз после нажатия p, чтобы начать воспроизведение.

Фото: Натан Сирлз

const width = 640;
const height = 450;
let videoPlaying = false;
let processControl;

// Main video
const canvas_video = document.getElementById('canvas_video');
const video_ctx = canvas_video.getContext('2d');
const video = document.getElementById('video');
video.crossOrigin = 'Anonymous';
video_ctx.canvas.width = width;
video_ctx.canvas.height = height;

// Mask
const canvas_mask = document.getElementById('canvas_mask');
const mask_ctx = canvas_mask.getContext('2d');
const mask = document.getElementById('mask');
mask.crossOrigin = 'Anonymous';
mask_ctx.canvas.width = width;
mask_ctx.canvas.height = height;

// Output canvas
const output = document.getElementById('output');
const output_ctx = output.getContext('2d');
output_ctx.canvas.width = width;
output_ctx.canvas.height = height;
output.crossOrigin = 'Anonymous';

function Process() {
  processControl = window.requestAnimationFrame(Process);

  video_ctx.drawImage(video, 0, 0, width, height);
  mask_ctx.drawImage(mask, 0, 0, width, height);

  // getImageData
  // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData
  const image = video_ctx.getImageData(0, 0, width, height);
  const imageData = image.data;

  const maskData = mask_ctx.getImageData(0, 0, width, height).data;

  for (let i = 3, len = imageData.length; i < len; i = i + 4) {
    imageData[i] = maskData[i-1];
  }

  output_ctx.putImageData(image, 0, 0, 0, 0, width, height);
}

document.body.onkeyup = function(e){
  if (e.keyCode === 80){
    if (videoPlaying) {
      mask.pause();
      video.pause();
      videoPlaying = false;
      cancelAnimationFrame(processControl);
    } else {
      mask.play();
      video.play();
      Process();
      videoPlaying = true;
    }
  }
}
/*
  Background pattern:
  https://www.svgbackgrounds.com/
*/
body {
  font-family: sans-serif;
  font-weight: 600;
  background-color: #5353;
  background-image: background-color: #ee5522;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 200 200'%3E%3Cdefs%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='100' y1='33' x2='100' y2='-3'%3E%3Cstop offset='0' stop-color='%23000' stop-opacity='0'/%3E%3Cstop offset='1' stop-color='%23000' stop-opacity='1'/%3E%3C/linearGradient%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='100' y1='135' x2='100' y2='97'%3E%3Cstop offset='0' stop-color='%23000' stop-opacity='0'/%3E%3Cstop offset='1' stop-color='%23000' stop-opacity='1'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cg fill='%23d23d09' fill-opacity='0.6'%3E%3Crect x='100' width='100' height='100'/%3E%3Crect y='100' width='100' height='100'/%3E%3C/g%3E%3Cg fill-opacity='0.5'%3E%3Cpolygon fill='url(%23a)' points='100 30 0 0 200 0'/%3E%3Cpolygon fill='url(%23b)' points='100 100 0 130 0 100 200 100 200 130'/%3E%3C/g%3E%3C/svg%3E");
  text-align: center;
}

p {
  margin: 20px 0;
  padding: 10px 20px;
  border-radius: 20px;
  background: rgba(255,255,255,0.95);
  box-shadow: 10px 10px 10px rgba(0,0,0,0.1);
  display: inline-block;
}

canvas {
  display: none;
}

#output {
  display: block;
  margin: 80px auto;
}

video {
  width: 640px;
  height: auto;
}
<div id = "stage">
  <p id = "control">Hit "p" to play/pause videos</p>

  <!-- Main element -->
  <canvas id = "output"></canvas>

  <!-- Shown for reference -->
  <canvas id = "canvas_video"></canvas>
  <canvas id = "canvas_mask"></canvas>

  <!-- Hidden with CSS -->
  <video id = "mask" src = "http://nathansearles.com/videos/knife-mask.mp4" crossorigin = "anonymous" loop></video>
  <video id = "video" src = "http://nathansearles.com/videos/knife.mp4" crossorigin = "anonymous" loop></video>
</div>

Позвольте мне попробовать это. Это кажется очень многообещающим по сравнению с решениями, которые я видел раньше.

Umar Uzman 12.06.2024 13:09

Я пробовал это, но, к сожалению, видео в этом случае получается очень плохого качества. мое оригинальное видео в HD. но это не так. Как сделать так, чтобы мое видео выглядело точно так же, как и исходное видео

Umar Uzman 13.06.2024 13:33

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

Remy Kabel 14.06.2024 00:30

Я использовал другой подход: я использовал видео Webm. Все работало совершенно нормально. Хотя в этом была изюминка. Мне пришлось закодировать mov, чтобы убедиться, что он работает в Safari и Chrome iOS. И веб-интерфейс отлично работал на Chrome Mac OS и Windows.

Umar Uzman 14.06.2024 09:10
Ответ принят как подходящий

Используйте формат WebM вместе с кодеком VP9 и альфа-каналом, чтобы включить полупрозрачное видео в настольных и мобильных веб-приложениях. Большинство современных браузеров поддерживают этот формат.

Используйте VP9 и альфа-канал для экспорта видео в формат WebM (например, в Adobe After Effects).

<video autoplay loop muted playsinline>
    <source src = "your-video-file.webm" type = "video/webm">
    <img src = "your-fallback-image.gif" alt = "Fallback image">
</video>

Используйте формат WebM вместе с кодеком VP9 и альфа-каналом, чтобы включить полупрозрачное видео в настольных и мобильных веб-приложениях. Большинство современных браузеров поддерживают этот формат.

Используйте VP9 и альфа-канал для экспорта видео в формат WebM (например, в Adobe After Effects).

Нет, это не решит мою проблему, так как я уже пробовал это, и, как я уже упоминал в своем вопросе, это работает, но не только на ios Chrome или Safari Mobile.

Umar Uzman 12.06.2024 13:10

После дальнейшего исследования я выявил проблему в этом подходе, этот подход работает нормально, но если он вызывает проблемы только в ios (chrome/safari), то это потому, что mov необходимо закодировать в HEVC с прозрачностью.

Umar Uzman 14.06.2024 09:12

Да, вы правы, это вызывает проблемы только на iOS.

Umer Farooq 14.06.2024 13:02

Другие вопросы по теме