广告位联系
返回顶部
分享到

WebRTC记录音视频流(web技术分享)

css 来源:互联网 作者:秩名 发布时间:2022-02-24 13:43:16 人浏览
摘要

一、监听开始事件 EventTarget.addEventListener()方法将指定的监听器注册到EventTarget上,当该对象触发指定的事件时,指定的回调函数就会被执行。 事件目标可以是一个文档上的元素Element,

一、监听开始事件

  • EventTarget.addEventListener() 方法将指定的监听器注册到 EventTarget 上,当该对象触发指定的事件时,指定的回调函数就会被执行。 事件目标可以是一个文档上的元素 Element,Document和Window或者任何其他支持事件的对象 (比如 XMLHttpRequest)。
  • addEventListener()的工作原理是将实现EventListener的函数或对象添加到调用它的EventTarget上的指定事件类型的事件侦听器列表中。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

document.querySelector('button#start').addEventListener('click', async () => {

 

    document.querySelector('button#start').disabled = true;

 

    const constraints = {

 

        audio: {},

 

        video: {

 

            width: 1280, height: 720

 

        }

 

    };

 

    await init(constraints);

 

});

二、获取音视频轨道

  • MediaDevices.getUserMedia() 会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D转换器等等),也可能是其它轨道类型。
  • 它返回一个 Promise 对象,成功后会resolve回调一个 MediaStream 对象。若用户拒绝了使用权限,或者需要的媒体源不可用,promise会reject回调一个 PermissionDeniedError 或者 NotFoundError 。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

async function init(constraints) {

 

    try {

 

        const stream = await navigator.mediaDevices.getUserMedia(constraints);

 

        handleSuccess(stream);

 

    } catch (e) {

 

        console.error('navigator.getUserMedia error:', e);

 

    }

 

}

  • HTMLMediaElement 接口的 srcObject 属性设定或返回一个对象,这个对象提供了一个与HTMLMediaElement关联的媒体源,这个对象通常是 MediaStream ,但根据规范可以是 MediaSource, Blob 或者 File。

1

2

3

4

5

6

7

8

9

10

11

function handleSuccess(stream) {

 

    recordButton.disabled = false;

 

    window.stream = stream;

 

    const gumVideo = document.querySelector('video#gum');

 

    gumVideo.srcObject = stream;

 

}

三、录制媒体流

  • MediaRecorder() 构造函数会创建一个对指定的 MediaStream 进行录制的 MediaRecorder 对象
  • MediaRecorder.ondataavailable 事件处理程序API处理dataavailable事件,在响应运行代码Blob数据被提供使用。
  • dataavailable当MediaRecorder将媒体数据传递到您的应用程序以供使用时,将触发该事件。数据在包含数据的Blob对象中提供。

这在四种情况下发生:

  • 媒体流结束时,所有尚未传递到ondataavailable处理程序的媒体数据都将在单个Blob中传递。
  • 当调用MediaRecorder.stop() (en-US)时,自记录开始或dataavailable事件最后一次发生以来已捕 获的所有媒体数据都将传递到Blob中;此后,捕获结束。
  • 调用MediaRecorder.requestData() (en-US) dataavailable时,将传递自记录开始或事件最后一次发生以来捕获的所有媒体数据;然后Blob创建一个新文件,并将媒体捕获继续到该blob中。
  • 如果将timeslice属性传递到开始媒体捕获的MediaRecorder.start() (en-US)方法中,dataavailable则每timeslice毫秒触发一次事件。这意味着每个Blob都有特定的持续时间(最后一个Blob除外,后者可能更短,因为它将是自上次事件以来剩下的所有东西)。

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

let mediaRecorder;

 

const recordButton = document.querySelector('button#record');

 

 

 

recordButton.addEventListener('click', () => {

 

    if (recordButton.textContent === '开始记录') {

 

        startRecording();

 

    } else {

 

        stopRecording();

 

        recordButton.textContent = '开始记录';

 

        playButton.disabled = false;

 

    }

 

});

 

 

 

function startRecording() {

 

    recordedBlobs = [];

 

    try {

 

        mediaRecorder = new MediaRecorder(window.stream);

 

    } catch (e) {

 

        console.error('创建MediaRecorder时异常:', e);

 

    }

 

    recordButton.textContent = '停止记录';

 

    playButton.disabled = true;

 

    mediaRecorder.ondataavailable = handleDataAvailable;

 

    mediaRecorder.start();

 

}

 

 

 

function stopRecording() {

 

    mediaRecorder.stop();

 

}

 

 

 

function handleDataAvailable(event) {

 

    if (event.data && event.data.size > 0) {

 

        recordedBlobs.push(event.data);

 

    }

 

}

四、播放媒体流

  • URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

let recordedBlobs;

 

const recordedVideo = document.querySelector('video#recorded');

 

const playButton = document.querySelector('button#play');

 

 

 

playButton.addEventListener('click', () => {

 

    const superBuffer = new Blob(recordedBlobs, { type: 'video/webm' });

 

    recordedVideo.src = null;

 

    recordedVideo.srcObject = null;

 

    recordedVideo.src = window.URL.createObjectURL(superBuffer);

 

    recordedVideo.controls = true;

 

    recordedVideo.play();

 

});

HTML:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

<link rel="stylesheet" href="./index.css">

 

 

 

<video id="gum" autoplay></video>

 

<video id="recorded"></video>

 

<div>

 

    <button id="start">开始</button>

 

    <button id="record" disabled>开始记录</button>

 

    <button id="play" disabled>Play</button>

 

</div>

 

 

 

<script src="./index.js"></script>

CSS:

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

button {

 

    margin: 0 3px 10px 0;

 

    padding-left: 2px;

 

    padding-right: 2px;

 

    width: 99px;

 

}

 

   

 

button:last-of-type {

 

    margin: 0;

 

}

 

   

 

video {

 

    vertical-align: top;

 

    --width: 25vw;

 

    width: var(--width);

 

    height: calc(var(--width) * 0.5625);

 

}

 

   

 

video:last-of-type {

 

    margin: 0 0 20px 0;

 

}

 

   

 

video#gumVideo {

 

    margin: 0 20px 20px 0;

 

}

JavaScript:

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

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

let mediaRecorder;

 

let recordedBlobs;

 

 

 

const recordedVideo = document.querySelector('video#recorded');

 

const recordButton = document.querySelector('button#record');

 

recordButton.addEventListener('click', () => {

 

    if (recordButton.textContent === '开始记录') {

 

        startRecording();

 

    } else {

 

        stopRecording();

 

        recordButton.textContent = '开始记录';

 

        playButton.disabled = false;

 

    }

 

});

 

 

 

const playButton = document.querySelector('button#play');

 

playButton.addEventListener('click', () => {

 

    const superBuffer = new Blob(recordedBlobs, { type: 'video/webm' });

 

    recordedVideo.src = null;

 

    recordedVideo.srcObject = null;

 

    recordedVideo.src = window.URL.createObjectURL(superBuffer);

 

    recordedVideo.controls = true;

 

    recordedVideo.play();

 

});

 

 

 

function handleDataAvailable(event) {

 

    if (event.data && event.data.size > 0) {

 

        recordedBlobs.push(event.data);

 

    }

 

}

 

 

 

function startRecording() {

 

    recordedBlobs = [];

 

    try {

 

        mediaRecorder = new MediaRecorder(window.stream);

 

    } catch (e) {

 

        console.error('创建MediaRecorder时异常:', e);

 

    }

 

    recordButton.textContent = '停止记录';

 

    playButton.disabled = true;

 

    mediaRecorder.ondataavailable = handleDataAvailable;

 

    mediaRecorder.start();

 

}

 

 

 

function stopRecording() {

 

    mediaRecorder.stop();

 

}

 

 

 

function handleSuccess(stream) {

 

    recordButton.disabled = false;

 

    window.stream = stream;

 

    const gumVideo = document.querySelector('video#gum');

 

    gumVideo.srcObject = stream;

 

}

 

 

 

async function init(constraints) {

 

    try {

 

        const stream = await navigator.mediaDevices.getUserMedia(constraints);

 

        handleSuccess(stream);

 

    } catch (e) {

 

        console.error('navigator.getUserMedia error:', e);

 

    }

 

}

 

 

 

document.querySelector('button#start').addEventListener('click', async () => {

 

    document.querySelector('button#start').disabled = true;

 

    const constraints = {

 

        audio: {},

 

        video: {

 

            width: 1280, height: 720

 

        }

 

    };

 

    await init(constraints);

 

});


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://www.jb51.net/css/812518.html
相关文章
  • CSS3浏览器兼容的介绍

    CSS3浏览器兼容的介绍
    一、浏览器兼容 1.1、概要 世界上没有任何一个浏览器是一样的,同样的代码在不一样的浏览器上运行就存在兼容性问题。不同浏览器其内核
  • CSS元素定位之通过元素的标签或者元素的id、cl

    CSS元素定位之通过元素的标签或者元素的id、cl
    大部分人在使用selenium定位元素时,用的是xpath元素定位方式,因为xpath元素定位方式基本能解决定位的需求。xpath元素定位方式更直观,更好
  • 微信小程序纯CSS实现无限弹幕滚动效果

    微信小程序纯CSS实现无限弹幕滚动效果
    啥也不说,先上效果图 实现背景 产品:我们需要一个弹幕滚动效果,类似于微博热搜那种实时评论,但是我们的数据是固定的20条,你让他
  • 使用CSS构建强大且酷炫的粒子动画效果

    使用CSS构建强大且酷炫的粒子动画效果
    粒子动画,顾名思义,就是页面上存在大量的粒子构建而成的动画。传统的粒子动画主要由 Canvas、WebGL 实现。 当然,不使用 HTML + CSS 的主要
  • flex:1的详细介绍

    flex:1的详细介绍
    简单的来说一下在别人问你这个问题的时候怎么来回答它 前端新人,如有错误求大佬指出~求教???? 情景复现 大佬提问:你知道flex: 1;的更深
  • 新的CSS伪类函数 :is 和 :where()示例介绍

    新的CSS伪类函数 :is 和 :where()示例介绍
    在编写 CSS 时,有时可能会使用很长的选择器列表来定位具有相同样式规则的多个元素。例如,如果您想对标题中的 b 标签进行颜色调整,我
  • 纯CSS打字动画的实现方法

    纯CSS打字动画的实现方法
    在一些技术网站中,经常会看到这样一种展示效果:逐个显示一段文本中的字符,模拟出一种打字的效果。通过这种方式可以显著地提升网
  • 实现el-form每行显示两列底部按钮居中效果的教程

    实现el-form每行显示两列底部按钮居中效果的教程
    el-form 每行显示两列,底部按钮居中 问题: 以前的解决办法是:el-col,el-row。但是这里只有一个el-form-item的label数据是已知的,其余项都是循
  • CSS实现六边形的图片效果的代码

    CSS实现六边形的图片效果的代码
    前言 在CodePen上看到一个有意思的效果: 这个效果的难点在于六边形的绘制, 那么接下来我们就一起来看下作者是怎么实现他的吧 实现思路
  • CSS浮动引起的高度塌陷问题的详细介绍

    CSS浮动引起的高度塌陷问题的详细介绍
    正常页面布局 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 style *{ margin:0; padding: 0; } .content{ width:400px; border:1px solid #000; } .box{ width:200px;
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计