记录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}`

}

相关推荐
San30.1 分钟前
ES6+ 新特性解析:让 JavaScript 开发更优雅高效
开发语言·javascript·es6
雨雨雨雨雨别下啦34 分钟前
【从0开始学前端】vue3简介、核心代码、生命周期
前端·vue.js·vue
simon_93491 小时前
受够了压缩和收费?我作为一个码农,手撸了一款无限容量、原图直出的瀑布流相册!
前端
e***87701 小时前
windows配置永久路由
android·前端·后端
u***27611 小时前
TypeScript 与后端开发Node.js
javascript·typescript·node.js
星空的资源小屋2 小时前
跨平台下载神器ArrowDL,一网打尽所有资源
javascript·笔记·django
Dorcas_FE2 小时前
【tips】动态el-form-item中校验的注意点
前端·javascript·vue.js
小小前端要继续努力2 小时前
前端新人怎么更快的融入工作
前端
八月ouc2 小时前
解密JavaScript模块化演进:从IIFE到ES Module,深入理解现代前端工程化基石
javascript·es6·模块化·cmd·commonjs·amd·iife
四岁爱上了她2 小时前
input输入框焦点的获取和隐藏div,一个自定义的下拉选择
前端·javascript·vue.js