Vonage Video框架解析(一)—— 应用中添加一个实时视
版本记录
版本号 | 时间 |
---|---|
V1.0 | 2021.05.19 星期三 |
前言
Vonage Video
框架是提供直播流服务的一个平台,接下来这几篇就主要对这个框架进行介绍和讲解。
开始
首先看下主要内容:
开始使用
Vonage Video API
,并将实时视频流添加到您的iOS应用。内容来自翻译。
接着看下写作环境:
Swift 5, iOS 14, Xcode 12
下面就是正文啦。
现场直播体验,例如由Vonage Video API
提供支持的体验,涵盖了从课堂到音乐会再到咨询的所有内容。 但是这些东西有什么共同点? 没错 —— 缺茶。 是时候有人构建了一个用于主持虚拟茶话会的应用了。 在本教程中,您将构建一个双向直播应用程序,与朋友一起举办虚拟茶话会。 多么令人愉快!
当然,构建实时流服务器和关联的API并非易事。 幸运的是,已经有一些直播平台已经为您完成了这项工作。 其中之一就是Vonage
的Video API
。
在您的应用程序中使用此API
时,您将了解WebRTC,HLS
和RTMP
的含义以及如何:
- 创建并使用
Vonage Video API
帐户。 - 创建一个直播会话
session
。 - 将相机和麦克风发布到会话中。
- 订阅并显示会话中其他用户摄像机的视频。
现在开始了。
Vonage Video API
提供了一个称为OpenTok
的SDK
,可通过CocoaPods
安装。 它为框架创建一个单独的项目,并将其与主项目进行分组以在workspace
中使用。
入门项目已预安装OpenTok
。 打开TeaParty.xcworkspace
来访问启动项目。
代码和storyboard
已经提供了该应用程序的界面。 由于您将使用相机和麦克风,因此它们的权限说明已在Info.plist
中预定义。
构建并运行。 您会在屏幕中央看到一个大按钮,Enter Lounge
:
![](https://img.haomeiwen.com/i3691932/8b31567d598a28bb.png)
您可以在休息室(lounge)
与朋友一起直播。 点击Enter Lounge
按钮:
![](https://img.haomeiwen.com/i3691932/e3510d0e21662397.png)
轻微问题 —— 完全是黑色,没有任何视频流的迹象!您的任务是添加实时流功能。
Livestreaming Technologies
Vonage Video API
允许多达3,000
个并发连接之间的实时通信。它使用称为WebRTC
的开源多平台框架。
对于WebRTC
不够的情况(例如非交互式广播)或您需要超过3,000
个连接的情况,Vonage
提供了以下替代技术:
-
HTTP Live Streaming(HLS):一种传统的自适应比特率广播技术,使用
CDN
(内容交付网络)以高延迟(大约15
到20
秒)交付内容。 -
Real-Time Messaging Protocol (RTMP):一种延迟约五秒钟的广播技术,可将内容推送到
Facebook
或YouTube Live
等社交媒体平台。
由于您不打算举办3001
人的茶话会,因此您无需担心这些其他广播技术 —— 或购买大量的茶!
Creating Your Vonage Video API Account and Project
打开StreamingViewController.swift
,您会在顶部注意到三个空属性:apiKey,sessionId
和token
。您需要这些凭据才能通过Vonage Video API
进行身份验证。
通过在Vonage
网站上注册signing up一个免费帐户来检索这些内容。
注册,登录并输入帐户名后,您将看到Vonage Video API
帐户门户。这有很多用途,包括:
- 创建直播项目。
- 注册服务器回调URL。
- 配置视频的云存储。
- 提供用于直播会话的分析和调试工具。
- 设置帐单。
- 提供开发人员文档的链接。
Vonage Video API
是一项付费服务,但是它提供了免费的信用额,可以帮助您入门。
首先从左侧边栏中选择Create Project
:
![](https://img.haomeiwen.com/i3691932/aefc314d20b4aa40.png)
接下来,选择Vonage Video API
部分下方的Create Custom Project
:
![](https://img.haomeiwen.com/i3691932/f8bcabc5ad3c2f86.png)
然后,添加一个project name
并选择VP8
作为首选编解码器:
![](https://img.haomeiwen.com/i3691932/2659c647921103a7.png)
在流式传输视频时,编解码器会对摄像机的视频输出进行编码,以将其输出到整个网络,然后对视频进行解码,以将其显示在设备的屏幕上。 Vonage
提供了两种编解码器:
-
VP8:此编解码器在设备的内存中作为软件运行,并且在较低的比特率下运行良好。在
WebRTC
的背景下,这是一种成熟的视频编解码器。最好进行具有许多连接的大型会话。 -
H.264:视设备而定,它可以作为软件和硬件编解码器使用。在硬件上运行时,它比
VP8
消耗更少的CPU
功率。在WebRTC
的背景下,这是一个相对较新的编解码器。这意味着每个设备可能具有不同的实现方式,从而导致质量变化。它在处理较低的比特率或大型会话方面不如VP8
。
在这种情况下,您会选择VP8
,因为您可能会在生产应用中使用VP8
,该应用可举办大型茶话会,并且来自不同设备的连接也更多(蛋糕也更多)。
单击Create
,然后复制生成的API key
:
![](https://img.haomeiwen.com/i3691932/335050a87837e8f9.png)
在您的Xcode
项目中,打开StreamingViewController.swift
并将您的API key
粘贴到apiKey
中:
![](https://img.haomeiwen.com/i3691932/58b26dc0098e8703.png)
1. Creating a Session
现在,回到Vonage Video API
帐户门户,单击View Project
,然后向下滚动到Project Tools
部分:
![](https://img.haomeiwen.com/i3691932/50c1f9819316e3d8.png)
您将在此处创建session ID and token
。正如网站所解释的,session ID
标识唯一的OpenTok
会话。您可以将Tea Party
应用程序中的休息室视为一个session
。
创建会话时,您可以使用Media Mode
来指定会话中的客户端如何发送其视频流。有两种选择:
- Relayed:客户端之间直接在对等端之间直接发送流,而不是使用服务器。由于网络跳数减少,因此可以减少延迟并提高质量,但是如果设备位于防火墙之后,则无法使用。中继会话仅支持连接到该会话的两个客户端。
-
Routed:客户端通过
OpenTok Media Router
相互发送流,该路由器是处理流分配到多个设备的服务器。这提供了诸如记录流的能力等优点。设备出现连接问题时的音频后备;多方会话中的带宽减少等。
对于此应用程序,选择Routed
作为Media Mode
,然后单击Create Session ID
。与使用API key
一样,将给定的session ID
复制粘贴到StreamingViewController.swift
中的sessionId
中。
2. Generating the Token
token
可验证每个用户的身份。在生产应用程序中,每个用户将拥有由服务器生成的自己的唯一token
。但是,为简单起见,您将为该项目的每个用户使用相同的令牌。
每个token
都有一个与之关联的角色role
,该角色确定连接到会话的客户端的功能。有三个可能的角色:
- Subscriber - 订阅者:连接到会话并接收其他客户端的流。客户无法将自己的摄像机发布到会话中。
- Subscriber - 发布者:接收流并将其自己的摄像机发布到会话中。
- Subscriber - 主持人:能够强制其他客户端从会话断开连接和/或停止向会话发布。
在帐户门户的token
生成部分中,粘贴您的session ID
,然后将Role
设置为Publisher
,并将Expiration Time
设置为30 days
。在这种情况下,Connection Data
字段应为空。在正式版应用中,您通常会使用它来传递用户ID,名称或其他数据来描述用户。
接下来,单击Generate token
,然后将结果复制粘贴到StreamingViewController.swift
中的token
中:
![](https://img.haomeiwen.com/i3691932/2a66b6301b7a087d.png)
现在,您具有身份验证所需的凭据,并开始使用Vonage Video API
流式传输您的虚拟茶话会。 现在该把水壶了!
Connecting to the Session
开始直播之前,您需要连接到会话。
为此,请转到StreamingViewController.swift
。 在token
属性下,添加以下内容:
private var session: OTSession?
OpenTok
使用OTSession
代表您的会话。 在这里,您将对会话对象保持强引用。
现在,要连接到会话,请在leave()
下面添加以下代码:
private func connectToSession() {
// 1
session = OTSession(
apiKey: apiKey,
sessionId: sessionId,
delegate: self
)
// 2
var error: OTError?
session?.connect(withToken: token, error: &error)
// 3
if let error = error {
print("An error occurred connecting to the session", error)
}
}
这是正在发生的事情:
- 1) 使用您的
apiKey
和sessionId
初始化OTSession
。 将委托设置为StreamingViewController
。 设置委托将导致编译器错误,因为您尚未使StreamingViewController
符合OTSessionDelegate
。 - 2) 使用
token
连接到会话,并传递对OTError
的引用以捕获任何同步错误。OTError
定义特定于OpenTok iOS SDK
的错误。 - 3) 如果确实发生同步错误,则将其打印到控制台。
由于您将OTSession
的委托设置为self
,因此您需要实现OTSessionDelegate
协议。 在StreamingViewController.swift
的底部添加以下扩展名:
// MARK: - OTSessionDelegate
extension StreamingViewController: OTSessionDelegate {
// 1
func sessionDidConnect(_ session: OTSession) {
print("The client connected to the session.")
}
// 2
func sessionDidDisconnect(_ session: OTSession) {
print("The client disconnected from the session.")
}
// 3
func session(_ session: OTSession, didFailWithError error: OTError) {
print("The client failed to connect to the session: \(error).")
}
// 4
func session(_ session: OTSession, streamCreated stream: OTStream) {
print("A stream was created in the session.")
}
// 5
func session(_ session: OTSession, streamDestroyed stream: OTStream) {
print("A stream was destroyed in the session.")
}
}
此代码处理与会话有关的事件。 具体而言,在:
- 1) 您已成功连接到会话。
- 2) 您已成功从会话断开连接。
- 3) 尝试连接到会话时发生异步错误。
- 4) 其他人将他们的视频流发布到会话中。 这提供了一个
OTStream
,表示它们的流。 - 5) 其他人停止将其视频流发布到会话中。
您几乎可以尝试使用您的应用了,但是您仍然需要实际连接到该会话。
为此,请在viewDidLoad()
的底部添加以下内容:
connectToSession()
构建并运行,然后进入休息室。 屏幕仍然是黑色的,但是您会在控制台中注意到已成功连接到会话:
![](https://img.haomeiwen.com/i3691932/0169f23c11fc8984.png)
Publishing the Camera
现在您可以连接到该会话了,该发布相机和麦克风了。
在connectToSession()
下面添加以下内容:
private func publishCamera() {
// 1
guard let publisher = OTPublisher(delegate: nil) else {
return
}
// 2
var error: OTError?
session?.publish(publisher, error: &error)
// 3
if let error = error {
print("An error occurred when trying to publish", error)
return
}
// 4
guard let publisherView = publisher.view else {
return
}
// 5
let screenBounds = UIScreen.main.bounds
let viewWidth: CGFloat = 150
let viewHeight: CGFloat = 267
let margin: CGFloat = 20
publisherView.frame = CGRect(
x: screenBounds.width - viewWidth - margin,
y: screenBounds.height - viewHeight - margin,
width: viewWidth,
height: viewHeight
)
view.addSubview(publisherView)
}
这是此代码的作用:
- 1) 初始化
OTPublisher
对象。该对象可以从设备的麦克风和摄像头捕获音频-视频流。 - 2) 将音频视频流发布到会话,并传递对
OTError
的引用以捕获任何同步错误。 - 3) 如果确实发生同步错误,则将其打印到控制台。
- 4) 从
publisher
处获取视图,其中包含从设备的摄像头捕获的视频。由于模拟器没有摄像头,因此它将替代默认视频。 - 5) 将视图作为子视图添加到
StreamingViewController
的角落。
注意:您可以在此处将
OTPublisher
的委托设置为nil
,但是您可以实现OTPublisherDelegate
来处理与发布者有关的事件,例如异步错误。您也可以使用它将设置传递到OTPublisher
,以调整摄像机分辨率,音频后备设置,视频缩放行为等。
接下来,要在建立连接后在sessionDidConnect(_ :)
内发布摄像机,请在print
后添加以下内容:
publishCamera()
构建并运行,您将在右下角看到模拟器的默认茶壶旋转视频。 多么贴切! 您现在正在该会话中进行直播。 如果您要在设备上运行此代码,则会看到相机的视频。 恭喜,您现在有半场茶话会!
![](https://img.haomeiwen.com/i3691932/70a929df3f15e784.png)
Subscribing to an Incoming Stream
您需要先订阅它,然后才能看到来自发布该会话的其他客户端的视频流。
在token
属性下添加以下内容:
private var subscriberView: UIView?
这将对保存其他客户端视频流的视图保持强引用。
现在,在publishCamera()
下面添加以下代码:
private func subscribe(to stream: OTStream) {
// 1
guard let subscriber = OTSubscriber(stream: stream, delegate: nil) else {
return
}
// 2
var error: OTError?
session?.subscribe(subscriber, error: &error)
// 3
if let error = error {
print("An error occurred when subscribing to the stream", error)
return
}
// 4
guard let subscriberView = subscriber.view else {
return
}
// 5
self.subscriberView = subscriberView
subscriberView.frame = UIScreen.main.bounds
view.insertSubview(subscriberView, at: 0)
}
这是这段代码中发生的事情:
- 1) 使用
OTStream
创建OTSubscriber
,它表示另一个设备的视频流。 - 2) 订阅此流,并传递对
OTError
的引用以捕获任何同步错误。 - 3) 如果确实发生同步错误,则将其打印到控制台。
- 4) 从订阅者那里获取视图。 此视图包含视频流的视频。
- 5) 保留对该视图的引用,并将该视图插入
StreamingViewController
的子视图下方。 此视图的尺寸与屏幕边界的尺寸相同,并且会填满整个屏幕。
注意:您还可以在此处将
OTSubscriber
的委托设置为nil
。 实现OTSubscriberDelegate
协议使您能够处理与订户有关的事件。
最后,在session(_:streamCreated:)
的底部,添加:
subscribe(to: stream)
这样一来,无论何时创建流,您都可以订阅。
要在您的应用中提供双向直播,您需要与其他设备或另一个iOS模拟器的朋友。 在这种情况下,请使用iPhone 12 Pro
模拟器进行构建和运行。 然后,停止运行该应用程序,选择iPhone 12
模拟器并重新构建并运行。
现在,在iPhone 12 Pro
模拟器上,点击TeaParty app
再次将其打开,您将有两个模拟器同时运行。 在两个模拟器上进入休息室,您会在每个设备上看到两个旋转的茶壶:
![](https://img.haomeiwen.com/i3691932/9ba72f57ad7a61ee.png)
这两个模拟器都举行了虚拟茶话会 —— 他们都将视频发布到会话中,并订阅彼此的视频流!
Disconnecting From the Session
按Leave
按钮,您会发现该应用程序未调用sessionDidDisconnect()
。 那是因为会话仍处于连接状态。 退出会话时,请务必断开其连接,这一点很重要。
在StreamingViewController.swift
中,用以下内容替换Leave()
的主体:
var error: OTError?
session?.disconnect(&error)
if let error = error {
print("An error occurred disconnecting from the session", error)
} else {
navigationController?.popViewController(animated: true)
}
这将使您与会话断开连接,当您单击Leave
按钮时,会话会自动取消发布流。 如果断开连接时没有发生同步错误,则它将从导航堆栈中弹出当前视图控制器。
在session(_:streamDestroyed :)
内部,在底部添加以下代码:
subscriberView?.removeFromSuperview()
当订阅者停止在会话中发布其流时,这将从屏幕上删除订阅者的视图。
现在,构建并运行并仔细检查离开和进入休息室的工作是否如您所愿。
就这样,您现在已经拥有一个功能齐全的应用程序,可以将其安装到真实的设备上,以便您可以与朋友进行虚拟茶话会!
在本教程中,您学到了很多有关如何创建直播事件的知识。您必须了解WebRTC,HLS
和RTMP
等重要术语,设置Vonage Video API
帐户,并使用Vonage Video API
构建了双向双向视频流应用程序。
但是,该项目只是简化了Vonage Video API
功能的表面。还有很多东西要学习,包括:
- Archiving:记录,保存和检索会话。
- Signaling:在连接到会话的客户端之间发送文本和数据。
-
Server integration:处理客户端和服务器
SDK
之间的交互,以自动分发token
,会话ID等。 -
Broadcasts:同时设置
HLS,RTMP
和WebRTC
广播。 -
SIP Interconnect:将
VoIP call
中的音频添加到会话中。 - Voice-only:设置纯语音会话。
如果您想了解有关Vonage Video API
功能的更多信息,请查看其 developer guides。
另外,请确保您在我们的Video Streaming Tutorial for iOS中阅读了使用Apple框架的iOS视频流。
后记
本篇主要讲述了基于
Vonage Video
的应用中添加一个实时视频流的简单实现,感兴趣的给个赞或者关注~~~
![](https://img.haomeiwen.com/i3691932/7a0763a9305e45f8.png)