Чтобы устранить эту проблему, я попытался удалить метод play() и добавить к видео атрибуты autoplay, playsinline и mute. тег, но, похоже, это не работает на iOS. Видео просто не воспроизводится и не извлекает кадры.
Мой вопрос: существуют ли какие-либо известные проблемы совместимости с тегом и мобильными устройствами, которые могут быть причиной этого? проблема? Существуют ли альтернативные подходы или библиотеки, которые позволили бы мне извлекать кадры из загруженных видео более надежным способом, учитывая мои требования полностью запускать эту функциональность в браузере?
Вот простая реализация который работает на моем ноутбуке:
Код: Выделить всё
Play Video
Select Frame
let frames = [];
// Create a video element, and play the video but do not display it.
async function getVideoElement() {
const video = document.getElementById("video");
const item = document.getElementById("file").files[0];
const reader = new FileReader();
reader.readAsArrayBuffer(item);
reader.onload = function (event) {
const blob = new Blob([event.target.result]);
video.src = URL.createObjectURL(blob);
video.hidden = true;
video.addEventListener("loadedmetadata", function () {
// Adjust the playback rate so all frames can be captured
video.playbackRate = 0.1; //playbackRate; // Set the playback rate
});
video.play();
};
return video;
}
// Frames are graded sequentially from the video, and displayed into a canvas.
// The frames will be resized in dispalyImage and shown in the specified "output"
// canvas. Frames are saved to an array for use later with the select dropdown.
async function playVideo() {
playing = true;
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const select = document.querySelector("select");
const video = await getVideoElement();
video.addEventListener("canplay", () => {
const drawingLoop = async () => {
const index = frames.length;
select.appendChild(new Option("Frame #" + (index + 1), index));
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
const imageBlob = await new Promise((resolve) =>
canvas.toBlob(resolve, "image/png")
);
const arrayBuffer = await new Response(imageBlob).arrayBuffer();
await displayImage(arrayBuffer);
frames.push(arrayBuffer);
if (!video.ended && playing) {
video.requestVideoFrameCallback(drawingLoop);
}
};
video.requestVideoFrameCallback(drawingLoop);
});
}
// Display a frame from the video into the output canvas.
// The incoming data is an ArrayBuffer.
async function displayImage(data) {
return new Promise((resolve) => {
const image = new Image();
image.onload = async function () {
const canvas = document.getElementById("output");
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
const scaleFactor = Math.min(
canvas.width / image.width,
canvas.height / image.height
);
const scaledWidth = image.width * scaleFactor;
const scaledHeight = image.height * scaleFactor;
ctx.drawImage(image, 0, 0, scaledWidth, scaledHeight);
const resizedImageData = canvas.toDataURL();
resolve(resizedImageData);
};
image.src = URL.createObjectURL(new Blob([data]));
});
}
// Choose a frame to display after video is processed.
async function selectFrame() {
const select = document.getElementById("frameSelect");
const selectedFrameIndex = parseInt(select.value);
if (selectedFrameIndex >= 0 && selectedFrameIndex < frames.length) {
const selectedFrameData = frames[selectedFrameIndex];
console.log(selectedFrameData);
await displayImage(selectedFrameData);
}
}
Подробнее здесь: https://stackoverflow.com/questions/784 ... e-to-video
Мобильная версия