当前位置: 首页 > news >正文

【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;

相关文章:

  • JAVA面试_进阶部分_Ibatis与Hibernate的区别
  • ORB-SLAM2源码学习:总结篇(二)三大线程
  • Redis四种模式在Spring Boot框架下的配置
  • 深度解析:如何在 Vue 3 中安全访问子组件实例
  • 《Python基础教程》附录B笔记:Python参考手册
  • 掌握 ArcGIS Pro:古地图制作技巧与方法
  • 2025华为昇腾CANN训练营 2.0 之旅
  • windows下玩转vllm:vllm简介;Windows下不能直接装vllm;会报错ModuleNotFoundError: No module named ‘vllm._C‘
  • Windows server网络安全
  • Next+React项目启动慢刷新慢的解决方法
  • Android 加解密算法工具类封装:AES、RSA、MD5 一站式解决方案
  • 鸿蒙系统中的持续部署
  • labview实现大小端交换移位
  • 虚拟机 CentOS 9 网络配置
  • 【Spring 事务】
  • Grafana集成Quickwit插件
  • 从零到EXE-探索用Python开发贪吃蛇单机小游戏全过程及避坑指南
  • 从0到1,带你开启PHP语言学习之旅
  • 电机控制常见面试问题(二)
  • 数据安全_笔记系列12:数据访问控制中的三个管理员权限划分
  • 专门做海报的网站/百度网站首页网址
  • 白云鄂博矿区网站建设/专业关键词排名软件
  • wordpress自动分享插件下载地址/安卓手机性能优化软件
  • 深圳城乡和建设局网站首页/站长统计幸福宝下载
  • 杭州市下城区建设厅网站/手机怎么创建自己的网站平台
  • 网站算信息化建设/企业网站搜索优化网络推广