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

}

相关推荐
天生我材必有用_吴用12 分钟前
vue3实战九、vue3+vue-cropper实现头像修改
前端
拳打南山敬老院21 分钟前
从零构建一个插件系统(四)插件的缓存
javascript·架构
Sobeit21 分钟前
ES2025 颠覆性 JS 黑科技新特性详解
前端
new_abc28 分钟前
net-snmp添加自定义mib树
服务器·前端·javascript
前端梭哈攻城狮34 分钟前
dify二开示例
前端·后端·python
该用户已不存在36 分钟前
Node.js 真的取代了PHP吗?
前端·后端·node.js
ze_juejin1 小时前
JavaScript 的事件循环(Event Loop)机制
前端
前端缘梦1 小时前
从源码到dist:拆解Webpack如何完成前端工程的"基因编译"
前端·webpack
热爱运维的小七1 小时前
中型企业如何用 RUM 技术破解地理分布式用户体验难题?从指标监测到优化实操
前端·网站响应速度·地域访问
程序猿阿伟1 小时前
《从点击到共鸣:论坛前端如何用交互细节编织用户体验》
前端·ux