当前位置:   article > 正文

前端使用navigator.mediaDevices.getUserMedia和window.MediaRecorder实现调用摄像头录制视屏

navigator.mediadevices.getusermedia

前端使用navigator.mediaDevices.getUserMedia和window.MediaRecorder实现调用摄像头录制视屏

在这里插入图片描述

一、navigator.mediaDevices.getUserMedia

MediaDevices.getUserMedia()会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D转换器等等),也可能是其它轨道类型。

它返回一个 Promise 对象,成功后会resolve回调一个 MediaStream 对象。若用户拒绝了使用权限,或者需要的媒体源不可用,promisereject回调一个 PermissionDeniedError 或者 NotFoundError

navigator.mediaDevices.getUserMedia详细的使用方法以及API可以去看官方文档

二、window.MediaRecorder

MediaRecorder() 构造函数会创建一个对指定的 MediaStream 进行录制的 MediaRecorder 对象。

这里的MediaStream就是上面resolve返回的那个MediaStream。

语法:

var mediaRecorder = new MediaRecorder(stream[, options]);
  • 1

stream

MediaStream 将要录制的流. 它可以是来自于使用 navigator.mediaDevices.getUserMedia() 创建的流或者来自于,以及DOM元素.

option(可选):

一个对象,包含一下属性:

  • mimeType: 为新构建的 MediaRecorder 指定录制容器的MIME类型. 在应用中通过调用 MediaRecorder.isTypeSupported() 来检查浏览器是否支持此种mimeType .
  • audioBitsPerSecond: 指定音频的比特率.
  • videoBitsPerSecond: 指定视频的比特率.
  • bitsPerSecond: 指定音频和视频的比特率. 此属性可以用来指定上面两个属性. 如果上面两个属性只有其中之一和此属性被指定, 则此属性可以用于设定另外一个属性.

window.MediaRecorder详细使用方法可以去看官方文档

三、简单实现调用摄像头录制视屏

使用react框架实现,调用的是原生方法,其他框架的写法都差不多。

页面结构:

			<div>
                {/* 这个video标签录制时看到实时画面使用 */}
                <video src="" ref='video' className={styles.video}></video>
                <button onClick={this.clickStart.bind(this)}>开始</button>
                <button onClick={this.clickEnd.bind(this)}>停止</button>
                {
                    this.state.chunkURL ? <a href={this.state.chunkURL} download='test.webm'>点击下载</a> : ''
                }
                {/* 这个video标签是录制完后把录制之后的数据处理为二进制流后进行展示使用 */}
                <video src={this.state.chunkURL} className={styles.video} ref='newvideo'></video>
            </div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

1、在页面加载的时候需要把使用媒体输入和创建录制视屏的弄好。

下面代码是需要在页面加载的时候完成。

init() {
        navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then(
            (stream) => {
                this.recorder = new window.MediaRecorder(stream)
                this.setState({
                    stream: stream
                })
            },
            (error) => {
                alert("出错,请确保已允许浏览器获取音视频权限");
            }
        );
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2、点击开始需要干的事情

(1)把第一个video标签的srcObject属性和navigator.mediaDevices.getUserMedia成功返回的stream关联上

(2)video的muted属性是是否静音,值是布尔值,true为静音

(3)让视屏播放起来

(4)让recorder开始录制

(5)给recorder绑定上ondataavailable和onstop的回调 ondataavailable:当有又用的数据的时候触发,onstop:停止录制当然时候触发

 // 给record绑定事件的回调
    bindEvents() {
        this.recorder.ondataavailable = (e) => {
            this.setState({
                chunk: e.data
            })
        }
        this.recorder.onstop = () => {
            let blob = new Blob([this.state.chunk], { type: 'video/webm' })
            let videoStream = URL.createObjectURL(blob);
            this.setState({ chunkURL: videoStream })
            setTimeout(()=>{
                console.log(this.state.chunkURL);
            },5000)
            this.refs.newvideo.play()
        }
    }
    // 点击开始
    clickStart() {
        this.onPreview()
        this.onStart()
        this.bindEvents()
    }
    onPreview() {
        this.refs.video.srcObject = this.state.stream
        this.refs.video.muted = true
        this.refs.video.play();
    }
    onStart() {
        this.recorder.start();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

3、点击结束

点击结束按钮调用record的stop事件停止录制,同时将第一个video标签暂停,不暂停也不影响,只有一直有摄像头拍到的实时画面但是不会录制。

clickEnd() {
        this.recorder.stop()
        this.refs.video.pause()
    }
  • 1
  • 2
  • 3
  • 4

完整代码

import React from 'react'
import styles from './index.less'
class VideoDemo extends React.Component {
    constructor(prop) {
        super(prop)
        this.state = {
            recorder: null,
            stream: null,
            chunk: null,
            chunkURL: null
        }
        this.recorder = null

    }
    render() {
        return (
            <div>
                {/* 这个video标签录制时看到实时画面使用 */}
                <video src="" ref='video' className={styles.video}></video>
                <button onClick={this.clickStart.bind(this)}>开始</button>
                <button onClick={this.clickEnd.bind(this)}>停止</button>
                {
                    this.state.chunkURL ? <a href={this.state.chunkURL} download='test.webm'>点击下载</a> : ''
                }
                {/* 这个video标签是录制完后把录制之后的数据处理为二进制流后进行展示使用 */}
                <video src={this.state.chunkURL} className={styles.video} ref='newvideo'></video>
            </div>
        )
    }
    init() {
        navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then(
            (stream) => {
                this.recorder = new window.MediaRecorder(stream)
                this.setState({
                    stream: stream
                })
            },
            (error) => {
                alert("出错,请确保已允许浏览器获取音视频权限");
            }
        );
    }
    // 给record绑定事件的回调
    bindEvents() {
        this.recorder.ondataavailable = (e) => {
            this.setState({
                chunk: e.data
            })
        }
        this.recorder.onstop = () => {
            let blob = new Blob([this.state.chunk], { type: 'video/webm' })
            let videoStream = URL.createObjectURL(blob);
            this.setState({ chunkURL: videoStream })
            setTimeout(()=>{
                console.log(this.state.chunkURL);
            },5000)
            this.refs.newvideo.play()
        }
    }
    // 点击开始
    clickStart() {
        this.onPreview()
        this.onStart()
        this.bindEvents()
    }
    onPreview() {
        this.refs.video.srcObject = this.state.stream
        this.refs.video.muted = true
        this.refs.video.play();
    }
    onStart() {
        this.recorder.start();
    }
    clickEnd() {
        this.recorder.stop()
        this.refs.video.pause()
    }
    componentDidMount() {
        this.init()
    }
}
export default VideoDemo
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82

less样式代码

.video{
    width: 100vw;
    height: 50vh;
}
  • 1
  • 2
  • 3
  • 4

总结

1、如果只想录制声音或是其他什么的只需要改init方法里面getUserMedia方法里的参数。

()
}
componentDidMount() {
this.init()
}
}
export default VideoDemo


less样式代码

  • 1
  • 2
  • 3

.video{
width: 100vw;
height: 50vh;
}


## 总结

1、如果只想录制声音或是其他什么的只需要改init方法里面getUserMedia方法里的参数。

2、本来想实现a标签下载的,但是不知道为什么下载下来的视屏是黑色的没有画面。该问题还未解决,解决了再来更新。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/571480
推荐阅读
  

闽ICP备14008679号