Raspberry Pi的开源AirPlay镜像服务器

2021-02-06 19:49:01

Raspberry Pi的AirPlay镜像服务器的开源实现,目的是使其即使在Raspberry Pi Zero上也能平稳运行。

屏幕镜像和音频适用于iOS 9或更高版本。最新的macOS版本似乎也兼容。 GPU用于解码h264视频流。 Pi没有音频的硬件加速(AirPlay镜像使用AAC),因此使用FDK-AAC解码器。

音频和视频在Raspberry Pi 3B +和Raspberry Pi Zero上都可以正常工作,尽管在3B +上回放更流畅。

确保没有其他苛刻的任务正在运行(这对于Pi Zero上的音频尤为重要)

通过使用OpenSSL进行AES解密,我可以将视频数据包的解密速度从大的数据包的0.2秒提高到0.007秒(在Pi Zero上)。现在平均更像是0.002秒。

RPiPlay可能不适合用于远程视频播放,因为它缺少专用的组件:AppleTV上的AirPlay似乎有效地在设备上运行了Web服务器并将URL发送到AppleTV,从而避免了对RPiPlay的重新编码。有关详细信息,请参阅(大多数已过时的)官方AirPlay规范。

为了在全新的Raspbian Stretch或Buster安装上进行构建,应运行以下步骤:

sudo apt-get install cmakesudo apt-get install libavahi-compat-libdnssd-devsudo apt-get install libplist-devsudo apt-get install libssl-devmkdir build cd buildcmake ..make

sudo apt-get install cmake libavahi-compat-libdnssd-dev libplist-dev libssl-dev \ libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-libav \ gstreamer1.0-vaapi gstreamer1.0-plugins -badmkdir构建cd buildcmake ..make

sudo dnf install cmake avahi-compat-libdns_sd-devel libplist-devel openssl-devel \ gstreamer1-plugins-base-devel gstreamer1-libav gstreamer1-vaapi \ gstreamer1-plugins-bad-freemkdir build cd buildcmake ..make

注意:gstreamer渲染器不支持-b,-r,-l和-a选项。

构建之后,要在系统上永久安装可执行文件(以便可以在任何地方运行),只需运行以下命令:

启动rpiplay可执行文件,AirPlay镜像目标设备将出现在网络中。目前,这些选项已实现:

-l:启用低延迟模式。低延迟模式通过在接收到音频和视频帧后立即有效地渲染它们而忽略了相关的时间戳,从而减少了延迟。副作用是,播放会断断续续,音频视频同步会明显关闭。

此存储库中的所有资源仅使用来自Internet的免费可用信息来编写。该代码和相关资源仅用于教育目的。用户有责任确保遵守所有当地法律。

该项目利用第三方GPL库来处理FairPlay。该图书馆的法律地位尚不清楚。如果您是Apple的代表,并且对该库的合法性及其在本项目中的使用有任何异议,请与我联系,我将采取适当的措施。

鉴于有大量可供购买的第三方AirPlay接收器(大多是封闭源),据我了解,具有相同功能的开源实现也不会侵犯任何Apple的权利。

随着时间的推移,此存储库中的代码是从各种来源累积的。这是我尝试列出各种作者及其创建的组件的尝试:

dsafa22:基于ShairPlay为Android创建了AirPlay 2镜像服务器(现在似乎消失了)。这个项目基本上是dsafa22代码到Raspberry Pi的移植,利用OpenMAX和OpenSSL在Pi上获得更好的性能。 lib /中所有有关镜像的代码都是dsafa22的工作。许可证:GNU LGPLv2.1 +

JuhoVähä-Herttua及其贡献者:创建了一个名为ShairPlay的AirPlay音频服务器,包括对基于PlayFair的Fairplay的支持。 lib /中的大多数代码最初都来自此项目。许可证:GNU LGPLv2.1 +

EstebanKubata:创建了一个名为PlayFair的FairPlay库。位于lib / playfair文件夹中。许可证:GNU GPL

Joyent,Inc和贡献者:创建了一个名为llhttp的http库。位于lib / llhttp /。执照:麻省理工学院

XBMC小组:设法为OpenMAX视频渲染显示黑色背景。该代码在视频渲染器中使用。许可证:GNU GPL

Alex Izvorski和贡献者:编写了h264bitstream,一个用于处理h264流的库。用于减少Raspberry Pi视频管道中的延迟。位于renderers / h264-bitstream文件夹中。许可证:GNU LGPLv2.1

恐怕我没有时间定期维护此项目。相反,我希望可以通过社区的努力来改善这个项目。我会根据个人需要修复和添加尽可能多的东西,并且我希望您也可以这样做!

现在,音频和视频可以在Raspberry Pi Zero上运行。我不知道该技巧到底做了什么,但是静态编译似乎有所帮助。

由于多种原因,要明确定义组成AirPlay流系统的组件的协议名称和版本非常困难。实际上,用于市场营销的AirPlay版本号似乎与实际实施中使用的版本号不同。为了稍微整理一下整个混乱情况,我做了一些研究,想在此总结一下:

AirPlay协议套件的真正起源是在2004年左右的某个时候作为AirTunes推出的。它允许将音频从iTunes流传输到AirPort Express电台。在内部,使用的协议名称为RAOP或远程音频输出协议。似乎早在那时,该协议就涉及AES加密。需要一个公共密钥来加密发送到AirPort Express的音频,并需要私有密钥来接收协议(即,在AirPort Express中用于解密流)。早在2004年,对公钥进行了逆向工程,因此开发了第三方发件人应用程序。

大约在2008年的某个时候,该协议进行了修订,并命名为AirTunes2。似乎更改主要涉及时间安排。到2009年,对新协议进行了逆向工程并记录了下来。

当Apple TV第二代于2010年推出时,它获得了对AirTunes协议的支持。但是,由于此设备允许播放视觉内容,因此该协议得到了扩展,并重命名为AirPlay。现在可以流式传输照片幻灯片和视频。在第二代Apple TV发行后不久,iOS 4.2更新中包括了对iOS的AirPlay支持。似乎到那时,音频流实际上仍在使用与上述相同的AirTunes 2协议。视频和照片流是作为基于HTTP的全新协议添加的,与音频流几乎没有关系。很快,第一批好奇的开发人员开始研究它是如何工作的。他们的结论是视觉内容未经加密就流化了。

2011年4月,一位才华横溢的黑客从AirPort Express中提取了AirPlay私钥。最终,这意味着第三方开发人员也可以构建AirPlay接收程序(服务器)程序。

对于2011年发布的iOS 5,Apple向AirPlay套件添加了新协议:AirPlay镜像。最初的研究人员发现,此新协议使用加密功能来保护传输的视频数据。

到2012年,大多数AirPlay协议都经过了逆向工程并记录在案。在这一点上,音频仍使用大约2008年左右的AirTunes 2协议,视频,照片和镜像仍以未经修改的形式使用其各自的协议,因此您仍然可以说是AirPlay 1(基于AirTunes 2)。在Apple TV上运行的Airplay服务器报告为版本130。AirPlay镜像的设置使用xml格式,尤其是stream.xml文件。此外,实际音频数据似乎使用ALAC编解码器仅用于音频( AirTunes 2)流媒体和AAC用于镜像音频。至少在更高的iOS版本中使用了这些不同的格式。

在iOS 9之前的某个时间,已略微修改了镜像协议:代替了" stream.xml" API端点,只需将API端点更改为" stream&#34 ;,而无需任何扩展,就可以以二进制plist形式查询相同的信息。我无法弄清楚哪个特定的客户端/服务器版本实际使用了其中的哪个。

对于iOS 9,Apple在2015年对AirPlay协议进行了重大更改,包括音频和镜像。显然,音频协议仅稍作修改,而较小的更改恢复了兼容性。为了进行镜像,在连接建立过程中添加了一个附加的配对阶段,该阶段由对建立和对验证呼叫组成。看来,添加这些是为了简化频繁连接的设备的使用。配对设置仅在iOS设备首次连接到AirPlay接收器时使用。生成的加密绑定可用于以后的会话中的配对验证。此外,stream / stream.xml端点已替换为info端点(仅可作为二进制plist AFAICT使用)。从iOS 12开始,仍仅对iOS 9引入的协议进行了少许改动(即使是传统模式)也受支持。 iOS 9使用两个SETUP调用(一个用于常规连接和镜像视频,一个用于音频),而iOS 12旧模式使用3个SETUP调用(一个用于常规连接(定时和事件),一个用于镜像视频,一个用于音频) 。

tvOS 10.2的发布在2017年破坏了许多第三方AirPlay发送器(客户端)程序。原因是现在必须强制通过大头针执行设备验证才能将内容流式传输到Apple TV。该功能以前曾在协议中提供,但不是强制性的。关于新方案的一些讨论可以在这里找到。配对和认证协议的完整规范已在GitHub上提供。当时,tvOS 10.2报告为AirTunes / 320.20。

iOS 11.4在2018年添加了AirPlay2。尽管媒体广泛报道了该信息,但尚不清楚苹果在协议方面做出了哪些具体改变。

从捕获的运行iOS 12.2的iOS设备与运行tvOS 12.2.1的AppleTV之间的流量捕获中可以看出,在初始握手之后,主镜像HTTP连接上的通信已加密,这在理论上可能是新AirPlay 2的一部分协议。运行tvOS 12.2.1的AppleTV标识为AirTunes / 380.20.1。从同一iOS设备连接到第三代AppleTV(报告为AirTunes / 220.68)时,仍然可以清晰地看到通信。从iOS设备连接到第三代AppleTV时产生的日志消息中,很明显,iOS设备正在将此简单协议视为旧协议(最初由iOS 9引入)。进一步的研究表明,目前,所有可用的第三方AirPlay镜像接收器(服务器)都在使用此旧协议,包括dsafa22的开源实现,后者是RPiPlay的基础。鉴于Apple认为这是旧版协议,可以预期将来会完全删除它。这意味着所有第三方AirPlay接收器都必须在某个时候更新为新的(完全加密的)协议。

更具体地说,加密是在完成对验证握手之后开始的,因此fp-setup握手已经在进行加密了。从AirPlay视频(又名HLS中继)的加密方案来看,套接字通信可能使用两种AES GCM 128密码(一种用于发送,一种用于接收)。但是,我不知道如何从握手数据派生密钥。