实时播放Macintosh Plus

2022-02-22 14:37:06

自从在System 6videos上录制了一些C编程之后,我偶尔想直播在Macintosh Plus上进行的更随意的日常编程。在把所有的片段整合在一起之后,我现在有了一个工作的自助广播设置。

如果我现在正在Mac上编程,你可以在我的网站上观看。

回到2020年,我尝试为我的Macintosh Plus编写一个伪驱动程序,通过SCSI端口将其屏幕数据发送到带有RaSCSI帽的Raspberry Pi,该帽随后会在Pi的帧缓冲区上显示数据,从而可以通过Pi的HDMI输出捕获Mac的屏幕。这被证明是太慢的工作,在Mac上消耗了大量的处理时间(尽管它被承认没有得到很好的优化),所以我回去用一台真正的相机(iPad)录制视频。

在观看了Adrian Black的VideoIn 2021关于使用一个RGBTHDMI设备从Macintosh经典获得视频,我试图得到一个,但他们不出售任何地方。RGBtoHDMI是一块板,连接到Raspberry Pi Zero的GPIO头,使用CPLDT处理来自各种源的模拟或TTL数字视频,然后将其馈送到Pi上运行的一些裸机软件,以在Pi的HDMIoutput上显示。

建立自己的RGBtoHDMI最终花了我很长时间。我首先必须将开放源代码的PCB设计发送到PCBway进行打印(现在我有9个额外的PCB),然后对所有组件进行源代码开发。最重要的组件Xilinx XC9572XL CPLD也因全球组件短缺而最难获得。最后,组装需要焊接一堆小电容器和CPLD的44引脚,但我以前从未做过表面贴装焊接,所以我有点紧张。

随着RGBtoHDMI的工作,我需要将其连接到我的Mac Plus。我在连接Mac Plus的sanalog和逻辑板的线束上焊接了四根电线,接入单色视频信号、水平同步、垂直同步和接地。(这些电线只传输低压TTL信号,所以应该很安全,但不要相信我的话。)

我在电线周围加了热缩管,并把它们穿过Mac电脑后部的锁桌连接器。我还3D打印了覆盆子皮零和RGBtoHDMI的外壳。

一旦电线正确连接,RGBtoHDMI使用Adrian视频中的锁定设置进行调整,我的Mac Plus的512x342屏幕的像素完美副本就会实时出现在HDMI屏幕上(通过填充填充填充640x480帧缓冲区)。

我买了一个便宜的20美元的HDMI捕捉设备(用最不幸的马尔可夫链品牌),它把一个HDMI源作为一个标准的USB网络摄像头。在我的OpenBSD笔记本电脑上,它显示为带有uaudio的uvideo USB设备:

uhub5端口4配置1接口0和34处的uvideo1;宏硅USB3。0次捕获#34次;rev 2.00/21.00 addr 14video1在uhub5端口4的Uvideo1Audio1配置1接口3和#34;宏硅USB3。0次捕获#34次;rev 2.00/21.00 addr 14uaudio1:class v1,高速,同步,通道:0播放,1录制,1 ctlsaudio2在UAUDIO1HIDEV4在uhub5端口4配置1接口4和#34;宏硅USB3。0次捕获#34次;修订版2.00/21.00增补14uhidev4:uhidev4处的iclass 3/0uhid7:input=0,output=0,feature=8

我能够使用video(1)实用程序查看Mac屏幕的像素完美拷贝(使用YUY2编码时)。在我的测试中,这个廉价的HDMI捕获设备完全能够以30fps的速度显示Mac的屏幕,尽管它当然只是一个640x480的1位视频流。我不知道它(或OpenBSD)是否能够跟上更高分辨率的全彩源代码,比如捕捉游戏。

按照我一贯希望保留对内容控制权的方式,我不想将流媒体外包给YouTube或Twitch。

由于黑白屏幕数据非常紧凑(1位PNG的全屏数据在5Kb到9Kb之间),我希望通过将其压缩为视频流来避免模糊,因此我开始编写一个程序,直接从设备读取YUY2数据,丢弃不必要的像素数据,然后将其发送到我的服务器上运行的程序,该程序将通过网络套接字为其提供服务。其想法是,一些Javascript可以将WebSocket数据读取为流,并直接在<;帆布>;要素

我最终放弃了这个想法,转而使用FFmpeg和出色的rtsp simple服务器进行更传统的流媒体设置。在大量阅读文档、测试并猜测Firefox为什么不播放我发送的任何视频(它无法播放avc1.f4001e视频)后,我找到了一个有效的解决方案:

ffmpeg-f v4l2-i/dev/video1 \-c:v libx264-profile:v main-pix_fmt yuv420p-preset ultrafast \-filter:v";作物=512:344:64:69"\-max_muxing_queue_size 1024-g 30 \-rtsp_传输tcp \-f rtsprtsp://user:pass@jcs。组织:8554/live

这将指示FFmpeg从/dev/video1处的HDMI capture V4L2设备读取数据,在将其从640x480裁剪到512x344后,将其编码为x264视频,并使用Firefox所需的YUV420p像素格式。它将该流作为RTSP TCP流发送到运行在我的服务器上的RTSP simple server,然后将其作为HLS流使用。要在将流的副本保存到本地文件的同时进行FFmpeg广播,可以使用其tee输出:

Mac的屏幕是512x342,但无论出于什么原因,我都无法在顶部添加一个1像素的黑条,使其成为512x343,以该分辨率正确编码。我制作了512x344只是为了让它更均匀,然后在我的网站上调整视频位置,将其显示为512x342。

我没有向流发送任何音频,但这样做只是额外的-c:ffmpeg的一个标志,也可以从我笔记本电脑的麦克风对音频进行多路复用。也许我会在不听音乐的时候用键盘和鼠标点击的环境音频来实现这一点。

由于RGBtoHDMI软件直接在Raspberry Pi上运行,它在接收USB电源的几秒钟内启动并开始显示HDMI数据,而无需等待完整的Linux内核启动。

一旦视频可用,我就可以运行FFmpeg脚本并启动流媒体服务器,然后让任何打开Livepage的人都可以使用流媒体。由于我没有使用OBS或其他繁重的视频多路复用过程,所以它非常轻量级,我的无风扇OpenBSD Laptop在播放音乐和运行web浏览器时处理流媒体,没有任何问题。

在服务器端,我让nginx为我的常用网站提供服务,但/live目录中的内容请求被代理回rtsp simple server,该服务器处理所有HLS处理和服务的单个视频块和播放列表生成。我用的是hls。由于只有Mobile Safari支持a<;视频>;标记HLS流作为其源。我本想在没有Javascript的情况下做任何事情,但即使是我使用WebSockets的非视频解决方案也需要它。

我在Livepage上添加了一些小装饰,比如在视频流周围画一个Mac显示器,类似于我的修正和Wallopsscreenshots。当视频开始播放时,我还使用了CSS转换来“打开屏幕”,在不透明度变化中淡入淡出。

我还显示了一个实时的观看者计数,这是由服务器上的一个脚本跟踪rtsp简单服务器日志文件完成的,并根据在过去30秒内获取视频块的唯一IP对观看者进行粗略计数。它将此计数写入一个文本文件,当视频打开时,一些Javascript每10秒获取一次该文件,然后更新屏幕下的视图计数器。如果rtsp simple server能够自己进行粗略的查看器计数计算,并将计数作为HLSplaylist中的某种元数据发送,那就太好了,这样我就可以避免额外的服务器进程,每个客户端都必须单独获取这个计数器。

YouTube或Twitch等服务的一个组成部分是integratedchat。用户可以发送关于屏幕上正在发生的事情的评论或问题,我可以在聊天中或通过在流媒体上显示内容来回复。

因为我已经有了一个基于我其他视频的社区IRC频道,我只是在一个<;iframe>;允许用户直接从流页面加入。当然,对于不想在浏览器中聊天的用户,他们可以加入一个普通的IRC客户端,仍然与我和其他观众互动,这在YouTube或Twitch流中是不可能的(很容易)。我也可以用我刚刚为System 6编写的IRC客户端从Mac进入IRC频道。

我通常的视频需要在我和Mac电脑之间的桌子上放一台iPad†立即从两台摄像机上拍摄,这有点“脱离”了我对Mac电脑的体验,并真正进入了编程的最佳状态,因为我必须通过iPad的屏幕做所有事情。他们还需要我在家里安静的时候花一个小时或更长时间全神贯注地录制视频,然后再花一个小时重新编码视频,然后可能再编辑一个自动的闭路字幕文件。

由于我的实时流媒体设置只捕捉Mac电脑的屏幕,没有我的音频或视频,因此我可以随心所欲地进行广播,而不必担心我此刻的样子、家里其他地方发出的噪音(通常是我儿子在楼下跑来跑去)或我在笔记本电脑上播放的音乐,我可以在需要的时候从办公桌上站起来,时间很短。

将来我可能会在页面上单独添加一个可选的视频和音频流,但现在我喜欢的是,它只是我的Macintosh屏幕上的一个短暂的流。