摘要:这是因为仅仅意味着将一个媒体元素的属性关联到一个对象上去。若用户拒绝了使用权限,或者需要的媒体源不可用,会回调一个或者。
音视频的录制音视频的分为服务端录制和客户端录制,下面主要讲的是利用webrtc进行客户端录制的方式。
因为WebRTC 录制音视频流之后,最终是通过 Blob 对象将数据保存成多媒体文件的,
Blob
对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream
来用于数据操作。
Blob 表示的不一定是JavaScript原生格式的数据。File
接口基于Blob
,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
要从其他非blob对象和数据构造一个 Blob
,请使用 Blob()
构造函数。要创建一个 blob 数据的子集 blob,请使用 slice()
方法。要获取用户文件系统上的文件对应的 Blob
对象。
接受 Blob
对象的API也被列在 File
文档中。
了解完Blob的特性之后呢, 我们进入正题。
let mediaRecorder;let recordedBlobs;const recordedVideo = document.querySelector("video#recorded");const recordButton = document.querySelector("button#record");const playButton = document.querySelector("button#play");const downloadButton = document.querySelector("button#download");
URL.createObjectURL()
静态方法会创建一个 DOMString
,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document
绑定。这个新的URL 对象表示指定的 File
对象或 Blob
对象。
URL.revokeObjectURL()
静态方法用来释放一个之前已经存在的、通过调用 URL.createObjectURL()
创建的 URL 对象。当你结束使用某个 URL 对象之后,应该通过调用这个方法来让浏览器知道不用在内存中继续保留对这个文件的引用了。你可以在 sourceopen
被处理之后的任何时候调用 revokeObjectURL()
。这是因为 createObjectURL()
仅仅意味着将一个媒体元素的 src
属性关联到一个 MediaSource
对象上去。调用revokeObjectURL()
使这个潜在的对象回到原来的地方,允许平台在合适的时机进行垃圾收集。
recordButton.addEventListener("click", () => { if (recordButton.textContent === "Start Recording") { startRecording(); } else { stopRecording(); recordButton.textContent = "Start Recording"; playButton.disabled = false; downloadButton.disabled = false; }});playButton.addEventListener("click", () => { const superBuffer = new Blob(recordedBlobs); recordedVideo.src = null; recordedVideo.srcObject = null; recordedVideo.src = window.URL.createObjectURL(superBuffer); recordedVideo.controls = true; recordedVideo.play();});downloadButton.addEventListener("click", () => { const blob = new Blob(recordedBlobs, { type: "video/webm" }); const url = window.URL.createObjectURL(blob); const a = document.createElement("a"); a.style.display = "none"; a.href = url; a.download = "test.webm"; document.body.appendChild(a); a.click(); setTimeout(() => { document.body.removeChild(a); window.URL.revokeObjectURL(url); }, 100);});document.querySelector("button#start").addEventListener("click", async () => { const constraints = { audio: {}, video: { width: 1280, height: 720 } }; console.log("Using media constraints:", constraints); await init(constraints);});
MediaDevices.getUserMedia()
会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream
,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D转换器等等),也可能是其它轨道类型。
它返回一个 Promise
对象,成功后会resolve
回调一个 MediaStream
对象。若用户拒绝了使用权限,或者需要的媒体源不可用,promise
会reject
回调一个 PermissionDeniedError
或者 NotFoundError
。
async function init(constraints) { try { const stream = await navigator.mediaDevices.getUserMedia(constraints); handleSuccess(stream); } catch (e) { console.error("navigator.getUserMedia error:", e); }}function handleSuccess(stream) { recordButton.disabled = false; console.log("getUserMedia() got stream:", stream); window.stream = stream; const gumVideo = document.querySelector("video#gum"); gumVideo.srcObject = stream;}
function startRecording() { recordedBlobs = []; try { mediaRecorder = new MediaRecorder(window.stream); } catch (e) { console.error("Exception while creating MediaRecorder:", e); return; } recordButton.textContent = "Stop Recording"; playButton.disabled = true; downloadButton.disabled = true; mediaRecorder.onstop = (event) => { console.log("Recorder stopped: ", event); console.log("Recorded Blobs: ", recordedBlobs); }; mediaRecorder.ondataavailable = handleDataAvailable; mediaRecorder.start();}function handleDataAvailable(event) { if (event.data && event.data.size > 0) { recordedBlobs.push(event.data); }}
DOCTYPE html><html><head> <meta charset="utf-8"> <meta id="theme-color" name="theme-color" content="#ffffff"> <link rel="stylesheet" href="./index.css">head><body> <div id="container"> <video id="gum" playsinline autoplay muted>video> <video id="recorded" playsinline loop>video> <div> <button id="start">Start camerabutton> <button id="record" disabled>Start Recordingbutton> <button id="play" disabled>Playbutton> <button id="download" disabled>Downloadbutton> div> div> <script src="./main.js" async>script>body>html>
button { background-color: #d84a38; border: none; border-radius: 2px; color: white; font-family: "Roboto", sans-serif; font-size: 0.8em; margin: 0 0 1em 0; padding: 0.5em 0.7em 0.6em 0.7em;}button:active { background-color: #cf402f;}button:hover { background-color: #cf402f;}button[disabled] { color: #ccc;}button[disabled]:hover { background-color: #d84a38;}div#container { margin: 0 auto 0 auto; max-width: 60em; padding: 1em 1.5em 1.3em 1.5em;}video { background: #222; margin: 0 0 20px 0; --width: 100%; width: var(--width); height: calc(var(--width) * 0.75);}
webRTC功能是非常强大的,关于webrtc和直播还有很多技术需要我们去研究,上续呢是DEMO的示例代码,感兴趣的小伙伴可以亲自试一试。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/119786.html
摘要:流媒体服务器端用来接受视频录制端提供的视频源,同时提供给视频播放端流服务。支持该协议即,是由苹果提出基于的流媒体传输协议。更多配置可以参考下面是的配置文件腾讯云直播后台主要是调用腾讯云。 本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/5811d... 作者:李智文 概要 分享内容: 互联网内容载体变迁历程,文字——...
摘要:为了使连接起作用,对等方必须获取元数据的本地媒体条件例如,分辨率和编解码器功能,并收集应用程序主机的可能网络地址,用于来回传递这些关键信息的信令机制并未内置到中。所有特定于多媒体的元数据都使用协议传递。 这是专门探索 JavaScript 及其所构建的组件的系列文章的第 18 篇。 想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你! 如果你错过了前面的章节,可以在这里...
摘要:我的文章不同于其他作者,鲜少有手把手入门性质文章这方面我的师哥雷博士已有许多著作在前,多是以某一个技术点为主题,展开进行较为深入的介绍。 恍惚间发现自己的博客文章已...
摘要:因此,对音视频人才的需求也从小众变成了大众,这更多的是大家对未来市场的预期导致的结果。做个勤奋向上的人,加紧学习,抓住中心,宁精勿杂,宁专勿多。 前言 如今音视频的...
摘要:本质上允许网页程序创建点对点通信,我们将会在随后的章节中进行介绍。信令涉及网络检索和穿透,会话创建及管理,通信安全,媒体功能元数据和调制及错误处理。这样就会完全建立及激活节点间的网络套接字会话。 原文请查阅这里,略有删减,本文采用知识共享署名 4.0 国际许可协议共享,BY Troland。 这是 JavaScript 工作原理第十八章。 概述 何为 WebRTC ?首先,字面上已经...
阅读 3187·2021-10-08 10:04
阅读 1223·2021-09-22 10:02
阅读 1717·2021-09-10 10:50
阅读 1346·2021-09-08 09:35
阅读 3707·2021-08-12 13:29
阅读 2365·2019-08-30 15:55
阅读 2118·2019-08-30 15:53
阅读 2162·2019-08-29 17:13