记录h5使用navigator.mediaDevices.getUserMedia录制音视频

!!!要在https环境下才行!!!

<video class="video" id="video" ref="recordRef" muted autoplay playsinline></video>

let stream

let mediaRecorder

let startTime

let recordSize = 0

let recordedChunks = []

mounted() {

this.init();

},

beforeDestroy() {

recordedChunks = []

if (stream) {

stream.getTracks().forEach(function (track) {

track.stop()

})

}

this.$refs.recordRef.srcObject = null

},

async init(){

this.$nextTick(async () => {

stream = await navigator.mediaDevices.getUserMedia({

video: {

// width:720,

// height:1280,

facingMode: 'user',

},

// video:true,

audio: true,

})

this.$refs.recordRef.srcObject = stream

mediaRecorder = new MediaRecorder(stream)

mediaRecorder.onstart = () => {

recordedChunks = []

recordSize = 0

startTime = new Date().getTime()

}

mediaRecorder.ondataavailable = (event) => {

recordSize += event.data.size

this.time = Math.round((new Date().getTime() - startTime) / 1000)

this.size = recordSize

if (event.data.size > 0) {

recordedChunks.push(event.data)

}

}

mediaRecorder.onstop = async () => {

if (stream) {

stream.getTracks().forEach(function (track) {

track.stop()

})

}

this.$refs.recordRef.srcObject = null

//上传到阿里云oss

getOss({}).then((ress)=>{

let resp = ress.data;

const formData = new FormData()

formData.append('key', resp.filename)

formData.append('OSSAccessKeyId', resp.accessid)

formData.append('policy', resp.policy)

formData.append('signature', resp.signature)

formData.append('file', new File(recordedChunks, 'file.webm', { type: mediaRecorder.mimeType }))

const video_url = resp.host + '/' + resp.mp4

this.percent = '0%'

const uploadRequestXHR = new XMLHttpRequest()

uploadRequestXHR.open('POST', resp.host, true)

uploadRequestXHR.onerror = (rejj) => {

Toast('上传失败')

}

uploadRequestXHR.upload.onprogress = (e) => {

let per = Math.floor((e.loaded / e.total) * 100)

// 控制进度条最大显示99%,最后请求结束后才变为100%

if (per > 99) {

per = 99

}

this.percent = per + '%'

}

uploadRequestXHR.onload = (rejj2) => {

if (uploadRequestXHR.status != 204) {

Toast('上传失败')

return

}

activationServiceRecording({family_member_id: this.family_member_id,family_service_id:this.family_service_id,recording:video_url}).then((res)=>{

if(res.code!==200){

return Toast(res.error);

}

this.percent = '100%'

Toast('录制已完成');

setTimeout(()=>{

this.$router.go(-1)

},800)

})

}

uploadRequestXHR.send(formData)

})

//上传到服务器

// const blob = new Blob(recordedChunks, {

// type: 'video/webm'

// });

// const formData = new FormData();

// formData.append('file[]', blob, 'recorded-video.webm');

// upFile(formData).then(ress => {

// console.log('数据:',ress)

// activationServiceRecording({family_member_id: this.family_member_id,family_service_id:this.family_service_id,recording:ress.data[0].path}).then((res)=>{

// console.log('数据:',res)

// if(res.code!==200){

// return Toast(res.error);

// }

// this.percent = '100%'

// Toast('录制已完成');

// setTimeout(()=>{

// this.$router.go(-1)

// },800)

// })

// })

// .catch((rej) => {

// console.log('上传错误:',rej)

// })

}

})

},

changeState(){

if (this.state == 'ready') {

this.state = 'recording'

// 开始录制

mediaRecorder.start(1000)

} else if (this.state == 'recording') {

this.state = 'uploading'

// 结束录制

mediaRecorder.stop()

}

},

附:

formatBytes(time){

return formatBytes(time)

},

formatSeconds(size){

return formatSeconds(size)

},

utils:

//录制的视频size

export function formatBytes(bytes, decimals = 2) {

if (bytes === 0) return '0 Bytes'

const k = 1024

const dm = decimals < 0 ? 0 : decimals

const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']

const i = Math.floor(Math.log(bytes) / Math.log(k))

return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + '' + sizes[i]

}

//录制时间

export function formatSeconds(seconds) {

const hours = Math.floor(seconds / 3600)

const minutes = Math.floor((seconds % 3600) / 60)

const secs = seconds % 60

const hoursStr = hours.toString().padStart(2, '0')

const minutesStr = minutes.toString().padStart(2, '0')

const secsStr = secs.toString().padStart(2, '0')

return `{hoursStr}:{minutesStr}:${secsStr}`

}

相关推荐
晚霞的不甘7 小时前
CANN 支持多模态大模型:Qwen-VL 与 LLaVA 的端侧部署实战
人工智能·神经网络·架构·开源·音视频
华玥作者13 小时前
[特殊字符] VitePress 对接 Algolia AI 问答(DocSearch + AI Search)完整实战(下)
前端·人工智能·ai
Mr Xu_14 小时前
告别冗长 switch-case:Vue 项目中基于映射表的优雅路由数据匹配方案
前端·javascript·vue.js
前端摸鱼匠14 小时前
Vue 3 的toRefs保持响应性:讲解toRefs在解构响应式对象时的作用
前端·javascript·vue.js·前端框架·ecmascript
sleeppingfrog14 小时前
zebra通过zpl语言实现中文打印(二)
javascript
lang2015092814 小时前
JSR-340 :高性能Web开发新标准
java·前端·servlet
好家伙VCC15 小时前
### WebRTC技术:实时通信的革新与实现####webRTC(Web Real-TimeComm
java·前端·python·webrtc
未来之窗软件服务15 小时前
未来之窗昭和仙君(六十五)Vue与跨地区多部门开发—东方仙盟练气
前端·javascript·vue.js·仙盟创梦ide·东方仙盟·昭和仙君
baidu_2474386115 小时前
Android ViewModel定时任务
android·开发语言·javascript
拾荒的小海螺15 小时前
开源项目:LTX2 高效可控的开源视频生成模型
开源·音视频