流式传输 html5 canvas 内容的有效方法?

2024-03-31

我正在尝试流式传输 a 的内容html5 canvas实时使用websockets and nodejs.

html5画布的内容只是一个视频。

到目前为止我所做的是:

我将画布转换为blob然后得到blob URL并使用 websockets 将该 URL 发送到我的 Nodejs 服务器。

我得到的 blob URL 是这样的:

canvas.toBlob(function(blob) {
   url = window.URL.createObjectURL(blob);
});

Blob URL 是按视频帧生成的(确切地说是每秒 20 帧),它们看起来像这样:

blob:null/e3e8888e-98da-41aa-a3c0-8fe3f44frt53

然后,我通过 websockets 从服务器获取该 blob URL,以便我可以使用它将其绘制到另一个画布上以供其他用户查看。

我确实搜索了如何从 blob URL 绘制到画布上,但找不到任何接近我想要做的事情。

所以我的问题是:

  1. 这是我想要实现的目标的正确方法吗?任何 优点和缺点将不胜感激。

  2. 有没有其他更有效的方法来做到这一点或者我是对的 小路?

提前致谢。

EDIT:

我应该提到的是,我不能在这个项目中使用 WebRTC,我必须用我所拥有的一切来完成这一切。

为了让我现在所在的每个人都更容易,我尝试使用 websockets 在画布中显示上面提到的 blob URL:

websocket.onopen = function(event) {

        websocket.onmessage = function(evt) {
            var val = evt.data;
            console.log("new data "+val);
            var canvas2 = document.querySelector('.canvMotion2');
            var ctx2 = canvas2.getContext('2d');
            var img = new Image();     

            img.onload = function(){
                ctx2.drawImage(img, 0, 0)
            }
            img.src = val;
        };

        // Listen for socket closes
        websocket.onclose = function(event) {

        };

        websocket.onerror = function(evt) {

        };

};

问题是,当我在 FireFox 中运行该代码时,画布始终为空/空白,但我在控制台中看到 blob URL,这让我认为我所做的事情是错误的。

在谷歌浏览器中,我得到Not allowed to load local resource: blob: error.

第二次编辑:

这就是我现在所处的位置。

第一个选项

我尝试通过 websockets 发送整个 blob,并且成功完成。但是,由于某种奇怪的原因,我无法在客户端读回它!

当我查看 NodeJS 服务器的控制台时,我可以看到发送到服务器的每个 Blob 的类似内容:

<buffer fd67676 hdsjuhsd8 sjhjs....

第二个选项:

因此,上面的选项失败了,我想到了其他方法,即将每个画布帧转换为 base64(jpeg) 并通过 websockets 将其发送到服务器,然后将这些 base64 图像显示/绘制到客户端的画布上。

我每秒向服务器发送 24 帧。

这奏效了。但是再次显示这些 Base64 图像的客户端画布非常慢,就像每秒绘制 1 帧一样。这就是我目前遇到的问题。

第三个选项:

我还尝试使用没有画布的视频。所以,使用 WebRTC,我得到了video Stream as a 单个斑点。但我不完全确定如何使用它并将其发送到客户端以便人们可以看到它。

重要的:我正在开发的这个系统不是点对点连接。这只是我试图实现的一种单向流媒体方式。


最多natural流式传输画布内容的方式:WebRTC

OP 明确表示他们不能使用它,对于很多人来说可能都是这样,因为,

  1. 浏览器支持 https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/captureStream#Browser_compatibility仍然不是那么好。
  2. 这意味着需要运行一台 MediaServer(至少 ICE+STUN/TURN,如果您想流式传输到多个对等方,则可能需要一个网关)。

但是,如果您负担得起,那么从画布元素获取 MediaStream 所需的只是

const canvas_stream = canvas.captureStream(minimumFrameRate);

然后你只需将它添加到你的 RTCPeerConnection 中:

pc.addTrack(stream.getVideoTracks()[0], stream);

下面的示例将仅将 MediaStream 显示到<video>元素。

let x = 0;
const ctx = canvas.getContext('2d');
draw();
startStream();

function startStream() {
  // grab our MediaStream
  const stream = canvas.captureStream(30);
  // feed the <video>
  vid.srcObject = stream;
  vid.play();
}
function draw() {
  x = (x + 1) % (canvas.width + 50);
  ctx.fillStyle = 'white';
  ctx.fillRect(0,0,canvas.width,canvas.height);
  ctx.fillStyle = 'red';
  ctx.beginPath();
  ctx.arc(x - 25, 75, 25, 0, Math.PI*2);
  ctx.fill();
  requestAnimationFrame(draw);
}
video,canvas{border:1px solid}
<canvas id="canvas">75</canvas>
<video id="vid" controls></video>

流式传输实时画布绘图的最有效方法:流式传输绘图操作。

OP 再次表示他们不想要这个解决方案,因为他们的设置不匹配,但可能对许多读者有帮助:

无需发送画布的结果,只需将绘图命令发送给您的同行,然后同行将在他们这边执行这些命令。

但这种方法有其自身的注意事项:

  • 您必须编写自己的编码器/解码器来传递命令。
  • 有些情况可能很难共享(例如,外部媒体必须以相同的方式在所有对等方上共享和预加载,最糟糕的情况是绘制其他画布,您还必须共享其自己的绘制过程)。
  • 您可能希望避免在所有对等点上进行密集的图像处理(例如图像数据操作)。

所以第三种,性能肯定较差的方法,就像OP尝试做的那样:

定期上传帧。

我不会在这里详细介绍,但请记住,您正在发送独立的图像文件,因此比编码为视频的数据要多得多。

相反,我会专注于为什么OP的代码不起作用?

首先,最好稍微提醒一下什么是 Blob(在回调中提供的东西)canvas.toBlob(callback)).

Blob 是一种特殊的 JavaScript 对象,它表示二进制数据,通常存储在浏览器的内存中,或者至少存储在用户的磁盘上,可供浏览器访问。
但 JavaScript 不能直接使用此二进制数据。为了能够访问它,我们需要读取这个 Blob(通过 FileReader 或 Response 对象),或者创建 BlobURI,这是一个假 URI,允许大多数 API 指向二进制数据,就像存储在真实服务器上一样,即使二进制数据仍然仅位于浏览器分配的内存中。

但是这个 BlobURI 只是浏览器内存的一个假的、临时的、受域限制的路径,不能与任何其他跨域文档、应用程序甚至更少的计算机共享。

所有这些都表明,应该直接发送到 WebSocket 的是 Blob,而不是 BlobURI。

您只需在消费者端创建 BlobURI,以便他们可以从现在位于的 Blob 二进制数据中加载这些图像。their分配的内存。

发射极侧:

canvas.toBlob(blob=>ws.send(blob));

消费端:

ws.onmessage = function(evt) {
  const blob = evt.data;
  const url = URL.createObjectURL(blob);
  img.src = url;
};

但实际上,为了更好地回答OP的问题,最终的解决方案,这可能是这种情况下最好的,

分享在画布上绘制的视频流。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

流式传输 html5 canvas 内容的有效方法? 的相关文章

  • JavaScript 对象镜像/单向属性同步

    出于安全目的 我需要一个 镜像 对象 也就是说 如果我创建对象 A 并浅克隆 A 的副本并将其称为 B 则每当 A 的属性发生更改时 我希望 B 自动更新自身以反映更改 但反之则不然 换句话说 单向属性同步 我的问题 是否已经存在我不知道的
  • Video.js - 阻止点击播放功能

    我正在使用 video js 将视频嵌入到 HTML 页面中 它将用作仅适用于 ipad 的 Web 应用程序 因此我相信它使用的是本机 HTML5 播放器 我正在尝试禁用点击播放功能 以便用户必须使用控件 但我在这样做时遇到了麻烦 我尝试
  • 使用javascript向url添加哈希而不滚动页面?

    在不滚动页面的情况下向 url 添加哈希 使用 JavaScript 我打开页面 我向下滚动 我单击添加哈希的链接 可能带有值 test 示例 http www example com test http www example com t
  • 使用 Jquery 更改 css 属性时的事件检测

    有没有办法检测元素的 显示 css 属性是否更改 是否更改为无 块或内联块 如果没有的话有什么插件吗 谢谢 Note 突变事件 https developer mozilla org en US docs Web Guide Events
  • WaveSurfer JS 无法在 Firefox 中为特定的 mp3 音频文件生成图表

    我们面临着在 Firefox 中使用 wavesurfer JS 对某些特定格式的 mp3 文件绘制音频可视化 图表 的问题 它总是给我们这样的错误 传递给decodeAudioData 的缓冲区包含未知的内容类型 但同一个文件在 chro
  • Javascript:打乱数组中的对象组

    我有一个对象数组 我已按键排序 group如下 使得所有具有相同值的对象group在索引中彼此相邻data 例如 var data foo cat group house foo cat group house foo cat group
  • 无法让 CloudKit 进行身份验证(使用 Javascript 和服务器到服务器密钥)

    我正在尝试使用苹果的cloudkit js文件以建立与 CloudKit 的服务器到服务器连接 然而 尽管配置混乱了几个小时 我似乎无法让 CloudKit 认为我的请求有效 我的配置逻辑非常简单 const privateKeyFile
  • 在 JavaScript 中引用 C# 变量

    我已经阅读了很多线程 但我不明白为什么这不起作用 我正在创建一个将用作导航栏的 SharePoint Web 部件 一切都很顺利 直到我尝试在 JS 代码中引用 C 变量 这是来自 VisualWebPart1UserControl asc
  • 将 DIV 转换为单击并拖动视口

    有人知道一种不显眼的 基于原型或无框架的方法将具有大内容 例如地图 的 DIV 转换为具有固定尺寸的可点击和可拖动的 地图 容器 非常像 Google 地图 我想在大型输入表单中显示 HTML 块 这些块可能会超出可用空间 每个块可以有大约
  • 使用 MailTo 链接,我可以向发件人发送副本吗?

    我们开发了一个非常简单的表单 一旦提交 就会填充一封电子邮件以发送支持票证 这些电子邮件目前发送给我们的 支持人员 但如果我们也能向发件人发送一份副本 那就更理想了 我们正在使用 mailto 链接 这可能吗 例如 我们的员工 Brad 填
  • 无法安装js-bson

    我正在使用Windows 7 64位 尝试安装bson作为mongodb的依赖项 我收到此错误 npm WARN package json email protected cdn cgi l email protection No READ
  • 如何在没有 DOM 的情况下将 javascript 作为 node.js 脚本运行?

    https github com jasondavies d3 cloud https github com jasondavies d3 cloud是一个使用 D3 库的 javascript 文字云 这是一个交互式演示 http www
  • 如何保存包含框架/iframe 的完整 html 页面?

    在网页抓取期间 我想将当前页面的 html 保存到文件中以供以后调试 browser html在大多数情况下有帮助 但是当页面包含 iframe frame 时 它 的内容不会返回browser html 我必须用类似的东西单独得到它bro
  • Google 折线图添加对象数组

    我有一个通过解析 JSON 字符串创建的对象数组 var measurementData Html Raw JsonConvert SerializeObject this Model Item1 var stringifiedData J
  • 让管道自我刷新角度

    我有来自后端的静态时间戳 我想每 1 秒刷新一次管道以获取现在的日期 这是我的烟斗 import Pipe PipeTransform from angular core import moment from moment Pipe nam
  • html 下钻下拉所选值未插入 MYSQL

    我有两个下拉列表 首先从数据库下拉填充 根据第一个下拉列表的选定值从数据库填充第二个下拉列表 document ready function c change function var c1 c selected text if c1 aj
  • 将响应式网格布局转换为 Plotly Dash

    我是一个非常活跃的 Dash 用户 我开始发现 Dash 使用中存在很多限制 并且我意识到有关如何将组件转换为 Dash 的信息 内容绝对有限 并且示例过时且非常简单 并且我对 Javascript 或 React 几乎没有任何了解 我完全
  • ESLint 如何集成到 Create React App 中?

    当我跑步时npx create react app some name 为我创建了一个简单的 React 项目 当我随后窥视package json 似乎有一些 ESLint 存在的证据 因为有 eslintConfig extends r
  • 类型错误:无法读取未定义的属性“长度” - 使用安全帽部署时

    我在尝试在安全帽开发链上部署模拟合约时收到以下错误 我正在关注 使用 JavaScript 学习区块链 Solidity 和全栈 Web3 开发 Patrick Collins 在 FreeCodeCamp YT 频道上的 32 小时课程
  • CSS 未使用 req.params 或其他内容加载

    我对节点 表达等非常陌生 我制作了一个博客应用程序 但遇到了问题 我正在使用 mongoose node express 和 ejs 当我打电话时 router get posts function req res Post find fu

随机推荐

  • Rails 中的部分 SSL

    我正在寻找在 Rails 中做一个部分 SSL 站点 我基本上想保护 SSL 背后的用户操作 但仅此而已 有人知道有一个插件或 gem 可以让这个变得简单而高效吗 这通常是通过SSL 要求 http github com rails ssl
  • 未收到从 MFMailComposer 发送的附件

    我正在尝试在 iPad 上发送一封带有 csv 附件的电子邮件 我根据下面显示的许多示例使用 MFMailComposer 发送电子邮件时 我可以在 MFMailComposer 窗口中看到正确的文件附件 但是当我收到电子邮件时 没有附加任
  • 创建C# Winform开发生产环境

    我想知道为我的 C winforms 项目正确创建开发和生产环境的最佳方法是什么 不幸的是没有开发环境 相反 每次我希望创建生产或开发版本时 我都必须指定发布路径 此外 由于每个产品或开发版本都使用不同的连接字符串 因此我也必须进入代码并更
  • 错误NG6002:出现在AppModule的NgModule.imports中,但本身有错误

    我在本地和建筑项目中有 Angular 12 它运行良好 没有任何错误 我的本地设置 Angular CLI 12 0 5 Node 12 16 3 Package Manager npm 6 14 4 OS win32 x64 Angul
  • 我可以从存储过程返回 varchar(max) 吗?

    带有 SQL Server 2005 后端的 VB net Web 系统 我有一个返回 varchar 的存储过程 但我们最终得到的值不适合 varchar 8000 我已将返回参数更改为 varchar max 但如何告诉 OleDbPa
  • SQL Server 找出表何时被重命名?

    是否可以查出表何时被重命名 作为首要问题 如果可能的话 是哪个用户干的 你可以试试这个 SELECT Name modify date FROM sys all objects WHERE Name Table name
  • 传递不带等号的查询字符串参数(值为空)是否有效?

    变化1 file jsp parameter1 parameter2 abc 变化2 file jsp parameter1 parameter2 abc 我知道变体 1 被认为是有效的 但是变体 2 被认为是有效的吗 具体来说 参数没有值
  • 使用 zope.schema 定义循环引用

    我正在尝试执行以下操作 定义两个类 其实例相互引用 例如以下示例中的用户和组 一个用户可以属于多个组 一个组可以包含多个用户 实际数据存储在数据库中 这是使用外键的多对多关系的简单问题 完全没问题 然后 数据通过 ORM 加载并存储在 py
  • Google Cloud Builder - Gradle

    继以下帖子后https cloudplatform googleblog com 2017 03 Google Cloud Container Builder a fast and flexible way to package your
  • 是否可以在 Vercel 中部署 NodeJs 应用程序?

    我正在尝试在 Vercel https vercel com https vercel com 之前的 Now 来自 CLI 但是 当我部署应用程序时 我打开站点 结果只是路径目录中的文件 而不是正在运行的应用程序 这是我的server j
  • 最简单的通过鼠标旋转相机不起作用

    好吧 这让我发疯 文档非常薄弱 Oracle 的示例应用程序非常奇怪 有一个巨大而复杂的帮助程序类 甚至这里的有关它的问题也没有答案 我基本上遵循并简化了本教程 https www genuinecoder com javafx 3d tu
  • .ogg 视频无法在 Firefox 中播放

    我们刚刚开始使用 html5 视频 似乎无法得到 ogg要在 Firefox 中播放文件 有什么提示吗 这是我们正在使用的来源
  • Objective C 中如何将字符串转换为数组?

    如何在 Objective C 中将字符串转换为数组 即 我有一个字符串 NSString str Hi How r u 这应该转换为数组 NSMutableArrayarr 其中 arr 0 嗨 arr 1 arr 2 如何 arr 3
  • 如果依赖项位于 false 分支语句内,则计算将永远停止触发

    我遇到一个问题 即我的计算可观察量在一系列依赖项更改后停止触发 最后我发现了一点 如果在最近一次评估期间依赖项位于错误分支语句内 则下次将不会触发计算即使在评估完成之前条件变为真 这是一个示例 https jsfiddle net sgs2
  • 非静态方法 next() 不能从静态上下文中引用

    我正在尝试解析一个mm dd yyyy将日期格式化为单独的字段 但是当我尝试编译时出现以下错误 非静态方法 next 不能从静态上下文中引用 什么可能导致错误 import java util Scanner public class Pr
  • 使用 c3p0 和 tomcat 与 MySQL 的僵尸连接

    我正在使用 c3p0 来管理与 MySQL 的数据库连接 问题是某些连接被永远保留 我的连接数限制为 1000 个 但由于某种未知原因 打开的连接数为 1200 个 为了调查它 我在 tomcat 服务器 shell 中执行以下命令 net
  • Eclipse PDT + 代码完成根本不起作用

    我想启动一个新的 Zend 项目 目前我面临一些有关 Eclipse PDT 的问题 我的问题是 Eclipse for PHP 中的代码完成根本不起作用 我尝试了很多不同的教程等 例如制作一个新项目并导入文件 创建一个新的工作区并在那里导
  • 在静态方法中使用 WPF 检测设计模式

    我正在使用 WPF 我有一个静态类 它执行一些在设计模式下不可用的设置 该构造函数由设计模式下的窗口调用 这会导致抛出异常 如何在静态方法中检测设计模式 以便可以调用适当的设计模式行为 The 推荐方法 https stackoverflo
  • 如何从远程页面获取iframe内容?

    我认为PHP没有用 因为iframe是在php执行后插入的 还是我错了 所以 我知道的唯一解决方案是使用 Javascript jQuery 例如 如果 JS 与 iframe 位于同一页面上 则这将起作用
  • 流式传输 html5 canvas 内容的有效方法?

    我正在尝试流式传输 a 的内容html5 canvas实时使用websockets and nodejs html5画布的内容只是一个视频 到目前为止我所做的是 我将画布转换为blob然后得到blob URL并使用 websockets 将