是否可以使用“javascript”或任何“网络客户端”方法从 gif(或一系列图像)和一些声音文件中编码视频?
具体来说,我想从一些源图像和声音文件在客户端动态创建一个视频文件。然后我想允许用户下载生成的视频。
我知道我可以使用 ffmpeg 和 PHP 在服务器端从图像和 mp3 创建视频,但我不想使用这种方法,因为这会导致大量服务器 CPU 使用和数据传输。
是否可以使用“javascript”或任何“网络客户端”方法从 gif(或一系列图像)和一些声音文件中编码视频?
具体来说,我想从一些源图像和声音文件在客户端动态创建一个视频文件。然后我想允许用户下载生成的视频。
我知道我可以使用 ffmpeg 和 PHP 在服务器端从图像和 mp3 创建视频,但我不想使用这种方法,因为这会导致大量服务器 CPU 使用和数据传输。
要实现这一目标,您需要解决几个问题。
获取 GIF 的原始像素。
<canvas>
可能是最好的方法,但我认为它不能很好地与动画 GIF 一起播放。您当然可以阅读一系列图像。
将帧转换为视频流。
虽然有MPEG 音频编解码器的 JavaScript 实现,但我不知道纯 JS 中的视频编解码器。您可以查看 ffmpeg 源代码并尝试移植它。
除了实现视频压缩编解码器本身(例如 MPEG-1、-2、H.264 等)之外,您还必须写入某种容器格式(例如,MPEG PS . )
处理二进制数据。
任何视频编解码器的输出都是二进制数据,而 JavaScript 本质上不能很好地处理原始二进制数据。最近的浏览器已经添加了类型化数组,以一种内存有效的方式来解决这个缺点。
将视频文件传送给用户。
我知道这听起来很傻,因为从技术上讲,以上所有内容都会发生在用户的计算机上,但它们会发生在浏览器沙箱中。您现在必须将数据从浏览器中取出并放入用户可以保存到其文件系统的文件中。
其他人建议使用data:
URI(base64 编码的数据),但从内存的角度来看,这是一个糟糕的主意,尤其是因为您将处理相对较大的视频数据。此时,您将拥有类型化数组中的视频流。从类型化数组创建一个新Blob
数组并将其传递Blob
给window.URL.createObjectURL
. 这样,数据就不需要在内存中重复了;相反,浏览器将从类型化数组“下载”到文件系统。
当然,所有这些都假设用户的机器有足够的内存(RAM)。与普通的视频压缩实现不同,您不能将输出数据流式传输到磁盘;您必须将整个文件保存在内存中。您可能会比您想象的更快地耗尽内存。
因此,虽然这在理论上可能是可行的,但这并不是一个好主意。如果它有效,它将非常慢并在对视频进行编码时冻结浏览器(因为 JS 和浏览器 UI 共享相同的单线程)。不过,我想你可以让网络工作者参与进来来解决这个问题。
此时,您几乎必须推出自己的服务器端解决方案或使用某种服务来为您完成繁重的工作。
或者,您可以在 Chrome 中利用 Google 的NaCl(本机客户端)来实际进行视频编码。NaCl 允许您在浏览器中运行本机 (C/C++) 代码。
看起来有一个ffmpeg port,并且有API 来做文件 I/O。
显然,这只适用于 Chrome。Firefox、Safari 和 IE 不支持 NaCl。
当然。
用于setInterval
按计划调用函数,将图像的来源依次更改为下一个。
您可能需要预加载图像,以便在图像源更改时无需等待。
更新:
您可以仅使用 JavaScript 从一系列图像创建视频文件,但这不太容易或效果很好。我建议您使用一些服务器端处理来生成这样的视频并将音频合并到其中(可能使用ffmpeg)。
您已经注意到,专门为此目的编写的 C 语言程序会消耗大量的 CPU 周期。是什么让您认为为其他目的而设计的脚本语言完全可以做到这一点?
不,浏览器上的Javascript不能直接访问单个像素,当然也不能创建二进制文件。如果您将帧作为单独的图像,则可以将它们加载到canvas
标签中,以这种方式访问像素,将 MPEG 版本计算为整数数组并将其发布回服务器(这会将数组转换为二进制文件),但是哇,那会很慢吗?至少比 ffmpeg 慢 1000 倍。
编辑
评论指出我实际上完全错了。尽管如此,我坚持我最初的结论,即这是一个糟糕的想法。
现在是 2014 年末,我不知道它是在什么时候成为可能的,但现在确实可以将视频变成 gif:http: //jnordberg.github.io/gif.js/tests/video .html
通过制作该演示的同一个人的图书馆:https ://github.com/jnordberg/gif.js
在 Chrome 38 中运行良好,我相信任何其他支持 Web Workers、文件 API 和类型化数组的浏览器。