uni-app App和H5平台上传视频截取视频第一帧生成图片
Posted 啟大大
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uni-app App和H5平台上传视频截取视频第一帧生成图片相关的知识,希望对你有一定的参考价值。
uni-app App和H5平台使用renderjs上传视频截取视频第一帧生成图片
提示:因为uni-app中renderjs仅支持App和H5平台,所以该方案仅支持当前这两个平台。 this.request为本人封装的接口请求方法,可以替换成个人的接口请求方法,如有需要可在下方留言
文章目录
前言
因为uni-app App端没有dom概念,不支持dom操作,并且uni-app的canvas不支持绘制video。renderjs完美解决了uni-app App端的基础dom操作。实现效果在最下方!!
一、renderjs简介
renderjs是一个运行在视图层的js。它比[WXS](https://uniapp.dcloud.io/tutorial/miniprogram-subject.html#wxs)更加强大。它只支持app-vue和h5。
renderjs的主要作用有2个:
- 大幅降低逻辑层和视图层的通讯损耗,提供高性能视图交互能力
- 在视图层操作dom,运行for web的js库
二、创建index.vue文件,下方代码均在index.vue中
1.HTML代码
代码如下(示例):
<template>
<view class="content">
// 逻辑层调用视图层方法,采用监听data中变量改变的方法
<view id="canvas" class="canvas" :prop="newVal" :change:prop="canvas.create"></view>
<button @click="choose">chooseVideo</button>
</view>
</template>
2.逻辑层代码
代码如下(示例):
<!-- 逻辑层script -->
<script>
export default
data()
return
newVal: null
;
,
methods:
choose()
// 选取视频文件,拿到本地地址
uni.chooseVideo(
sourceType: ['camera', 'album'],
success: (blod)=>
// 获取视频信息,拿到宽高信息
uni.getVideoInfo(
src: blod.tempFilePath,
success: (info) =>
// 上传视频到网络地址,当然也可以使用本地地址。App、H5平台本人都测试过,都没问题!!!
uni.uploadFile(
url: 'http://替换成自己个上传文件接口/api/common/upload', //仅为示例,非真实的接口地址
filePath: blod.tempFilePath,
name: 'file',
formData:
'token': uni.getStorageSync('userInfo').token
,
success: src =>
// fullurl也可以使用本地地址,上传选择文件获取到的 => blod.tempFilePath
this.newVal = fullurl: JSON.parse(src.data).data.fullurl, width: info.width, height: info.height
// 这里当时想做个平台区分,但是后面发现H5平台这种调用方式,视图层create接受参数的时候,只能接收到newValue,但是不能接收到event, ownerInstance,所以还是统一使用上方操作
// 下方方法仅展示,调用还是统一使用上方操作
// // #ifdef APP-PLUS
// this.newVal = fullurl: JSON.parse(src.data).data.fullurl, width: info.width, height: info.height
// // #endif
// // #ifdef H5
// this.create(fullurl: JSON.parse(src.data).data.fullurl, width: info.width, height: info.height)
// // #endif
,
complete: all =>
console.log(JSON.parse(all.data))
)
)
)
,
// 逻辑层拿到base64字符串,上传网络图片
getBase64(options)
this.request(
url: 'common/base64', //仅为示例,非真实的接口地址
data:
base64: options.base64
).then(res=>
// 拿到上传base64图片的网络图片
console.log(res)
)
,
</script>
3.视图层代码
代码如下(示例):
<!-- 视图层script module对应HTML代码中view的id-->
<script module="canvas" lang="renderjs">
export default
methods:
// 视图层创建base64图片
create(newValue, oldValue, ownerInstance)
// 第一次进入为空不操作
if(newValue == null)
return
// 在缓存中创建video标签
var video = document.createElement("VIDEO")
// 通过setAttribute给video dom元素添加自动播放的属性,因为视频播放才能获取封面图
// 设置video自动播放属性
video.autoplay = true
// 该设置方法无效
// video.setAttribute('autoplay', true)
// 再添加一个静音的属性,否则自动播放会有声音
// 该设置方法无效
// video.setAttribute('muted', true)
video.muted = true
// 如果报错Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
// 可以把下面两行代码加上,因为我用的线上video url,所以可能抛出了异常。大概意思就是跨域了toDataURL()使用了外域资源
video.setAttribute('crossOrigin', 'anonymous')
video.crossOrigin = '*'
// 上面我们只是创建了video标签,视频播放需要内部的source的标签,scr为播放源
video.innerHTML = '<source src=' + newValue.fullurl + ' type="audio/mp4">'
// 再创建canvas画布标签
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// video注册canplay自动播放事件
// 防止video不播放,所以手动加个播放操作
video.play()
// video播放事件
video.addEventListener('canplay', ()=>
// 创建画布的宽高属性节点,就是图片的大小,单位PX
var anw = document.createAttribute("width");
anw.nodeValue = newValue.width;
var anh = document.createAttribute("height");
anh.nodeValue = newValue.height;
canvas.setAttributeNode(anw);
canvas.setAttributeNode(anh);
// 画布渲染
ctx.drawImage(video, 0, 0, newValue.width, newValue.height);
// 生成base64图片,指定type为jpeg格式生成的图片base64编码会小很多
var base64 = canvas.toDataURL('image/jpeg') // 这就是封面图片的base64编码
// 传递数据给逻辑层
ownerInstance.callMethod('getBase64',
base64: base64
)
// 删除创建的video 、canvas dom,要不然重新选取视频生成图片不生效
// ps:开始有这个问题,但是后面不知道为什么又没有了,如果发现生成第一次base64之后再选择不生效,可以尝试一下把下方注释打开
// document.body.removeChild(video)
// document.body.removeChild(canvas)
)
</script>
提示:本文由本人原创,转载请注明出处!!! 如果本文对你有帮助,请点个赞吧!
实现效果
1.base64图片效果
2.线上图片效果
uni-app技术分享| uni-app转小程序_实时音视频
微信小程序 实现实时音视频与 uniapp 转码成微信小程序 实现实时音视频两者是一样的,区别仅仅是一个是原生小程序一个是 uniapp 转码成小程序
本文使用uniapp转码成小程序实现音视频通话
前提
- 确保微信开发平台 =》开发 =》开发管理 =》接口设置 的 实时播放音视频流与实时录制音视频流开启
- 线上版本配置 anyRTC 相关的服务器域名(本地调试可设置不校验域名)
如图所示:小程序原生本地设置不校验域名
- uniapp 转小程序可以在小程序编辑器中配置也可在 uniapp 的 manifest.json 中配置
代码逻辑
1. 引入anyRTC 小程序版的实时音视频 SDK
2. 初始化 SDK
3. 加入相同的频道并将自己的视频流发布出去
4. 根据相关事件回调处理相关逻辑
必须填写 appid (在 anyRTC 控制台的项目管理中获取)
用户 uid 类型必须为字符串并且不重复
只有加入同一频道房间(类型必须为字符串)才可进行通话
代码实现
1. npm 引入 ar-rtc-miniapp
```js
npm i ar-rtc-miniapp
```
2. 封装 rtc.js
```javascript
// 引入 RTC
import ArRTC from "ar-rtc-miniapp";
console.log("ArRTC 版本", ArRTC);
// 定义
let Store =
appId: '',
// 本地用户uid
userId: "",
// 频道房间
channelId: "",
// RTC 客户端
rtcClient: null,
// 本地录制地址(小程序特有推流)
livePusherUrl: "",
// 远端播放(小程序特有拉流)
livePlayerUrl: "",
;
// 初始化 RTC
const InItRTC = async (info) =>
Store = Object.assign(Store, info)
// 创建RTC客户端
Store.rtcClient = new ArRTC.client();
// 初始化
await Store.rtcClient.init(Store.appId);
// 已添加远端音视频流
Store.rtcClient.on('stream-added', rtcEvent.userPublished);
// 已删除远端音视频流
Store.rtcClient.on('stream-removed', rtcEvent.userUnpublished);
// 通知应用程序发生错误
Store.rtcClient.on('error', rtcEvent.error);
// 更新 Url 地址
Store.rtcClient.on('update-url', rtcEvent.updateUrl);
// 远端视频已旋转
Store.rtcClient.on('video-rotation', rtcEvent.videoRotation);
// 远端用户已停止发送音频流
Store.rtcClient.on('mute-audio', rtcEvent.muteAudio);
// 远端用户已停止发送视频流
Store.rtcClient.on('mute-video', rtcEvent.muteVideo);
// 远端用户已恢复发送音频流
Store.rtcClient.on('unmute-audio', rtcEvent.unmuteAudio);
// 远端用户已恢复发送视频流
Store.rtcClient.on('unmute-video', rtcEvent.unmuteAudio);
return
// RTC 监听事件处理
const rtcEvent =
// RTC SDK 监听用户发布
userPublished: (uid) =>
console.log("RTC SDK 监听用户发布", uid);
if (Store.Mode == 0)
uni.showLoading(
title: '远端加载中',
mask: true,
)
// 订阅远端用户发布音视频
Store.rtcClient.subscribe(uid, (url) =>
console.log("远端用户发布音视频", url);
// 向视频页面发送远端拉流地址
uni.$emit("livePusherUrlEvent",
livePlayerUrl: url
);
, (err) =>
console.log("订阅远端用户发布音视频失败", err);
)
,
// RTC SDK 监听用户取消发布
userUnpublished: (uid ) =>
console.log("RTC SDK 监听用户取消发布", uid);
,
// 更新 Url 地址
updateUrl: (
uid,
url
) =>
console.log("包含远端用户的 ID 和更新后的拉流地址", uid, url);
// 向视频页面发送远端拉流地址
uni.$emit("livePusherUrlEvent",
livePlayerUrl: url
);
,
// 视频的旋转信息以及远端用户的 ID
videoRotation: (
uid,
rotation
) =>
console.log("视频的旋转信息以及远端用户的 ID", uid, rotation);
,
// 远端用户已停止发送音频流
muteAudio: (
uid
) =>
console.log("远端用户已停止发送音频流", uid);
,
// 远端用户已停止发送视频流
muteVideo: (
uid
) =>
console.log("远端用户已停止发送视频流", uid);
,
// 远端用户已恢复发送音频流
unmuteAudio: (
uid
) =>
console.log("远端用户已恢复发送音频流", uid);
,
// 远端用户已恢复发送视频流
unmuteAudio: (
uid
) =>
console.log("远端用户已恢复发送视频流", uid);
,
// 通知应用程序发生错误。 该回调中会包含详细的错误码和错误信息
error: (
code,
reason
) =>
console.log("错误码:" + code, "错误信息:" + reason);
,
// RTC 内部逻辑
const rtcInternal =
// 加入频道
joinChannel: () =>
console.log("加入频道", Store.rtcClient);
return Store.rtcClient.join(undefined, Store.channelId, Store.userId, () =>
// uni.showModal(
// title: '加入频道'
// )
console.log("加入频道成功", Store.rtcClient);
// 发布视频
rtcInternal.publishTrack();
, (err) =>
console.log("加入频道失败");
);
,
// 离开频道
leaveChannel: (sendfase = true) =>
console.log("RTC 离开频道", Store);
,
// 发布本地音视频
publishTrack: () =>
Store.rtcClient.publish((url) =>
console.log("发布本地音视频", url);
// 本地录制地址(小程序特有推流)
Store.livePusherUrl = url;
// 向视频页面发送本地推流地址
uni.$emit("livePusherUrlEvent",
livePusherUrl: url
);
, (
code,
reason
) =>
console.log("发布本地音视频失败", code, reason);
)
,
module.exports =
InItRTC,
rtcInternal,
```
3. 页面调用
- 页面
<!-- 本地录制 -->
<live-pusher v-if="livePusherUrl" :url="livePusherUrl" mode="RTC" autopush @statechange="statechange" @error="error" style="height: 100%;width: 100%;" />
<!-- 远端播放 -->
<live-player v-if="livePlayerUrl" :src="livePlayerUrl" mode="RTC" autoplay @statechange="statechange" style="height: 100%;width: 100%;position: absolute;z-index: -100;" />
- 页面逻辑
import RTC from "../rtc.js";
export default
data()
return
// 可用宽度
windowWidth: "",
// 本地录制地址(小程序特有推流)
livePusherUrl: "",
// 远端播放(小程序特有拉流)
livePlayerUrl: "",
,
async onLoad()
// 初始化 RTC
await ArRTC.InItRTC(
appId: "------------anyRTC 控制台项目管理中获取"
userId: "----------------自定义",
channelId: "----------自定义"
);
// 加入频道
await ArRTC.rtcInternal.joinChannel();
const _this = this;
// // 推拉流变更
uni.$on("livePusherUrlEvent", (data) =>
if (data.livePusherUrl)
_this.livePusherUrl = data.livePusherUrl
if (data.livePlayerUrl)
_this.livePlayerUrl = data.livePlayerUrl
);
// 获取页面宽度
try
const res = uni.getSystemInfoSync();
this.windowWidth = res.windowWidth;
catch (e)
// error
,
onUnload()
// uni.$off()
,
methods:
// 组件状态
statechange(e)
console.log('组件状态:', e)
,
// 组件错误
error(e)
console.log("组件错误", e);
以上是关于uni-app App和H5平台上传视频截取视频第一帧生成图片的主要内容,如果未能解决你的问题,请参考以下文章