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



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Существует несколько подходов к этому.
Первый вариант — использовать другой формат видео. Вы говорите об использовании 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>Позвольте мне попробовать это. Это кажется очень многообещающим по сравнению с решениями, которые я видел раньше.
Я пробовал это, но, к сожалению, видео в этом случае получается очень плохого качества. мое оригинальное видео в HD. но это не так. Как сделать так, чтобы мое видео выглядело точно так же, как и исходное видео
Вы обязательно отрегулировали высоту и ширину кода в соответствии с разрешением вашего видео? После этого вы можете использовать масштабирование, чтобы изменить его, но давайте сначала проверим, не является ли проблема разрешением?
Я использовал другой подход: я использовал видео Webm. Все работало совершенно нормально. Хотя в этом была изюминка. Мне пришлось закодировать mov, чтобы убедиться, что он работает в Safari и Chrome iOS. И веб-интерфейс отлично работал на Chrome Mac OS и Windows.
Используйте формат 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.
После дальнейшего исследования я выявил проблему в этом подходе, этот подход работает нормально, но если он вызывает проблемы только в ios (chrome/safari), то это потому, что mov необходимо закодировать в HEVC с прозрачностью.
Да, вы правы, это вызывает проблемы только на iOS.
Я помню, как некоторое время назад, когда я пытался реализовать что-то подобное, не было универсальной поддержки альфа-канала. Лучший способ сделать это — замаскировать два видео (черно-белую маску для альфа-канала и само видео) на холсте с помощью
globalCompositeOperation.