在移动端IOS上获取video视频的第一帧为黑屏 ;代码如下:
/**
* 获取视频的第一帧 来当做封面
* @param url 是该文件的base64格式 返回值也是base64格式 可以直接使用
*/
export function getVideoBase64(url) {
return new Promise(function (resolve, reject) {
let dataURL = ''; // 最终得到的第一帧图片
let width = '90'; // 截取图片的宽度 单位是px
let height = '90'; // 截取图片的高度 单位是px
let listen = 'loadeddata'; // 监听的是loadeddata事件
let video = document.createElement('video');
let canvas = document.createElement('canvas');
video.setAttribute('crossOrigin', 'anonymous'); //处理跨域
video.setAttribute('src', url);
video.setAttribute('width', width);
video.setAttribute('height', height);
video.currentTime = 1; // 第一帧
video.preload = 'auto'; //metadata:抓取原数据
//判断是否是IOS设备 监听 durationchange或progress 在ios也会出现黑屏
if (/iPad|iPhone|iPod/.test(navigator.userAgent)) {
video.load(); // 重新加载视频 解决在ios设备中 不会默认加载视频或音频资源的问题
video.autoplay = true; // 设置自动播放
video.muted = true; // 静音
listen = 'loadeddata'; // 当前帧的数据已加载 时触发
}
video.addEventListener(listen, () => {
console.log('监听到了listen:', listen);
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(video, 0, 0, width, height); //绘制canvas
dataURL = canvas.toDataURL('image/jpeg'); //转换为base64
resolve(dataURL);
});
});
}
首先需要了解 iOS 系统在处理视频的时候有一些特殊的要求,通常情况下,获取视频第一帧的方法是在 loadeddata 或 durationchange 事件触发后,将 video 元素的画面绘制到 canvas 中,然后通过 canvas.toDataURL() 方法将画布内容转换成 base64 格式的图片数据。
但是,在 iOS 环境下,当视频播放器尝试第一次自动播放或者被调用播放方法时,系统会对视频进行一个静音、暂停和不会自动播放的限制,以避免用户隐私泄漏,所以在 iOS 系统中获取视频第一帧通常是黑屏的情况。
为了解决这个问题,我们可以使用以下方法来获取视频第一帧:
判断是否是 iOS 系统。如果是则设置 video 元素的 autoplay 属性为 true,muted 属性为 true,并在 loadeddata 事件触发前加载资源。
监听 loadeddata 事件或 progress 事件。
将 video 元素的画面绘制到 canvas 中,然后通过 canvas.toDataURL() 方法将画布内容转换成 base64 格式的图片数据。
以下是示例代码:
/**
* 获取视频第一帧的方法,并将画面转换成 base64 格式
* @param {String} url 视频的 URL,可以是 base64 格式
* @return {Promise} 一个 Promise 对象,返回值为视频第一帧的 base64 数据
*/
export function getVideoBase64(url) {
return new Promise((resolve, reject) => {
// 创建 video 元素
const video = document.createElement('video');
// 设置跨域属性
video.crossOrigin = 'anonymous';
// 设置视频 URL
video.src = url;
// 设置视频画面宽度
video.width = '90';
// 设置视频画面高度
video.height = '90';
// 设置视频播放位置为第一帧
video.currentTime = 1;
//设置预加载方式为自动加载
video.preload = 'auto';
// 创建 canvas 元素
const canvas = document.createElement('canvas');
// 将 canvas 的宽度和高度设置为视频画面的宽度和高度
canvas.width = video.width;
canvas.height = video.height;
// 监听事件类型,默认为 loadeddata
let listen = 'loadeddata';
// 判断是否为 iOS 系统
if (/iPad|iPhone|iPod/.test(navigator.userAgent)) {
// 在 iOS 系统中,需要手动触发视频加载,然后设置自动播放和静音属性
video.load();
video.autoplay = true;
video.muted = true;
// 在 iOS 系统中,监听 canplaythrough 事件可以保证视频数据已经全部加载完毕
listen = 'canplaythrough';
}
// 监听 video 元素的事件
video.addEventListener(listen, () => {
// 将视频画面绘制到 canvas 中
canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
// 将 canvas 转换成 base64 格式的图片数据,并通过 Promise 返回结果
const dataURL = canvas.toDataURL('image/jpeg');
resolve(dataURL);
});
});
}
黑屏的原因有可能是因为该视频的第一帧本身就是一个黑色图片