【UNIAPP】获取视频的第一帧作为封面(基于视频URL,Canvas)复制即用
文章目录
- 关键代码(复制即用)
- 完整方法业务js
- yudao自带的上传js(修改版)
关键代码(复制即用)
注意,包裹这些代码的函数,需要用async修饰。 代码版本是vue3的,vue2也适用【自行修改】
// 准备好你的视频地址
const videoUrl = 【视频地址 例如http://test.com/xxx.mp4】;
// 1.创建视频元素
const video = document.createElement('video');
video.crossOrigin = 'anonymous'; // 处理跨域问题
video.muted = true;
video.playsInline = true;
// 2.创建画布元素
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
try {
// 等待视频元数据加载
await new Promise((resolve, reject) => {
video.addEventListener('loadedmetadata', resolve);
video.addEventListener('error', reject);
video.src = videoUrl;
});
// 设置视频当前帧到开始位置
video.currentTime = 0;
// 等待视频帧准备好
await new Promise((resolve, reject) => {
video.addEventListener('seeked', resolve);
video.addEventListener('error', reject);
});
// 设置画布尺寸与视频一致
anvas.width = video.videoWidth;
canvas.height = video.videoHeight;
// 绘制到画布
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
// 将画布转换为 Blob
const blob = await new Promise(resolve =>
canvas.toBlob(resolve, 'image/jpeg', 0.95)
);
// 创建文件对象
const file = new File([blob], '【文件名可以自定义】.jpg', {
type: 'image/jpeg',
lastModified: Date.now()
});
console.log('封面文件:',file)
let fm = await 【换成你的上传文件API接口】(file)
console.log('上传封面结果',fm)
data['image'] = fm.data
} catch (error) {
console.error('处理失败:', error);
}
完整方法业务js
业务场景:用户选择【图文】or【视频】进行发布文章,如果是图文的话,选择第一个图片作为封面,如果是视频的话,选择视频的第一帧作为封面
const submitDiscover = async function(){
if(title.value == ''){
uni.showToast({
title:'请输入标题',
icon:'none'
})
return
}
if(content.value == ''){
uni.showToast({
title:'请输入内容',
icon:'none'
})
return
}
if(fileList.value.length==0){
uni.showToast({
title:'请上传内容',
icon:'none'
})
return
}
// 开始提交
let data = {
title: title.value,
content: content.value,
type: submitType.value == 'tuwen' ? '1' : '2', // 1图文 2视频,
image:'',
// contextImg:[],
// video:''
}
let files = []
for(let i=0;i<fileList.value.length;i++){
let rs = (fileList.value[i].response)
if(!rs){
uni.showToast({
title:'上传失败!请检查文件大小或格式',
icon:'none'
})
return
}
let fileData = JSON.parse(rs)
files.push(fileData.data)
}
if(submitType.value == 'tuwen'){
data['contextImg'] = files
data['image'] = files[0] // 设置封面图
}else{
// 视频
data['video'] = files[0]
// 封面要获取视频的第一帧并上传
// data['image'] = files[0]
console.log('获取封面:',fileList.value[0])
const videoUrl = files[0];
// 创建视频元素
const video = document.createElement('video');
video.crossOrigin = 'anonymous'; // 处理跨域问题
video.muted = true;
video.playsInline = true;
// 创建画布元素
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
try {
// 等待视频元数据加载
await new Promise((resolve, reject) => {
video.addEventListener('loadedmetadata', resolve);
video.addEventListener('error', reject);
video.src = videoUrl;
});
// 设置视频当前帧到开始位置
video.currentTime = 0;
// 等待视频帧准备好
await new Promise((resolve, reject) => {
video.addEventListener('seeked', resolve);
video.addEventListener('error', reject);
});
// 设置画布尺寸与视频一致
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
// 绘制到画布
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
// 将画布转换为 Blob
const blob = await new Promise(resolve =>
canvas.toBlob(resolve, 'image/jpeg', 0.95)
);
// 创建文件对象
const file = new File([blob], 'file.jpg', {
type: 'image/jpeg',
lastModified: Date.now()
});
// 创建一个FileReader实例
// const reader = new FileReader();
// reader.onload = function(event) {
// // event.target.result包含了文件的Data URL(Base64编码的字符串)
// const base64String = event.target.result;
// // 你可以在这里使用base64String,例如将其显示在页面上或发送到服务器
// console.log('封面base64',base64String);
// };
// reader.readAsDataURL(file);
console.log('封面文件:',file)
let fm = await FileApi.uploadFileByFile(file) // TODO改成自己的方法
console.log('上传封面结果',fm)
data['image'] = fm.data
} catch (error) {
console.error('处理失败:', error);
}
}
console.log('submit..' ,data,files)
// 发布文章
DiscoverApi.publishDiscover(data).then(res=>{
console.log('发布结果',res)
if(res.code == 0){
uni.showToast({
title:'发布成功',
icon:'success'
})
setTimeout(()=>{
title.value = ('')
content.value = ('')
// file
fileList.value = ([])
uni.navigateBack()
},1000)
}
})
}
yudao自带的上传js(修改版)
import { baseUrl, apiPath, tenantId } from '@/sheep/config';
import request from '@/sheep/request';
const FileApi = {
// 上传文件
uploadFile: (file) => {
// TODO 芋艿:访问令牌的接入;
const token = uni.getStorageSync('token');
uni.showLoading({
title: '上传中',
});
return new Promise((resolve, reject) => {
uni.uploadFile({
url: baseUrl + apiPath + '/infra/file/upload',
filePath: file,
name: 'file',
header: {
// Accept: 'text/json',
Accept: '*/*',
'tenant-id': tenantId,
// Authorization: 'Bearer test247',
},
success: (uploadFileRes) => {
let result = JSON.parse(uploadFileRes.data);
if (result.error === 1) {
uni.showToast({
icon: 'none',
title: result.msg,
});
} else {
return resolve(result);
}
},
fail: (error) => {
console.log('上传失败:', error);
return resolve(false);
},
complete: () => {
uni.hideLoading();
},
});
});
},
uploadFileByFile: (file) => { // !!!!就是这个方法加一下
// TODO 芋艿:访问令牌的接入;
const token = uni.getStorageSync('token');
uni.showLoading({
title: '上传中',
});
return new Promise((resolve, reject) => {
uni.uploadFile({
url: baseUrl + apiPath + '/infra/file/upload',
formData: {
'file':file
},
name: 'file',
header: {
// Accept: 'text/json',
Accept: '*/*',
'tenant-id': tenantId,
// Authorization: 'Bearer test247',
},
success: (uploadFileRes) => {
let result = JSON.parse(uploadFileRes.data);
if (result.error === 1) {
uni.showToast({
icon: 'none',
title: result.msg,
});
} else {
return resolve(result);
}
},
fail: (error) => {
console.log('上传失败:', error);
return resolve(false);
},
complete: () => {
uni.hideLoading();
},
});
});
},
// 获取文件预签名地址
getFilePresignedUrl: (path) => {
return request({
url: '/infra/file/presigned-url',
method: 'GET',
params: {
path,
},
});
},
// 创建文件
createFile: (data) => {
return request({
url: '/infra/file/create', // 请求的 URL
method: 'POST', // 请求方法
data: data, // 要发送的数据
});
},
};
export default FileApi;