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

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

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

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

二、window.MediaRecorder

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

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

语法:

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

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、在页面加载的时候需要把使用媒体输入和创建录制视屏的弄好。

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

init() {
        navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then(
            (stream) => {
                this.recorder = new window.MediaRecorder(stream)
                this.setState({
                    stream: stream
                })
            },
            (error) => {
                alert("出错,请确保已允许浏览器获取音视频权限");
            }
        );
    }

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();
    }

3、点击结束

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

clickEnd() {
        this.recorder.stop()
        this.refs.video.pause()
    }

完整代码

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

less样式代码

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

总结

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

()
 }
 componentDidMount() {
 this.init()
 }
 }
 export default VideoDemoless样式代码.video{
 width: 100vw;
 height: 50vh;
 }
## 总结

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

2、本来想实现a标签下载的,但是不知道为什么下载下来的视屏是黑色的没有画面。该问题还未解决,解决了再来更新。