用 Chromebook 打造的疯狂 Video Wall 项目
用 Chromebook 打造的世界级疯狂 Video Wall
- 2025年3月1日 星期六
- #writeups
这是一个我们耗时三年,将一批笔记本电脑改造成堪称世界级疯狂 Video Wall 的故事。
这个项目是我和我朋友 Aksel Salmi 合作完成的。我负责软件部分,他设计了令人难以置信的硬件。请查看 他的博客,了解安装这些拆卸后的电脑所需的出乎意料的复杂硬件[1]。
大约三年前,我的设计老师(了不起的 Bush 先生)向我们提出了一个想法——我们学校即将处理一批 Chromebook,他想知道我们是否可以用它们做些什么。
认识 Lenovo ThinkPad 11e #
Lenovo ThinkPad 11e 很可能就是世界上最糟糕的笔记本电脑。它也是标准配置的学校笔记本电脑,巩固了八岁的我对电脑的兴趣。
我们从小学到初中开始一直使用这台学校配发的笔记本电脑。这是我五年级时使用学校笔记本电脑做 PYP Exhibition 项目(一个用 Scratch 制作的游戏)[2]。
尽管我对它们有情感上的联系,但今天这些设备实际上就是垃圾。因此,我的学校开始用(稍微不那么垃圾的笔记本电脑)替换它们。
这些东西不再收到来自 Google 的软件更新,它们难以加载大多数网页,更糟糕的是,它们与一些早已被遗忘的 Enterprise Enrolment 系统绑定,因此甚至无法在没有学校 Google 帐户的情况下使用。
什么是 Video Wall? #
Video Wall 是一个大型显示器,由多个屏幕排列在一起组成,以在所有屏幕上创建一个单一、无缝的显示。在我们的项目中,我们决定尝试重新利用笔记本电脑屏幕来构建 Video Wall。
我们可以使用单独的硬件来驱动屏幕吗? #
我们的第一个想法是只收集笔记本电脑的显示面板,并以某种方式使用一台可以同时驱动 10 个屏幕的强大计算机来驱动它们。我们没有走这条路(因为我们不知道自己在做什么,并且对所涉及的时间和成本的快速估算吓退了我们)。
好的,在我们尝试任何其他方法之前,让我们先尝试在两个设备上同步一个视频 #
由于屏幕连接到功能完好的笔记本电脑,因此很快就清楚,我们最好让每个屏幕由自己的笔记本电脑主板独立驱动。
在这一点上,仍然存在许多问题(例如,我们如何在 Chromebooks 上做到这一点),因此我们将这个挑战放在一边,专注于它带来的新问题:我们可以在多台计算机上同步一个视频吗?
我们的实验将我们带到了学校的计算机实验室,在那里我们尝试了 VLC 的流媒体功能,以使流在单个网络上的设备之间同步,但这带来了两个挑战:该系统并非为 完美 同步的视频而设计,也并非为两个客户端接收不同的视频输入而设计(因为 Video Wall 的全部意义在于在屏幕上显示一个超长的视频,而不是同一视频的 10 个重复副本)。
我们在这里陷入了困境,直到我的“突破”。
背景是,故事目前发生在 2022 年。两年前,由于 COVID 封锁,我被锁在房间里,在这段时间里,我通过构建随机的实时 Web 应用程序(例如聊天应用程序和多人绘图游戏)获得了大量的乐趣。这些应用程序之所以有效,要归功于 socket.io
,这是一个(主要)基于 WebSocket 的库,允许低延迟的双向通信。
我制作的一个聊天网站的屏幕截图,用于打发 2020 年封锁期间的时间
我意识到,使视频同步的最佳方法是使用一个使用 socket.io
来同步客户端之间视频播放的网页。是的,有更好的方法,但考虑到所有因素,仅仅这样做效果非常好。
<video src="..." id="video">
你的浏览器不支持 video 标签。
</video>
const socket = io();
// ...
socket.on("play", () => {
const videoElement = document.getElementById("video");
videoElement.play();
});
我将这个 ExpressJS 服务器/客户端系统命名为 c-sync
[3]。
感谢 c-sync(以及大量的调整),经过一段时间后,我们在计算机屏幕上通过网页获得了相当同步的视频(或者至少在这些台式计算机上进行测试时看起来是这样)。
事实证明,实际上,Chromebooks 太慢了,无法可靠地同步播放,并且加载时间 + 延迟 + 系统时钟等方面的微小差异导致视频无法同步。
现在,我不完全确定 为什么 它如此有效,但我偶然想出了一个荒谬的解决方案。当视频达到播放结束时,每个客户端都会发出开始事件。
video.onended = () => {
socket.emit("start");
// 是的,说真的,这就是我所需要的全部
};
这意味着最慢的计算机会阻碍最快的计算机,并获得加载视频的机会。这也意味着循环可能是一个非常轻微的抖动过程(每个屏幕收到 10 个“开始”事件),但只要视频的前几帧相同,就不会有人注意到。
旁注:为什么不使用时间戳进行调度?现代计算机具有您可以依赖的时钟,这些时钟非常精确。加上定期的 NTP 同步,这意味着一个理性的人可能会尝试确保整个视频都已缓存,然后只向每个客户端发送一个“开始”事件,该事件会安排客户端在给定的时间戳开始播放。不幸的是,这些 Chromebook 无法可靠地跟踪彼此之间几毫秒内的时间,因此这种方法对我们不起作用。
使用这种方法,我们几乎可以完美地同步视频播放,并且可以在任何屏幕上播放任何视频(这意味着我们可以将一个宽视频分成 10 段,并且每台计算机显示其各自的部分,所有这些都彼此同步)。
组合在一起 #
已拆卸的 Chromebook 打开到测试视频
我们在一个月或两个月内达到了这个阶段。信不信由你,这个项目还有三年的工作要做。最大的问题是 Chromebook 软件。在这一点上,我们有一个网站,我们可以在每台笔记本电脑上手动打开该网站以显示全屏同步视频。
理想情况下,我们希望这是完全自动化的,以便 Chromebook 一收到电源,它就会自动启动到 c-sync 客户端页面。不幸的是,目前,启动 Chromebook 只会带您到一个 Google 登录页面(并且该页面被锁定到我们的学校域名 才能启动)。
另外,只是为了雪上加霜,当电池被移除时,笔记本电脑在收到电源时不会自行打开(您必须按住电源按钮)。
这意味着我们的下一步将必须是用其他东西替换 ChromeOS。
ChromeOS Firmware Recovery Script
是一项神奇的技术,它以某种方式支持许多不同的 Chromebook 主板。我们的主板被称为“GLIMMER”。我们只需要进入内置的“恢复模式”,启用“开发者模式”并使用 ChromeOS Shell 运行脚本。
现在我们基本上已经进入了最后阶段。我们所需要做的就是选择一些稳定的 Linux 发行版,编写一个粗糙的启动脚本,该脚本会加载 Chromium 并模拟按键以使视频全屏显示,我们就完成了!
我们遇到了两个主要问题:一些 Chromebooks(大约一半的可用笔记本电脑)由于企业注册而拒绝进入开发者模式,并且虽然我们能够将另一半装载到 Linux 发行版上,但视频播放会在一段时间后持续冻结(实际上它们会完全锁定)。
我们花费了几个月的时间来断断续续地进行实验以弄清楚该怎么做。从本质上讲,解决方案是用 coreboot
覆盖整个默认固件(这也可以使用 MrChromebox 的脚本来完成)。我们只需要从每台笔记本电脑的主板上卸下“写保护”螺钉,并且这似乎也绕过了注册。
Lenovo 的方便的写保护螺钉图
为 20 多台计算机执行此操作既缓慢又繁琐。我们只需要 WiFi、主板和屏幕处于工作状态,但我们决定(主要)保持温和并保持笔记本电脑看起来像笔记本电脑,以便我们在其余安装步骤中使用键盘和鼠标。
到最后,我们非常有效地卸下了写保护螺钉
在“corebooting”Chromebooks 之后,我们也很惊喜地发现“Wake on AC”是固件的一项功能,并且视频播放不再随机中断。到目前为止,我们已经有了足够的未损坏的 Chromebooks,可以组成 10 个屏幕的阵容,以及少数几个备用屏幕。
最后冲刺 #
现在我们真的进入了最后冲刺阶段。Aksel 负责安装硬件,您可以 在他的博客上阅读有关它的信息,而我则致力于寻找一种比我拼凑在一起的按键模拟和启动脚本更可靠的“启动到网页”的方法。
我之前为另一个项目使用了 名副其实的“FullPageOS”(我在 [我的 TED 演讲中简要提到了它,您应该观看该演讲](https://varun.ch/posts/videowall/https:/youtu.be/gzc1p_QlO2I?t=457)),但它无法在 x86 硬件上运行。
我最终使用了“Porteus Kiosk”,它只是一个最小的 Linux 发行版,它会打开一个全屏 Chromium 浏览器,其中包含所有正确的标志,以便进行免手动使用(例如,允许视频播放而无需用户交互)。
老实说,这完全没问题,但由于两个原因,我仍然不满意。首先,我不喜欢我们无法自定义启动画面,因此我们的项目将在每次启动时(即每天早晨)永远带有 Porteus 徽标。其次,为了寻找一个更好的问题来证明额外的工作是合理的,我意识到如果没有重新安装,我们就无法远程对安装进行任何操作(例如,更改页面 URL),一旦将它们安装在墙上,这肯定会是一个问题。
由于这些充分的理由,我开始了构建我们可以在笔记本电脑上安装的“自己的发行版”的旅程。该系统应从最小的系统开始(没有桌面环境),并具有一个优雅的脚本,以自动启动 kiosk 模式 Chromium 实例。
我首先尝试了 NixOS,然后很快意识到它无法与这些 Chromebooks 上的少量存储空间一起使用(并且每次尝试都无法安装)。
然后我放弃了,从 Debian 最小安装开始,只是编写了一个脚本来配置客户端(生成一个“KIOSK_ID”,将其主机名设置为 csync-client-$KIOSK_ID
,连接到学校的 WiFi,创建用户/权限并设置 openbox
以自动启动全屏 kiosk 模式 Chromium)。
然后在尝试在第二台机器上重复此操作之后,我意识到我会浪费大量时间(安装 Debian 非常“手动”——您需要按下许多按钮),然后我发现了“FAI - Fully Automatic Installation”以及 Web FAI.me 工具。简而言之[4],在重做了无数次之后,我有一个可以插入任何“corebooted” Chromebook 的 USB,该 USB 会将其配置为 c-sync 客户端。哇!
我还为 c-sync 构建了一个“控制器”,使我们可以管理连接的客户端并为其分配视频。
经过为期三天的压力测试,视频播放仍然非常流畅(并且我牺牲了睡眠能力,以便在打开背光的情况下进行更好的测试),我们准备将这些笔记本电脑安装在墙上。
安装 #
安装主要是 Aksel 的事情,因此 我恳请您阅读他的博客,但这里有一些来自该过程的酷照片。(另外,我们的电缆拼接是否非常漂亮且不可怕??😁❤️)
使用激光切割的亚克力片安装背板的早期迭代
Aksel 设计了一个非常棒的背板来安装主板,该主板悬挂在墙壁上的防滑钉上。然后,显示器用夹紧的东西固定到位。这对我来说是黑魔法。
一切都放好了
准备一些显示器和主板
我们决定将电源线拼接在一起,以便每个电源可以为两台计算机供电。如有任何投诉,请发送至我的联系页面上的寻呼机
快完成了!
还有一件事…… #
在我们费尽心思地安装完所有东西后,我意识到了一些有点重要的事情。计算机会产生热量。在清除固件的过程中,笔记本电脑风扇停止了旋转,这意味着东西很快就会变得很热。我必须想办法让它们再次工作,这样我们才能放心地让它 24/7 运行(好吧,实际上是 12/7)。
嵌入式控制器 #
显然,您可以使用名为 ectool
的工具与 “ChromeOS Embedded Controller” 进行交互,该工具应允许您手动设置风扇速度(以及其他内容)。在线文档不足,并且显然有一个来自 coreboot
和直接来自 Google 的略有不同的 ectool
。这些对我来说完全没有意义,并且我能找到的任何已构建的 ectool
二进制文件都无法工作。在某个时候,我发现了一个死链接,但是 感谢 Wayback Machine 的魔力,我能够找到一些不会立即崩溃的东西。
奇迹般地,此版本的工具实际上可以很好地设置风扇速度,经过一些测试,我找到了一些平衡噪音和温度的黄金值。
旁注:为该设备制作视频 #
事实证明,制作如此宽的视频实际上并不容易。每个显示器的分辨率为 1366×768,并且很少有软件可以让您编辑 13660 × 768 的视频。Final Cut Pro 和 Blender 是我们能够以如此宽的尺寸进行任何操作的唯一程序。
Blender 是有史以来最伟大的软件之一(与 c-sync 一起)
然后只需渲染宽视频并将其分成 10 段即可。
#!/bin/bash
# 以防万一有人再次遇到这种疯狂的用例
input_video="input.mp4"
prefix="v8"
width=1366
height=768
segments=10
for ((i=1; i<=segments; i++)); do
x_offset=$(((i - 1) * width))
output_file="${prefix}-${i}.mp4"
ffmpeg -i "$input_video" -vf "crop=$width:$height:$x_offset:0" -c:a copy "$output_file"
done
echo "拆分完成!"
荣耀时刻 #
启动顺序和“自校准” #
播放
同步视频! #
播放
现在有一个外壳和电缆布线! #
播放
是的,它是不完美的 #
我们的 Video Wall 是不完美的。TN 面板视角很糟糕,并且屏幕的颜色和其他东西各不相同。是的,同步不是 完美的 ,是的,我相信我们沿途做出的几乎每个决定都有更好的替代方案。
但我喜欢我们的 Video Wall,尽管它非常荒谬。它是迭代设计过程的完美代表,也是团队合作和协作的真实证明。我们将电子垃圾变成了有趣的东西。也许,真正的 Video Wall 是我们一路结交的朋友。
这个项目之所以成为可能,要归功于许多人的辛勤工作。除了我的合作者 Aksel Salmi 之外,我们的设计老师 Daniel Bush 在指导我们完成该项目方面发挥了巨大作用。
此外,我要感谢 coreboot project 和 Matt ‘MrChromebox’ DeVillier 构建 固件和工具,这些固件和工具使这一切得以实现。我还想感谢 FAI project 的 Thomas Lange 在构建基于 FAI.me 的自动化安装程序方面提供的帮助,该安装程序为我们节省了大量时间,以及他通过电子邮件提供的支持。
听起来很傻,但这个项目是我高中经历的支柱。在过去的几年里,我们每个星期一都在研究它,并且我们也一路成长。
脚注
- 由于这个项目是他 Common App 文章的主题,我认为说它帮助他进入了一所常春藤盟校大学是公平的!很酷的东西。我仍在等待我的录取通知书寄来。如果您碰巧是大学招生官员......您好! ↩
- 去年夏天,我继续以实习生的身份加入了 Scratch 的工程团队。 ↩
- 我将其命名为 c-sync,作为对许多押韵的“VSYNC”、“G-Sync”、“FreeSync”产品的松散参考。而且因为它听起来像 sea-sink。就像一艘没有漂浮的船。 ↩
- 有趣的事实:如果您的系统时间相对于软件包日期不正确,则 apt 无法在本地安装软件包。Chromebooks 的系统时钟电池都坏了,所以它们的日期自然会被搞砸。解决方案是切换到 tty,将日期设置为合理的值,并在不让笔记本电脑失去交流电源的情况下重新启动脚本。 ↩
- 上一篇:浏览器需要更改自动填充的工作方式
版权所有 © 2025 Varun Biniwale。保留所有权利。