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

关山初度尘未洗,策马扬鞭再奋蹄!这篇文章主要讲述web技术分享| WebRTC记录音视频流相关的知识,希望能为你提供帮助。
监听开始事件

  • EventTarget.addEventListener() 方法将指定的监听器注册到 EventTarget 上,当该对象触发指定的事件时,指定的回调函数就会被执行。 事件目标可以是一个文档上的元素 Element,DocumentWindow或者任何其他支持事件的对象 (比如 XMLHttpRequest)
  • addEventListener()的工作原理是将实现EventListener的函数或对象添加到调用它的EventTarget上的指定事件类型的事件侦听器列表中。
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 对象。若用户拒绝了使用权限,或者需要的媒体源不可用,promisereject回调一个PermissionDeniedError 或者 NotFoundError
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 ,但根据规范可以是 MediaSourceBlob 或者 File
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除外,后者可能更短,因为它将是自上次事件以来剩下的所有东西)。
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 对象。
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 = https://www.songbingjia.com/android/null; recordedVideo.srcObject = null; recordedVideo.src = window.URL.createObjectURL(superBuffer); recordedVideo.controls = true; recordedVideo.play(); );

HTML
< link rel="stylesheet" href="https://www.songbingjia.com/android/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="https://www.songbingjia.com/android/index.js"> < /script>

CSS
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
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 = https://www.songbingjia.com/android/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); );

【web技术分享| WebRTC记录音视频流】
web技术分享| WebRTC记录音视频流

文章图片


    推荐阅读