如何编辑 Chrome MediaRecorder 捕获的 .webm Blob

2024-04-25

在 Chrome 中。我在用着媒体记录器 https://developer.mozilla.org/en-US/docs/Web/API/MediaStream_Recording_API and canvas.captureStream() https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/captureStream创建画布的 webm 文件。

let recorder = new MediaRecorder(document.querySelector('canvas').captureStream(), {mimeType: 'video/webm'});
let chunks = [];
let blob;

recorder.ondataavailable = function(event) {
  if (event.data.size > 0) {
    chunks.push(event.data);
  }
};
recorder.onstop = function() {
  blob = new Blob(chunks, {type: 'video/webm'});
  let url = URL.createObjectURL(blob);
  let a = document.createElement('a');
  document.body.appendChild(a);
  a.href = url;
  a.download = Date.now()+'.webm';
  a.click();
  window.URL.revokeObjectURL(url);
  a.parentNode.removeChild(a);
}
recorder.onstart = function() {
  chunks = [];
}

这是基本的录音和下载代码以及调用recorder.start()开始录音并recorder.stop() to end.

输出的 webm 文件很好,我遇到的问题是,由于计算机/开销很差,我不能总是足够快地绘制画布以使其达到完整的 60 fps。在画布本身上,我不介意较低的帧速率,但绘制到画布上的延迟会转化为 webm,并且我留下的是 x0.9 速度的视频。

我尝试通过使用来解决这个问题canvas.captureStream(0)一次仅捕获一帧并将其与每个画布渲染相匹配。但这失败了,因为我无法指定每个帧应持续的持续时间,并且文件大小变得巨大,因为每个帧都有所有标头信息。

我可以在我的 blob 数组中看到,前 131 个 blob 是常量,而第 132 个 blob 的数据量非常大。之后,通常有大约 7 个间隔 blob(每个 1 字节),然后是一个包含大量数据的单个 blob。我知道前 132 个 blob 是标头信息 + 我的第一帧。我想象每帧都有大量数据的斑点。我还假设 1 字节间隔块与帧持续时间或暂停一定时间有关。

我想做的是能够修改这些间隔块以指定帧的确切持续时间。我尝试手动执行此操作,方法是在我知道帧速率理想的 2 帧之间复制 7 个间隔块,然后删除所有其他间隔块并在每个帧之间粘贴这些理想的间隔块,但输出文件无法播放。

我是否误解了 blob 数据?有没有办法通过修改 blob 数据来手动指定帧持续的持续时间,或者我是否坚持可以绘制到画布上的任何帧速率?


我能够通过在超时时暂停和恢复记录器并在再次暂停之​​前请求帧来定义与画布刷新率分开的帧率:

let recorder = new MediaRecorder(canvas.captureStream(), {mimeType: 'video/webm'});
recorder.start();
recorder.pause();

function draw() {
  context.drawImage(...);
  recorder.resume();
  setTimeout(function() {
    recorder.requestData();
    recorder.pause();

    //update progress bars or any laggy overhead stuff at this point

    requestAnimationFrame(draw);
  }, 1000/fps);
}
requestAnimationFrame(draw);

这样,实际画布绘制或更新进度条等中的任何滞后都不会影响记录器的帧集合。recorder.requestData()似乎没有必要,但也似乎没有任何缺点。为了清楚起见,将其包含在此处。

我没有详细检查过,但开头可能有双帧,具体取决于是否recorder.start()收集初始帧并且您的画布不是空白的。

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

如何编辑 Chrome MediaRecorder 捕获的 .webm Blob 的相关文章

随机推荐

  • PHP 创建日期范围

    以这种格式的日期开始 2011 05 01 09 00 00 如何创建一个包含一年中所有工作日 因此排除所有周六和周日 的所有办公时间 09 00 到 17 00 的数组 我想要达到的是这样的 2011 05 01 09 00 00 201
  • 重置远程跟踪分支

    如何将远程跟踪分支的分支指针重置为其之前的提交之一 这样看起来我没有拉动 类似于本地分支的硬重置 您可以使用以下命令设置对任何其他提交的引用 git update ref refs remotes origin master
  • 如何从 VB-6 旧应用程序中启动屏幕键盘程序

    我正在尝试从 Windows 10 32 或 Windows 10 64 位计算机上的 VB 6 应用程序中 shell osk exe 过去我们只是简单地使用 Private Sub Command1 Click Dim strTemp
  • 您能否将 TeamCity“工件”配置为重新检入源代码管理?

    我希望将 TeamCity Artifacts 重新签入源代码管理 我以前使用过 TFS Integrator 所以我习惯了它的方法 通过配置 它可以将输出构建签入源代码管理 然后 当人们进行 get 操作时 他们将收到这些文物 或者是否有
  • 指定共享对象(共享库)的名称

    Go 编译器为共享对象生成的名称是错误的 例子 go install buildmode shared linkshared github com apache thrift lib go thrift code google com p
  • Windows 安装程序和安装应用程序合并到一个文件中?

    我使用 Visual Studio 在 C 中编写了一个应用程序 我创建了一个项目设置文件 该文件在我的调试中为我创建了文件 Windows Installer 和安装应用程序都是必需的 但我想将它们合并为一个 就像当您下载应用程序时 安装
  • java中删除文件中的一行

    好的 所以我尝试使用 java lang String 从文本文件中删除行 目前我这样做的方式是跟踪行号并输入索引 索引是我要删除的行 因此 每次读取新的数据行时 我都会增加行数 现在 当我达到相同索引的行数时 我不会将数据写入临时文件 现
  • asp.net mvc相当于rails回调before_save

    您好 我正在寻找一个 ASP NET MVC 回调 以便在保存模型之前获取详细数据 Rails 中有 before save Thanks 如果您正在使用实体框架 您的标签表明 那么这个 StackOverflow 帖子 https sta
  • Async CTP 可以与可移植库一起使用吗

    我想看看异步 CTP 是否带有可移植类库 不可以 异步 CTP 对于桌面 电话 Silverlight 4 和 Silverlight 5 有不同的 dll 希望在不久的将来 所有这些平台都将原生支持任务 和异步 然后可移植类库将能够使用异
  • 依赖注入和项目参考[重复]

    这个问题在这里已经有答案了 我正在尝试了解 DI 以便更好地了解 IoC 以及其他好处 在 DI 之前 我有一个项目 其中包含一个 UI 项目 MVC 一个 BusinessLogic 项目和一个 DataAccess 项目 我还有一个 S
  • 当 Django 在 postgresql 中使用可序列化事务隔离级别时,哪些具体异常代表序列化失败?

    有时 对于 Django 中的数据库操作 需要使用比默认 已提交读 更高的隔离级别 文档警告 https docs djangoproject com en 1 11 ref databases isolation level that 在
  • StringBuilder 在 C# 中的性能?

    我有一个StringBuilder对象 我在其中添加一些字符串 如下所示 我想知道哪种方法更好 第一个是 StringBuilder sb new StringBuilder sb Append Hello How are you 第二个是
  • 使用 XSLT 转换 XML 并保留 Unicode 字符

    我的 XSLT 转换已经成功了几个月 直到我遇到带有 Unicode 字符 很可能是表情符号 的 XML 文件 我需要保留 Unicode 但 XSLT 正在将其转换为 HTML 实体 我认为将编码设置为 UTF 8 可以解决我的问题 但我
  • 为什么 copyTo(... PASTE_VALUES) 在宏中间不起作用?

    我长期使用的电子表格技术之一是就地复制 粘贴特殊值 C PSV 使用公式生成我感兴趣的值后 I C PSV 然后可以删除源数据 所以我写了一个使用这种技术的宏 但单元格最终是空的 但如果我将宏分成两个 在 C PSV 之前结束第一个宏 那么
  • 不同种类的ReaderT?

    冒着成为一个XY问题 https en wikipedia org wiki XY problem 是否有可能有一个ReaderT与不同的环境 我正在尝试类似 type AppM perms ReaderT perms IO 但是编译器抱怨
  • 如何以动态方式创建 Spring Bean。使用 Quartz SchedulerFactoryBean

    我有一个QuartzJobConfig我注册的班级Spring Quartz Beans 我按照指示SchedulerFactoryBean JobDetailFactoryBean and CronTriggerFactoryBean 我
  • 绘制动画

    我正在创建一个简单的应用程序 当用户按下按钮时 屏幕上将绘制一系列线条 并且用户将能够实时看到这些线条 几乎像动画一样 我的代码看起来像这样 已简化 UIGraphicsBeginImageContext CGSizeMake 300 30
  • 如何在Java中对多通道声音输入进行采样

    我意识到这可能是相对小众的 但这也许就是为什么无论如何都要问这个问题 我正在寻找一个硬件多输入录音控制台 例如 Alesis IO 26 来接收 Adat 光管 8 通道输入来进行信号处理 由于我还没有获得该设备 并且需要弄清楚这是否可行
  • ListView 与 getView() 由于不断的 GC 而变得缓慢?

    我的应用程序中有一个 ListView 并且我已经重写了 getView 方法 因此我可以根据行的文本更改行的 ImageView src 问题是 我注意到 ListView 滚动滞后 当我检查 DDMS 时 似乎每次滚动 ListView
  • 如何编辑 Chrome MediaRecorder 捕获的 .webm Blob

    在 Chrome 中 我在用着媒体记录器 https developer mozilla org en US docs Web API MediaStream Recording API and canvas captureStream h