本文以时间顺序讲述一个后端程序员为了在Apple TV上观看球赛并开发了一个Apple TV应用的故事。先简单介绍一下App。地址:https://apps.apple.com/app/dlplay/id6448221325

DLPlay 是一款在 Apple TV 上实现 DLNA 投屏的软件,经过若干次的迭代,软件基本能适配大部分国内使用率高的视频软件。软件一开始开发出来的目的原本只是为了用咪咕视频投屏看球赛,随着用户越来越多,客户的需求也越来越多。主要分为三类:

  1. 投送哔哩哔哩/腾讯视频/优酷等视频类。
  2. 投送斗鱼/虎牙/抖音等直播类
  3. 投送 Nas/Jellyfin/迅雷本地视频类

DLPlay 对这三种场景都做了适配,可以选用三种不同的播放器(native/mpv/vlc)应对这三种场景。

0. 源起

0.1 从树莓派进化到Apple TV

去年(2022年),由于疫情,我有了很多居家办公的机会,居家办公时少不了摸鱼看剧/电影。因为我有两台显示器,一台用来办公,一台作为电视显示器,每一次看剧我都要拔下笔记本电脑,插到另一台显示器上看剧,很不方便,有时候还很容易错过工作消息,刚好手头一台树莓派4B,于是接上硬盘盒,安装上了kodi,这个树莓派就成为了我的第一个电视盒子,为了方便遥控,我还特地买了一个飞鼠,配合kodi,当时觉得还不错,只是树莓派的解码能力实在太低,解码4k非常卡顿,基本不可用。

我又买了一个小型迷你电脑作为电视盒子,但是遥控的问题又来了,我的遥控器是一个飞鼠,有一个小型键盘,用这个键盘输入特别麻烦,安装的是Ubuntu系统,经常出问题,不是kodi假死就是系统假死,还有要求输入密码,升级之类的,有时候想看个电影要折腾一番,心情没了,有时候看到一半要折腾一番,心情没了,于是想买个专业的电视盒子。这时候Apple TV 4k恰好发布,我想都没想,入手了,不得不说Apple TV配合Infuse看电影刷剧非常舒服。

IMG_1115
我的第一个「电视盒子」

0.2 看电影刷剧很爽,看足球很麻烦

上面说道,2022年我有很多机会看电影电视剧,但是到下半年,电影电视剧已经不能给我带来新鲜感了,也不能说是剧荒,更像是「电子阳痿」的表现,而且心情也被防控搞得很压抑,这时候刷到了夏奇拉的南非世界杯主题曲《waka waka》和推广曲《旗开得胜》,这两首歌真的很欢快很有氛围,压抑的心情一下舒展了,看到里面的人自由自在的舞动歌唱,瞬间羡慕起这种气氛,原来恰好世界杯就要举办了,我便开始期待世界杯的来临,我本不是球迷,我那时对足球世界的了解仅限于高中时座位旁边几位同学的口中,我高中时期是13-16年,那时候梅西和C罗正值职业巅峰期,bbc组合和msn组合在西甲和欧冠赛场的争夺给了我周围的同学很多话题,我也耳濡目染。到了大学,我就再也没有关注过足球世界。

话说回来,我发现在Apple TV上观看世界杯赛事还是真是件麻烦事,在世界杯上观看世界杯赛事主要有两个渠道,一个是CCTV-5一个是咪咕视频,CCTV-5可以通过IPTV观看,但是大部分IPTV源都很差,非常卡顿,根本看不了,而咪咕视频不支持通过AirPlay投屏,只支持DLNA投屏,于是又在Apple TV上安装了kodi,kodi并没有上架App Store,只能通过Xcode侧载的方式安装,由于是开发者证书,还得每7天重新安装一次,那个时候我萌生了开发一个DLNA投屏软件的想法。

1. 开始行动

随着安装kodi的次数越来越多,我开发软件的想法越来越强烈,希望能一次性解决投屏的问题。为了了解其他与我有同样困扰的用户,我在V2EX也发起了一个问答。从那天开始,我也开始了行动。

image-20230709152001652

2. 开发故事

2.1 初出茅庐

我本是一个Java后端程序员,因为也是开发老油条了,我没打算先学习Swift或者iOS开发再写程序,而是直接新建文件夹开始项目,除了一些特性比如Swift协议,泛型,扩展让我很不习惯外,Swift语言和Java大部分都是相通的,当然,两者的编码风格也是不同的,作为Java程序员我很自然的就用Java风格来写这个程序,一个多月后,第一个版本开发出来了,上架了App Store,在V2EX首发,我很高兴的告诉了其他同样有这个需求的用户,送出了一些兑换码和testfilght邀请他们测试。当天就有十几个用户购买,让我很受激励。

image-20230709164815705

2.2 继续完善

这个软件本来开发设计出来只是为了用咪咕投屏看球赛而已,所以只测试了一些基本的视频软件,由于各方的对DLNA协议(DLNA只是一个标准)的实现不同,所以兼容性并不强,很多软件投不了,随着用户越来越多,他们通过邮件,私信和反馈群给了我各种宝贵意见和建议,我最终准备重构一个大版本,几乎花了一个多月,重写了几乎所有代码,重新设计了架构,改用了Swift的编码风格(这时候我已经爱上了Swift这个编程语言),新版本我很满意,把版本号标记为2.0,表示这是一次巨大的更新,新版也解决了大多数软件的投屏兼容性问题。

2.3 还有问题

作为一个投屏软件,我以为2.0版本已经很完善了,随后收到直播音画不同步的反馈,由于我一直用屏幕镜像来调试App,没有办法发出声音,也很少投虎牙,斗鱼直播,一直没发现这个问题,后来排查,发现是vlckit对直播的兼容性不是很好,只能想办法集成mpv播放器。mpv与vlc不同,vlc通过vlckit暴露了自己的api,但是mpv是个裸的库,通过命令的方式来调用,还好找到了一些开源项目和官方案例供参考。通过2.0版本也积累了大量经验和代码,新的架构也对集成新播放器是包容的,集成mpv播放器比我想象得快,用了大概一周时间就完成了,至此,作为一个投屏应用,这个软件已经适配了大部分场景了。

3. DLPlay VS AirPlay

大家知道,对于视频投屏,Apple平台一直有一个非常好用的解决方案:AirPlay,DLPlay相对于AirPlay有什么优势呢,我总结出了下面四点

  1. 从任何平台的 DLNA 客户端投送视频。iOS 可以投,Android 可以投,Windows 也可以投。
  2. 支持视频格式多。相比于 AirPlay ,DLPlay 集成了三个播放器,几乎可以播放任何格式的视频。
  3. 针对投屏个各个场景优化。比如针对 NAS 场景优化的 VLC 播放器,拥有切换音轨,字幕轨道,倍速播放等高级功能,针对直播场景我们集成了对直播兼容性更好的 MPV 播放器。
  4. 无需保持在投屏界面。AirPlay 投屏时,投屏客户端必须保持在投屏界面,一旦切换到其他媒体,投屏也被切换,但使用 DLPlay 不会,投屏时,你可以随意切换到其他软件。