uni.chooseVideo 后h5端获取图片第一帧图片

uni.chooseVideo对于h5端很不友好,无法获取视频图片,网上说的用renderjs可以使用,不过我用的是canvas绘制

比较需要注意的是你绘制的要跟你canvas设置的宽高一致不然绘制的图片会不完整

1.html得写这个canvas元素

<canvas id="videoCanvas" canvas-id="videoCanvas"></canvas>

2.设置css样式(这个只能隐藏,你也可以放出来)

#videoCanvas {
		width: 228px;
		height: 228px;
		position: fixed;
		// top: -400px;
		z-index: 9;
		visibility: hidden;
	}

3.写个按钮然后上传图片

const chooseVideo = () => {

		uni.chooseVideo({
			sourceType: ['album', 'camera'],
			maxDuration: 300,
			success: res => {
				nextTick(() => {
					// 使用定时器等待组件挂载和渲染完成
					setTimeout(() => {
						attemptCaptureVideoFrame();
					}, 800); // 根据平台情况调整延迟时间
				});
				// uploadVideo(res.tempFilePath)
			},
			fail: err => {
				console.error('选择视频失败:', err)
			}
		})
	}

4.这一步是绘制

function attemptCaptureVideoFrame() {
		const canvasId = 'videoCanvas'; // 对应 <canvas canvas-id="videoCanvas">
		const isH5 = typeof window !== 'undefined' && window.document;

		if (isH5) {
			uni.createSelectorQuery()
				.select('#videoCanvas')
				.fields({
					node: true,
					size: true
				}, canvasRes => {
					if (!canvasRes || !canvasRes.node) {
						console.error('Canvas 元素无效');
						return;
					}
					const canvasNode = canvasRes.node;
					const ctx = canvasNode.getContext('2d');

					// 创建独立 video 元素用于截图
					const videoEl = document.createElement('video');
					videoEl.src = videoUrl.value;
					videoEl.crossOrigin = 'anonymous';
					videoEl.muted = true; // 静音避免自动播放限制

					// 设置目标截图时间点(单位:秒)
					const targetTime = 2; // 修改为合适的截图时间点,比如第 3 秒

					// 监听视频加载完成
					videoEl.onloadeddata = () => {
						// 设置视频跳转到指定时间点
						videoEl.currentTime = targetTime;
					};

					// 监听 seek 完成事件,确保跳转到目标时间点
					videoEl.onseeked = () => {
						// 确保 DOM 更新后再绘制
						setTimeout(() => {
							try {
								ctx.drawImage(videoEl, 0, 0, 228, 228);
								const tempFilePath = canvasNode.toDataURL('image/png');
								thumbnail.value = tempFilePath;
								console.log(`手动绘制第 ${targetTime} 秒帧图成功:`, tempFilePath);
							} catch (err) {
								console.error('绘制失败:', err);
							}
						}, 200); // 添加短延迟确保画面已渲染
					};

					// 超时保护
					setTimeout(() => {
						if (videoEl.readyState < 2) {
							console.warn('视频加载超时,无法绘制');
						}
					}, 5000);
				})
				.exec();
		} else {
			// 小程序平台处理逻辑(可选使用 uni.canvasToTempFilePath 或服务端生成)
			const ctx = uni.createCanvasContext(canvasId);

			setTimeout(() => {
				ctx.draw(false, () => {
					uni.canvasToTempFilePath({
						canvasId: canvasId,
						success: res => {
							thumbnail.value = res.tempFilePath;
							console.log('小程序生成首帧图成功:', res.tempFilePath);
						},
						fail: err => {
							console.error('canvasToTempFilePath 失败:', err);
						}
					});
				})
			}, 800);
		}
	}

然后thumbnail.value 就是绘制的图片

效果图如下

<think>好的,我现在要解决用户关于uni.chooseVideo获取不到文件名的问题。首先,我需要了解用户的使用场景和具体问题表现。用户可能是在使用UniApp开发应用时,调用uni.chooseVideo选择视频文件后,无法正确获取到文件名。这个问题可能出现在不同的平台上,比如微信小程序、H5或者App,每个平台的机制可能不同,所以需要分情况讨论。 首先,我应该回顾uni.chooseVideo的官方文档。根据文档,uni.chooseVideo返回的对象中包含tempFilePath(临时文件路径)和duration(视频时长)、size(文件大小)、height(高度)、width(宽度)等信息。但并没有直接提到文件名这个属性。这可能意味着文件名并不是所有平台都支持的,或者需要其他方式获取。 接下来,我需要考虑各个平台的差异。例如,在微信小程序中,选择视频的API返回的tempFilePath可能是一个临时路径,文件名可能被编码或者不包含原始文件名。而在H5,浏览器环境下可能可以通过File对象的name属性获取文件名,但需要检查UniApp是否封装了这个属性。App则可能依赖于原生实现,不同原生平台的处理方式可能不同。 然后,用户可能在尝试从返回的tempFilePath中解析文件名,但发现路径中不包含原始名称,或者在不同平台上路径结构不同,导致解析失败。例如,微信小程序的临时路径可能是一串随机字符,无法直接获取原始文件名。 接下来,我需要思考解决方案。可能的解决思路包括: 1. 检查uni.chooseVideo的返回值是否有遗漏,或者是否有其他属性可以获取文件名。比如,在H5,可能返回的是一个File对象,可以通过file.name获取,但需要查看UniApp是否将此属性暴露出来。 2. 如果官方API确实不支持获取文件名,可能需要使用其他方法,比如在H5通过input元素手动选择文件,然后获取文件名,再调用uni.chooseVideo。不过这可能涉及到兼容性问题。 3. 在App,可能需要使用原生插件或模块来获取文件名,或者通过后处理,将文件上传到服务器后,从Content-Disposition头部或其他方式获取原始文件名。 4. 在微信小程序中,可能需要用户手动输入文件名,或者通过其他接口获取文件信息,但这可能不太现实。 另外,还需要考虑用户是否需要文件名用于显示还是其他业务逻辑。如果只是显示,可以考虑在用户选择视频后,让用户手动输入名称,或者从tempFilePath中提取一部分作为显示名称,尽管这可能不准确。 还需要检查是否有相关的社区讨论或Issues,看看其他开发者是否遇到同样的问题,以及他们的解决方案。例如,在DCloud论坛或GitHub仓库中可能有人提出过类似的问题,是否有官方回复或可行的Workaround。 最后,总结可能的原因和解决方案,分平台进行说明,并给出示例代码或建议步骤,帮助用户在不同场景下解决问题。同时,提醒用户注意平台差异,并建议在需要文件名的场景下,可能需要结合多种方法或后协助处理。</think>在 UniApp 中使用 `uni.chooseVideo` 获取视频文件时,若无法直接获取文件名,可能是由以下原因和解决方案导致的: --- ### 一、问题原因 1. **平台差异性** - 微信小程序:返回的临时路径 `tempFilePath` 为随机字符串,不保留原始文件名。 - H5 浏览器:可通过 `File` 对象获取文件名,但需注意 UniApp 的封装逻辑。 - App :原生平台可能未直接暴露文件名。 2. **API 限制** `uni.chooseVideo` 官方文档未明确提供 `fileName` 字段,需依赖额外处理。 --- ### 二、解决方案 #### 1. H5 浏览器H5 中,可通过 `<input type="file">` 手动监听文件选择事件,直接获取文件名: ```html <template> <input type="file" accept="video/*" @change="handleFileSelect" /> </template> <script> export default { methods: { handleFileSelect(e) { const file = e.target.files[0]; const fileName = file.name; // 直接获取文件名 uni.chooseVideo({ success(res) { res.fileName = fileName; // 合并到结果中 console.log('文件名:', fileName); } }); } } } </script> ``` #### 2. 微信小程序 微信小程序的 `tempFilePath` 为临时路径,需通过后解析文件名: ```javascript uni.chooseVideo({ sourceType: ['album', 'camera'], success: (res) => { // 上传到服务器后,从 Content-Disposition 或文件头解析文件名 uni.uploadFile({ url: 'YOUR_SERVER_API', filePath: res.tempFilePath, name: 'video', success: (uploadRes) => { const fileName = JSON.parse(uploadRes.data).fileName; console.log('服务器返回的文件名:', fileName); } }); } }); ``` #### 3. App (Android/iOS) 通过原生插件或文件路径解析: ```javascript uni.chooseVideo({ success: (res) => { // 示例:从路径中截取文件名(不保证通用性) const path = res.tempFilePath; const fileName = path.split('/').pop().split('.')[0]; console.log('临时文件名:', fileName); } }); ``` --- ### 三、注意事项 1. **兼容性处理** 使用 `#ifdef H5`、`#ifdef MP-WEIXIN` 等条件编译,区分平台逻辑。 2. **用户交互** 若必须获取文件名,可让用户手动输入后关联文件。 3. **后协作** 上传文件后,通过服务器解析文件名更可靠(如 HTTP 头的 `Content-Disposition`)。 --- ### 四、总结 - **H5**:通过 `<input type="file">` 直接获取 `File` 对象。 - **小程序**:依赖服务器解析文件名。 - **App**:尝试从路径截取或使用原生插件。 建议根据实际场景选择方案,优先考虑后解析保证准确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值