const handleGetVideoThumb = async function (url, options = {}) {
if (typeof url !== "string") {
console.error("URL must be a string");
return;
}
// 默认参数
const defaults = {
seekTime: 1,
onLoading: () => {},
onLoaded: () => {},
onFinish: (thumbData) => {},
onError: (error) => console.error(error),
};
const params = { ...defaults, ...options };
// 基于视频元素绘制缩略图,而非解码视频
const video = document.createElement("video");
// 静音
video.muted = true;
// 绘制缩略图的 canvas 画布元素
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d", {
willReadFrequently: true,
});
// 绘制缩略图的标志量
let isTimeUpdated = false;
// 设置视频源并返回 blob URL
const setVideoSource = async (url) => {
if (/^blob:|base64,/i.test(url)) {
return url;
} else {
try {
const response = await fetch(url);
const blob = await response.blob();
params.onLoaded();
return URL.createObjectURL(blob);
} catch (error) {
params.onError(error);
}
}
};
// 获取视频尺寸并开始绘制
const onLoadedMetadata = () => {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
draw();
};
// 触发绘制监控
const onTimeUpdate = () => {
isTimeUpdated = true;
};
// 绘制方法
const draw = () => {
const thumbData = [];
video.currentTime = params.seekTime;
const onSeeked = () => {
if (isTimeUpdated) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(video, 0, 0, canvas.width, canvas.height);
canvas.toBlob((blob) => {
thumbData.push(URL.createObjectURL(blob));
params.onFinish(thumbData);
}, "image/jpeg");
video.removeEventListener("seeked", onSeeked);
}
};
video.addEventListener("seeked", onSeeked);
};
// 设置事件监听
video.addEventListener("loadedmetadata", onLoadedMetadata);
video.addEventListener("timeupdate", onTimeUpdate);
// 获取视频数据
params.onLoading();
video.src = await setVideoSource(url);
};
// 示例调用
handleGetVideoThumb(
"https://xxxxx.mp4",
{
seekTime: 7, // 截取第7s视频
onFinish: (data) => {
console.log(data); // 图片数据
},
onError: (error) => {
console.error("Error occurred:", error);
},
}
);