前提・実現したいこと
ビデオ通話になっているのを音声のみの通話に変えたい
発生している問題・エラーメッセージ
self.localStream?.removeVideoRenderer(constraints, track: 0)の部分で
カメラをオフにできると思っていたがエラーが起きてしまう
下記にエラー内容
Cannot convert value of type 'SKWMediaConstraints' to expected argument type 'SKWVideo'
該当のソースコード
Swift
1import UIKit 2import SkyWay 3 4class MediaConnectionViewController: UIViewController { 5 6 fileprivate var peer: SKWPeer? 7 fileprivate var mediaConnection: SKWMediaConnection? 8 fileprivate var localStream: SKWMediaStream? 9 fileprivate var remoteStream: SKWMediaStream? 10 11 @IBOutlet weak var myPeerIdLabel: UILabel! 12 @IBOutlet weak var targetPeerIdLabel: UILabel! 13 @IBOutlet weak var callButton: UIButton! 14 @IBOutlet weak var endCallButton: UIButton! 15 16 override func viewDidLoad() { 17 super.viewDidLoad() 18 self.setup() 19 } 20 21 override func viewWillDisappear(_ animated: Bool) { 22 super.viewWillDisappear(animated) 23 self.mediaConnection?.close() 24 self.peer?.destroy() 25 } 26 27 override func didReceiveMemoryWarning() { 28 super.didReceiveMemoryWarning() 29 // Dispose of any resources that can be recreated. 30 } 31 32 @IBAction func tapCall(){ 33 guard let peer = self.peer else{ 34 return 35 } 36 37 Util.callPeerIDSelectDialog(peer: peer, myPeerId: peer.identity) { (peerId) in 38 self.call(targetPeerId: peerId) 39 } 40 } 41 42 @IBAction func tapEndCall(){ 43 self.mediaConnection?.close() 44 self.changeConnectionStatusUI(connected: false) 45 } 46 47 func changeConnectionStatusUI(connected:Bool){ 48 if connected { 49 self.callButton.isEnabled = false 50 self.endCallButton.isEnabled = true 51 }else{ 52 self.callButton.isEnabled = true 53 self.endCallButton.isEnabled = false 54 } 55 } 56} 57 58// MARK: setup skyway 59 60extension MediaConnectionViewController{ 61 62 func setup(){ 63 64 guard let apikey = (UIApplication.shared.delegate as? AppDelegate)?.skywayAPIKey, let domain = (UIApplication.shared.delegate as? AppDelegate)?.skywayDomain else{ 65 print("Not set apikey or domain") 66 return 67 } 68 69 let option: SKWPeerOption = SKWPeerOption.init(); 70 option.key = apikey 71 option.domain = domain 72 73 //idでPeerIDの固定を可能 74 peer = SKWPeer(options: option) 75 76 if let _peer = peer{ 77 self.setupPeerCallBacks(peer: _peer) 78 self.setupStream(peer: _peer) 79 }else{ 80 print("failed to create peer setup") 81 } 82 } 83 84 func setupStream(peer:SKWPeer){ 85 SKWNavigator.initialize(peer); 86 let constraints:SKWMediaConstraints = SKWMediaConstraints() 87 self.localStream = SKWNavigator.getUserMedia(constraints) 88 self.localStream?.removeVideoRenderer(constraints, track: 0) //constraintsのところで引数のエラー 89 //self.localStream?.addVideoRenderer(self.localStreamView, track: 0) //ここを削除(コメントアウト)した 90 } 91 92 func call(targetPeerId:String){ 93 let option = SKWCallOption() 94 95 if let mediaConnection = self.peer?.call(withId: targetPeerId, stream: self.localStream, options: option){ 96 self.mediaConnection = mediaConnection 97 self.setupMediaConnectionCallbacks(mediaConnection: mediaConnection) 98 }else{ 99 print("failed to call :(targetPeerId)") 100 } 101 } 102} 103 104// MARK: skyway callbacks 105 106extension MediaConnectionViewController{ 107 108 func setupPeerCallBacks(peer:SKWPeer){ 109 110 // MARK: PEER_EVENT_ERROR 111 peer.on(SKWPeerEventEnum.PEER_EVENT_ERROR, callback:{ (obj) -> Void in 112 if let error = obj as? SKWPeerError{ 113 print("(error)") 114 } 115 }) 116 117 // MARK: PEER_EVENT_OPEN 118 peer.on(SKWPeerEventEnum.PEER_EVENT_OPEN,callback:{ (obj) -> Void in 119 if let peerId = obj as? String{ 120 DispatchQueue.main.async { 121 self.myPeerIdLabel.text = peerId 122 self.myPeerIdLabel.textColor = UIColor.darkGray 123 } 124 print("your peerId: (peerId)") 125 } 126 }) 127 128 // MARK: PEER_EVENT_CONNECTION 129 peer.on(SKWPeerEventEnum.PEER_EVENT_CALL, callback: { (obj) -> Void in 130 if let connection = obj as? SKWMediaConnection{ 131 self.setupMediaConnectionCallbacks(mediaConnection: connection) 132 self.mediaConnection = connection 133 connection.answer(self.localStream) 134 } 135 }) 136 } 137 138 func setupMediaConnectionCallbacks(mediaConnection:SKWMediaConnection){ 139 140 // MARK: MEDIACONNECTION_EVENT_STREAM 141 mediaConnection.on(SKWMediaConnectionEventEnum.MEDIACONNECTION_EVENT_STREAM, callback: { (obj) -> Void in 142 if let msStream = obj as? SKWMediaStream{ 143 self.remoteStream = msStream 144 DispatchQueue.main.async { 145 self.targetPeerIdLabel.text = self.remoteStream?.peerId 146 self.targetPeerIdLabel.textColor = UIColor.darkGray 147 } 148 self.changeConnectionStatusUI(connected: true) 149 } 150 }) 151 152 // MARK: MEDIACONNECTION_EVENT_CLOSE 153 mediaConnection.on(SKWMediaConnectionEventEnum.MEDIACONNECTION_EVENT_CLOSE, callback: { (obj) -> Void in 154 if let _ = obj as? SKWMediaConnection{ 155 DispatchQueue.main.async { 156 self.remoteStream = nil 157 self.mediaConnection = nil 158 } 159 self.changeConnectionStatusUI(connected: false) 160 } 161 }) 162 } 163}
試したこと
Storyboad上でViewを消したので画面に映像は流れませんが、
利用する場合にカメラの使用を聞かれてしまいます。
ここをマイクの使用のみの通話に変えたいです。
補足情報(FW/ツールのバージョンなど)
xcode 12
プログラムソース skyway swift tutorialより
Info.plistにNSCameraUsageDescriptionを記述していませんか?また、AVCaptureDevice.requestAccess(for: .video) みたいなコードで権限を取得しようとしていませんか?
ご回答ありがとうございます。
はい、おっしゃる通りでInfo.plistに記入しています。
skywayさんのチュートリアルのプログラムのままだと
カメラを利用しているみたいで
NSCameraUsageDescriptionが無い状態で実行すると以下のエラーが表示されます。
This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSCameraUsageDescription key with a string value explaining to the user how the app uses this data.
これを避けたくて通話方法を音声のみに変更する方法が知れれば幸いなのですが,,,
あなたの回答
tips
プレビュー