如何从充当服务器的 iPhone 流式传输视频?
Posted
技术标签:
【中文标题】如何从充当服务器的 iPhone 流式传输视频?【英文标题】:How do I stream video from iPhone acting as a server? 【发布时间】:2014-01-03 01:07:12 【问题描述】:我正在开发一款适用于 ios 的应用,其中一部 iPhone 必须将其相机记录实时流式传输到另一部 iPhone(为简单起见,两者都在同一个 Wi-Fi 网络中)。 流应该在没有物理互连的情况下工作(例如,用于将流路由到客户端的服务器)。事实上,录制的 iPhone 应该是服务器,它为其他 iPhone(或网络中的更多其他 iOS 设备)提供实时流。 所以,我需要做的是:
-
从相机中获取实时图片
根据需要处理此数据
逐帧发送到连接的客户端 (TCP?)
在客户端接收帧并实时显示
我所拥有的和我坚持的:
我已经解决了问题1。我使用AVCaptureSession
,它不断返回CMSampleBufferRef
(找到here)。
我还不确定我需要用 CMSampleBufferRef
做什么。我确实知道如何将其转换为 CGImage
或 UIImage
(感谢 Benjamin Loulier 的精彩博文2),但我不知道我具体需要发送什么以及是否需要以某种方式对帧进行编码.
正如@jab 在上述链接答案 (this) 中所提到的,可以将这些样本写入具有一个或多个 AVAssetWriter
的文件。但话又说回来,他说那些 5 秒的视频 sn-ps 将被上传到一个服务器,该服务器从中制作一个可流式电影文件(然后该电影可以通过HTTP Live Streaming
流式传输到 iOS 设备@我想)。
正如我已经指出的,我的应用程序(即视频捕获“服务器”设备)有一个或多个客户端连接到它,并且需要实时向它们发送视频帧。 我想到的一个想法是使用简单的TCP
连接,服务器以序列化 格式将每个帧发送到循环连接的客户端。更具体地说:当一个缓冲的帧成功发送到客户端时,服务器将最近的帧作为下一个发送。
现在:这是正确的想法吗?或者是否有另一种更适合此类任务的协议? 记住:我想保持简单(对我来说简单,即,这样我就不需要学习太多新的编程方面)和快速。我已经了解了一些关于 TCP 的知识,我在C
学校用它编写了服务器和客户端,所以我更愿意将我现在所掌握的知识应用到这个项目中......
最后但同样重要的是,接收客户端:
我想,如果我真的要使用TCP
连接,那么在客户端我从服务器接收帧接帧,将读取的字节包转换为使用的格式(CMSampleBuffer
,CGImage
, UIImage
) 并将其显示在 CALayer
或 UIImageView
上,对吗?只需不断更新该图像视图即可获得电影的效果。
请给我一些关于如何实现这个目标的想法。这非常重要,因为它是我学校毕业项目的一部分......任何示例代码也很感激;-) 或者只是将我引向另一个网站、教程、***-answer 等。
如果您对此有任何疑问,请发表评论,我会更新帖子。
【问题讨论】:
你也想流式传输音频吗? @user523234 流式音频将是下一步,但不是真正必要的。无论如何,我更愿意在完成的项目中使用它:) 你对此有什么建议吗? 【参考方案1】:听起来不错?
视频帧真的很大。您将在将视频从一台设备流式传输到另一台设备时遇到带宽问题。您可以使用来自UIImage
的UIImageJPEGRepresentation
将帧压缩为JPEG
s,但这在“服务器”上的计算成本很高,并且仍然可能无法使它们小到足以流式传输。您还可以通过丢帧、对UIImage
s 进行下采样以及调整AVCaptureSession
中的设置来降低帧速率和/或分辨率。或者,您可以发送小型(5 秒)视频,这些视频在服务器上进行了硬件压缩,并且在带宽上更容易处理,但当然会在流中延迟 5 秒。
如果您需要 iOS 7,我建议您尝试MultipeerConnectivity.framework
。设置起来并不难,我相信它支持多个客户端。如果您要构建自己的网络,请绝对使用 UDP 而不是 TCP - 这是 UDP 的教科书应用程序,而且开销较低。
逐帧,只需将JPEG
s 转换为UIImage
s 并使用UIImageView
。涉及大量计算,但我相信您仍然会受到带宽而不是 CPU 的限制。如果您要发送小视频,可以使用MPMoviePlayerController
。每个视频之间可能会有一些小故障,因为它“准备”它们进行播放,这也将导致播放每个 5 秒的视频需要 5.5 秒左右。我不建议使用 HTTP Live Streaming,除非您可以在某处获得真正的服务器。或者,如果您可以/想要为 iOS 编译 ffmpeg
,您可以使用 ffmpeg
管道——输入视频并弹出单个帧。
如果您需要澄清这些问题,请告诉我。工作量很大,但相对简单。
【讨论】:
感谢您的回答。它给了我一些很好的新建议。关于第 2 点:在流中存在相关持续时间的滞后对我来说是不可能的 :( 我会看看我可以通过压缩等做些什么。 第 3 点:MultipeerConnectivity.framwork 绝对值得一看,因为它还支持发送文件并且是高级实现(不像处理 CFSocket 那样)。我刚刚在 UDP 上读过一些东西,我想我会使用它,因为从 TCP 切换并不难:) Here 是一个很好的教程,包括MultipeerConnectivity
。它在蓝牙的背景下进行了讨论,但该框架也使用了可用的 Wi-fi。
还有一个问题:我是否需要使用UIImages
(它们需要在CMSampleBufferRef
之前创建,这又要消耗CPU)?我不能发送CGImage
甚至CMSampleBuffer
吗?
你可以,但是根据定义,样本缓冲区是未压缩的。我认为您应该首先尝试用 CPU 换取带宽,但这只是一个需要测试的假设。流式传输到更多客户端将花费更多带宽,但几乎不需要 CPU。【参考方案2】:
如果您需要现成的解决方案,您可以尝试一些现成的流媒体库。我有经验的是angl streaming lib。使用 RTMP 输出到 Wowza 媒体服务器时效果很好。
【讨论】:
以上是关于如何从充当服务器的 iPhone 流式传输视频?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 iOS 设备(而不是自己的相机)流式传输 (RTMP) 视频
如何将 4K HDR 视频流式传输到 Apple TV 4K?