如何在 Sinch 中禁用视频
How to disable video in Sinch
我正在使用 Sinch 实现视频聊天,但我找不到在通话开始后禁用传出视频的方法。
这在某处记录了吗?
如果 SDK 不支持它,是否有办法(即使是 hackish 的)"intercept" 视频流并阻止它被发送。
显然在 SDK 中没有官方方法可以做到这一点,但这里有一个可以按预期工作的 hack。
长话短说,通过一些运行时间 "magic" 我们可以拦截 Sinch 发起的 AVCaptureSessoin
并控制它。
方法如下:
extension AVCaptureSession {
public override class func initialize() {
struct Static {
static var token: dispatch_once_t = 0
}
// make sure this isn't a subclass
if self !== AVCaptureSession.self {
return
}
dispatch_once(&Static.token) {
let originalSelector = #selector(AVCaptureSession.init)
let swizzledSelector = #selector(AVCaptureSession.hd_init)
let originalMethod = class_getInstanceMethod(self, originalSelector)
let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
if didAddMethod {
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
}
@nonobjc static var hd_currentSession: AVCaptureSession? = nil
func hd_init() {
hd_init() // at runtime this is the original `init` implementation
AVCaptureSession.hd_currentSession = self
}
}
简要说明:第一部分只是两种方法的基本运行时调配,与此实现无关。
也就是说,我们正在用我们自己的 AVCaptureSession.hd_init
替换 AVCaptureSession.init
的实现(hd
只是避免方法名称潜在冲突的任何前缀)。
NOTE
In hd_init
we're calling hd_init
. This is a bit mind-bending, but it's how swizzling works: at the time we execute that piece of code hd_init
has been replaced by the original init
, so we're actually calling the original implementation, which is what we want.
我们对 init
的自定义实现只是为了存储对实例的静态引用,我们将其称为 hd_currentSession
。
大功告成!
现在我们可以从应用程序的任何位置获取对当前 AVCaptureSession
的引用并随意停止/启动它。
例如
func toggleVideo() {
if let session = AVCapture.hd_currentSession {
if session.running {
session.stopRunning()
} else {
session.startRunning()
}
}
}
在 Sinch 视频流开始后的任何时候,我们都可以简单地调用 toggleVideo()
CAVEAT
Stopping the capture session will cause the video to "freeze" to the last frame. I haven't worked around this issue on iOS side, but I've noticed that on the Javascript API you get a "muted"
event on the video MediaTrack
. Given this, you can - for example - hide the video on the other client's side using the onmuted
event.
我正在使用 Sinch 实现视频聊天,但我找不到在通话开始后禁用传出视频的方法。
这在某处记录了吗?
如果 SDK 不支持它,是否有办法(即使是 hackish 的)"intercept" 视频流并阻止它被发送。
显然在 SDK 中没有官方方法可以做到这一点,但这里有一个可以按预期工作的 hack。
长话短说,通过一些运行时间 "magic" 我们可以拦截 Sinch 发起的 AVCaptureSessoin
并控制它。
方法如下:
extension AVCaptureSession {
public override class func initialize() {
struct Static {
static var token: dispatch_once_t = 0
}
// make sure this isn't a subclass
if self !== AVCaptureSession.self {
return
}
dispatch_once(&Static.token) {
let originalSelector = #selector(AVCaptureSession.init)
let swizzledSelector = #selector(AVCaptureSession.hd_init)
let originalMethod = class_getInstanceMethod(self, originalSelector)
let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
if didAddMethod {
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
}
@nonobjc static var hd_currentSession: AVCaptureSession? = nil
func hd_init() {
hd_init() // at runtime this is the original `init` implementation
AVCaptureSession.hd_currentSession = self
}
}
简要说明:第一部分只是两种方法的基本运行时调配,与此实现无关。
也就是说,我们正在用我们自己的 AVCaptureSession.hd_init
替换 AVCaptureSession.init
的实现(hd
只是避免方法名称潜在冲突的任何前缀)。
NOTE
In
hd_init
we're callinghd_init
. This is a bit mind-bending, but it's how swizzling works: at the time we execute that piece of codehd_init
has been replaced by the originalinit
, so we're actually calling the original implementation, which is what we want.
我们对 init
的自定义实现只是为了存储对实例的静态引用,我们将其称为 hd_currentSession
。
大功告成!
现在我们可以从应用程序的任何位置获取对当前 AVCaptureSession
的引用并随意停止/启动它。
例如
func toggleVideo() {
if let session = AVCapture.hd_currentSession {
if session.running {
session.stopRunning()
} else {
session.startRunning()
}
}
}
在 Sinch 视频流开始后的任何时候,我们都可以简单地调用 toggleVideo()
CAVEAT
Stopping the capture session will cause the video to "freeze" to the last frame. I haven't worked around this issue on iOS side, but I've noticed that on the Javascript API you get a
"muted"
event on the videoMediaTrack
. Given this, you can - for example - hide the video on the other client's side using theonmuted
event.