在uniapp中nvue页面用不了Canvas怎办,将上传的视频通过前端获取第一帧,并将第一帧图片保存到后端<video style=height: 350rpx;width: 750rpx; :src=urls/><view @click=upload(item)> upload(item) { uni.chooseVideo({count: 1,解决案例
时间: 2024-04-02 13:37:25 浏览: 141
可以使用uni-app提供的weex渲染引擎来实现在nvue页面中使用Canvas,从而获取视频的第一帧并将其保存到后端。具体步骤如下:
1. 在uni-app项目中创建一个weex页面,用于绘制Canvas并获取视频第一帧,例如可以创建一个名为`canvas.vue`的文件。
2. 在`canvas.vue`文件中引入weex-ui组件库,并在模板中使用wxc-canvas组件创建Canvas元素:
```html
<template>
<div>
<wxc-canvas ref="canvas" v-bind="canvasStyle" @wxcCanvasDraw="handleCanvasDraw"></wxc-canvas>
</div>
</template>
<script>
import { WxCanvas } from 'weex-ui'
export default {
components: {
WxCanvas
},
props: {
videoUrl: { // 视频地址
type: String,
default: ''
}
},
data() {
return {
canvasStyle: { // Canvas样式
width: 750,
height: 350,
backgroundColor: '#000000'
},
thumbnailUrl: '' // 缩略图地址
}
},
methods: {
handleCanvasDraw(ctx, size) {
const video = uni.createVideoContext('video') // 获取视频元素
video.play()
setTimeout(() => { // 延时绘制,确保视频播放完成
ctx.drawImage(video, 0, 0, size.width, size.height) // 绘制视频帧
const thumbnailUrl = this.$refs.canvas.toDataURL('image/jpeg') // 将画布转为base64格式
this.thumbnailUrl = thumbnailUrl // 将缩略图地址保存到变量中
uni.navigateBack() // 返回上一页
}, video.duration * 1000)
}
}
}
</script>
```
这里我们通过`WxCanvas`组件创建了一个Canvas元素,并绑定了`canvasStyle`变量来设置Canvas样式。同时,我们绑定了`videoUrl`变量来获取视频地址,并在`handleCanvasDraw`函数中获取视频第一帧。在`handleCanvasDraw`函数中,我们首先通过`uni.createVideoContext`方法获取视频元素,然后调用`play`方法开始播放视频。由于绘制Canvas需要一些时间,因此我们通过`setTimeout`方法延时一段时间,确保视频播放完成后再绘制视频帧。最后,我们通过`toDataURL`方法将Canvas转为base64格式的图片,并将缩略图地址保存到`thumbnailUrl`变量中。需要注意的是,由于weex渲染引擎与webview渲染引擎有所不同,因此在使用weex渲染引擎时,需要使用`this.$refs.canvas`来获取Canvas元素。
3. 在nvue页面中,通过`uni.navigateTo`方法跳转到`canvas.vue`页面,并将视频地址作为参数传递过去:
```html
<template>
<div>
<video style="height: 350rpx;width: 750rpx;" :src="videoUrl" @loadedmetadata="handleLoadedMetadata"></video>
<view @click="handleUpload">上传视频</view>
</div>
</template>
<script>
export default {
data() {
return {
videoUrl: '', // 视频地址
thumbnailUrl: '' // 缩略图地址
}
},
methods: {
handleLoadedMetadata() {
const video = this.$refs.video // 获取视频元素
video.pause() // 暂停视频播放
uni.navigateTo({ // 跳转到weex页面,获取视频第一帧
url: '/pages/canvas/canvas',
success: (res) => {
res.eventChannel.emit('videoUrl', this.videoUrl) // 将视频地址传递到weex页面
res.eventChannel.on('thumbnailUrl', (thumbnailUrl) => { // 接收weex页面返回的缩略图地址
this.thumbnailUrl = thumbnailUrl // 将缩略图地址保存到变量中
})
}
})
},
async handleUpload() {
// 上传视频和缩略图到后端
const [videoRes, thumbnailRes] = await Promise.all([
uni.uploadFile({
url: 'your_backend_upload_api',
filePath: this.videoUrl,
name: 'video'
}),
uni.request({
url: 'your_backend_upload_api',
method: 'POST',
header: {
'Content-Type': 'application/json'
},
data: {
thumbnailUrl: this.thumbnailUrl
}
})
])
console.log(videoRes, thumbnailRes)
}
}
}
</script>
```
在这个页面中,我们使用`<video>`标签来加载视频,并绑定了`loadedmetadata`事件,用于在视频元数据加载完成后调用`handleLoadedMetadata`函数。在`handleLoadedMetadata`函数中,我们通过`this.$refs.video`获取视频元素,并调用`pause`方法暂停视频播放。接着,我们使用`uni.navigateTo`方法跳转到`canvas.vue`页面,并将视频地址作为参数传递过去。在weex页面中,我们通过`res.eventChannel.emit`方法将视频地址传递到weex页面,并在`handleCanvasDraw`函数中获取视频地址。最后,我们在weex页面中使用`res.eventChannel.emit`方法将缩略图地址返回到nvue页面中,然后将视频和缩略图上传到后端。
需要注意的是,由于视频第一帧的绘制是异步的,因此在上传缩略图时需要确保第一帧已经绘制完成。如果上传缩略图的方法与视频加载的方法不在同一个组件中,可以使用全局事件或状态管理工具来传递缩略图地址。
阅读全文