答案 0 :(得分:0)
显然,在SDK中没有正式的方法可以做到这一点,但这里的黑客行为符合预期。
长话短说,有一些运行时间"魔法"我们可以拦截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.init
替换AVCaptureSession.hd_init
的实现(hd
只是任何前缀,以避免方法名称的潜在冲突。)
注意强>
在
hd_init
我们正在呼叫hd_init
。这有点令人费解,但它是如何调制的:当我们执行那段代码时,hd_init
被原来的init
所取代,所以我们就这样了实际上调用原始实现,这就是我们想要的。
我们init
的自定义实现只是为了存储对实例的静态引用,我们将其称为hd_currentSession
。
我们已经完成了!
现在,从应用中的任何位置,我们都可以获得对当前AVCaptureSession
的引用,并随意停止/启动它。
例如
func toggleVideo() {
if let session = AVCapture.hd_currentSession {
if session.running {
session.stopRunning()
} else {
session.startRunning()
}
}
}
在Sinch视频流开始后的任何时间,我们只需拨打toggleVideo()
<强> CAVEAT 强>
停止捕获会话将导致视频“冻结”#34;到最后一帧。我还没有在iOS方面解决这个问题,但我注意到在Javascript API上你会在视频
"muted"
上收到MediaTrack
个事件。鉴于此,您可以 - 例如 - 使用onmuted
事件在其他客户端隐藏视频。