libjingle iOS: 不要请求麦克风许可
libjingle iOS: Don't ask for mic permission
我正在开发 WebRTC iOS 应用程序以从网络摄像头接收 video/audio。
只有网络摄像头发送视频和音频,移动设备不发送任何内容。
我正在使用来自 CocoaPods (v11177.2.0) 的 libjingle_peerconnection 库。
一切正常,我可以正常接收视频和音频,但设备权限有问题。我第一次使用该应用程序时,当我想从网络摄像头接收视频时,iOS 应用程序要求获得麦克风许可。
这很重要,因为设备不发送音频,而我的客户说 "Why the app is asking for the microphone??"
这很奇怪,因为对于相机,应用程序不需要任何权限。
我已经检查了 SDP,似乎都可以(提供和回答)。
这是我创建对等连接对象的方式没有附加流:
RTCICEServer *stunServer = [[RTCICEServer alloc]initWithURI:[NSURL URLWithString:@"stun:stun.l.google.com:19302"] username:@"" password:@""];
NSMutableArray *iceServers = [NSMutableArray arrayWithObject:stunServer];
RTCPeerConnectionFactory *factory = [[RTCPeerConnectionFactory alloc]init];
NSArray *peerConnectionConstraints = @[[[RTCPair alloc] initWithKey:@"DtlsSrtpKeyAgreement" value:@"true"]];
RTCMediaConstraints *peerConnectionConstraints = [[RTCMediaConstraints alloc]initWithMandatoryConstraints:peerConnectionConstraints optionalConstraints:nil];
RTCPeerConnection *pConnection = [factory peerConnectionWithICEServers:iceServers constraints:peerConnectionConstraints delegate:self];
NSArray *sdpConstraints = @[[[RTCPair alloc] initWithKey:@"OfferToReceiveAudio" value:@"true"],
[[RTCPair alloc] initWithKey:@"OfferToReceiveVideo" value:@"true"]];
RTCMediaConstraints* sdpConstraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:sdpConstraints optionalConstraints:nil];
[pConnection createOfferWithDelegate:self constraints:sdpConstraints];
这是生成的 SDP 报价:
v=0
o=- 6528383367639880158 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS
m=audio 9 RTP/SAVPF 111 103 104 9 102 0 8 127 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:0QOsaBCKhCBBcHz5
a=ice-pwd:/y5snrrO3Qmq37m2aejRbK1E
a=mid:audio
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=recvonly
a=rtcp-mux
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:x1lfnVdo9lCRa9ykH6759WhY1SnI+dbLjKNbkTl+
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10; useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:102 ILBC/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:127 red/8000
a=rtpmap:126 telephone-event/8000
a=maxptime:60
m=video 9 RTP/SAVPF 100 101 116 117 96
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:0QOsaBCKhCBBcHz5
a=ice-pwd:/y5snrrO3Qmq37m2aejRbK1E
a=mid:video
a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:4 urn:3gpp:video-orientation
a=recvonly
a=rtcp-mux
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:x1lfnVdo9lCRa9ykH6759WhY1SnI+dbLjKNbkTl+
a=rtpmap:100 VP8/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=rtpmap:101 VP9/90000
a=rtcp-fb:101 ccm fir
a=rtcp-fb:101 nack
a=rtcp-fb:101 nack pli
a=rtcp-fb:101 goog-remb
a=rtcp-fb:101 transport-cc
a=rtpmap:116 red/90000
a=rtpmap:117 ulpfec/90000
a=rtpmap:96 rtx/90000
a=fmtp:96 apt=100
这是来自网络摄像头的 SDP 回答:
v=0
o=- 3699612909 3699612909 IN IP4 0.0.0.0
s=-
c=IN IP4 0.0.0.0
t=0 0
a=msid-semantic: WMS
a=group:BUNDLE audio video
m=audio 1 RTP/SAVPF 111 0
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=mid:audio
a=rtcp:9 IN IP4 0.0.0.0
a=rtpmap:111 opus/48000/2
a=rtpmap:0 PCMU/8000
a=sendonly
a=rtcp-mux
a=fmtp:111 minptime=10; useinbandfec=1
a=maxptime:60
a=ssrc:3192391506 cname:user604422501@host-6a96398f
a=ice-ufrag:r2kq
a=ice-pwd:6VJu/y0Kbc4iUDQB/1ZrnE
a=fingerprint:sha-256 57:26:29:A5:DD:CD:42:74:C9:A3:BB:C4:67:D1:1C:24:E9:4B:4C:86:6F:93:32:03:52:6B:2B:77:B3:C4:E8:88
m=video 1 RTP/SAVPF 100
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=mid:video
a=rtcp:9 IN IP4 0.0.0.0
a=rtpmap:100 VP8/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 goog-remb
a=sendonly
a=rtcp-mux
a=ssrc:455461391 cname:user604422501@host-6a96398f
a=ice-ufrag:r2kq
a=ice-pwd:6VJu/y0Kbc4iUDQB/1ZrnE
a=fingerprint:sha-256 57:26:29:A5:DD:CD:42:74:C9:A3:BB:C4:67:D1:1C:24:E9:4B:4C:86:6F:93:32:03:52:6B:2B:77:B3:C4:E8:88
如您所见,在 SDP 报价中,两种媒体(音频和视频)都是 "receiveOnly" 并且在 SDP 答案中 "sendOnly",所以我认为没有与SDP.
有人知道为什么要请求麦克风许可吗?如果您需要更多信息,请告诉我。
谢谢!
我没有和你的 code/libraries 合作过,对于那部分我无能为力,但是从 Apple documentation 我们可以读到:
The first time your app’s audio session attempts to use an audio input
route while using a category that enables recording, the system
automatically prompts the user for permission. You can explicitly ask
earlier by calling the requestRecordPermission(_:) method. Until
the user grants your app permission to record, your app can record
only silence.
这可能会给你一些线索,某处(可能在 libjingle 中)正在访问 iOS Audio Session
并且可能是什么触发了麦克风权限。
给你。您需要像
这样创建本地流
-(RTCMediaStream*)createLocalMediaStream
{
RTCMediaStream* localStream = [_factory mediaStreamWithLabel:@"ARDAMS"];
if(![[ReveSingleton sharedManager].localCallControl isEqualToNumber:@251])
{
RTCVideoTrack* localVideoTrack;
localVideoTrack = [self createLocalVideoTrack];
if (localVideoTrack) {
[localStream addVideoTrack:localVideoTrack];
[_delegate appClient:self didReceiveLocalVideoTrack:localVideoTrack];
}
}
[localStream addAudioTrack:[_factory audioTrackWithID:@"ARDAMSa0"]];
if (_isSpeakerEnabled)
[self enableSpeaker];
return localStream;
}
createLocalVideoTrack 方法会像
- (RTCVideoTrack*)createLocalVideoTrack
{
RTCVideoTrack* localVideoTrack = nil;
#if !TARGET_IPHONE_SIMULATOR && TARGET_OS_IPHONE
NSString* cameraID = nil;
for (AVCaptureDevice* captureDevice in
[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) {
if (captureDevice.position == AVCaptureDevicePositionFront) {
cameraID = [captureDevice localizedName];
[captureDevice lockForConfiguration:nil];
//configure frame rate
[captureDevice unlockForConfiguration];
// [AVCaptureDevice release];
break;
}
}
NSAssert(cameraID, @"Unable to get the front camera id");
RTCVideoCapturer* capturer = [RTCVideoCapturer capturerWithDeviceName:cameraID];
RTCMediaConstraints* mediaConstraints = [self defaultMediaStreamConstraints];
RTCVideoSource* videoSource = [_factory videoSourceWithCapturer:capturer constraints:mediaConstraints];
localVideoTrack = [_factory videoTrackWithID:@"ARDAMSv0" source:videoSource];
#endif
return localVideoTrack;
}
处理代码时,将在屏幕上询问相机和麦克风权限。
我正在开发 WebRTC iOS 应用程序以从网络摄像头接收 video/audio。 只有网络摄像头发送视频和音频,移动设备不发送任何内容。
我正在使用来自 CocoaPods (v11177.2.0) 的 libjingle_peerconnection 库。
一切正常,我可以正常接收视频和音频,但设备权限有问题。我第一次使用该应用程序时,当我想从网络摄像头接收视频时,iOS 应用程序要求获得麦克风许可。 这很重要,因为设备不发送音频,而我的客户说 "Why the app is asking for the microphone??"
这很奇怪,因为对于相机,应用程序不需要任何权限。
我已经检查了 SDP,似乎都可以(提供和回答)。
这是我创建对等连接对象的方式没有附加流:
RTCICEServer *stunServer = [[RTCICEServer alloc]initWithURI:[NSURL URLWithString:@"stun:stun.l.google.com:19302"] username:@"" password:@""];
NSMutableArray *iceServers = [NSMutableArray arrayWithObject:stunServer];
RTCPeerConnectionFactory *factory = [[RTCPeerConnectionFactory alloc]init];
NSArray *peerConnectionConstraints = @[[[RTCPair alloc] initWithKey:@"DtlsSrtpKeyAgreement" value:@"true"]];
RTCMediaConstraints *peerConnectionConstraints = [[RTCMediaConstraints alloc]initWithMandatoryConstraints:peerConnectionConstraints optionalConstraints:nil];
RTCPeerConnection *pConnection = [factory peerConnectionWithICEServers:iceServers constraints:peerConnectionConstraints delegate:self];
NSArray *sdpConstraints = @[[[RTCPair alloc] initWithKey:@"OfferToReceiveAudio" value:@"true"],
[[RTCPair alloc] initWithKey:@"OfferToReceiveVideo" value:@"true"]];
RTCMediaConstraints* sdpConstraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:sdpConstraints optionalConstraints:nil];
[pConnection createOfferWithDelegate:self constraints:sdpConstraints];
这是生成的 SDP 报价:
v=0
o=- 6528383367639880158 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS
m=audio 9 RTP/SAVPF 111 103 104 9 102 0 8 127 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:0QOsaBCKhCBBcHz5
a=ice-pwd:/y5snrrO3Qmq37m2aejRbK1E
a=mid:audio
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=recvonly
a=rtcp-mux
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:x1lfnVdo9lCRa9ykH6759WhY1SnI+dbLjKNbkTl+
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10; useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:102 ILBC/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:127 red/8000
a=rtpmap:126 telephone-event/8000
a=maxptime:60
m=video 9 RTP/SAVPF 100 101 116 117 96
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:0QOsaBCKhCBBcHz5
a=ice-pwd:/y5snrrO3Qmq37m2aejRbK1E
a=mid:video
a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:4 urn:3gpp:video-orientation
a=recvonly
a=rtcp-mux
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:x1lfnVdo9lCRa9ykH6759WhY1SnI+dbLjKNbkTl+
a=rtpmap:100 VP8/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=rtpmap:101 VP9/90000
a=rtcp-fb:101 ccm fir
a=rtcp-fb:101 nack
a=rtcp-fb:101 nack pli
a=rtcp-fb:101 goog-remb
a=rtcp-fb:101 transport-cc
a=rtpmap:116 red/90000
a=rtpmap:117 ulpfec/90000
a=rtpmap:96 rtx/90000
a=fmtp:96 apt=100
这是来自网络摄像头的 SDP 回答:
v=0
o=- 3699612909 3699612909 IN IP4 0.0.0.0
s=-
c=IN IP4 0.0.0.0
t=0 0
a=msid-semantic: WMS
a=group:BUNDLE audio video
m=audio 1 RTP/SAVPF 111 0
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=mid:audio
a=rtcp:9 IN IP4 0.0.0.0
a=rtpmap:111 opus/48000/2
a=rtpmap:0 PCMU/8000
a=sendonly
a=rtcp-mux
a=fmtp:111 minptime=10; useinbandfec=1
a=maxptime:60
a=ssrc:3192391506 cname:user604422501@host-6a96398f
a=ice-ufrag:r2kq
a=ice-pwd:6VJu/y0Kbc4iUDQB/1ZrnE
a=fingerprint:sha-256 57:26:29:A5:DD:CD:42:74:C9:A3:BB:C4:67:D1:1C:24:E9:4B:4C:86:6F:93:32:03:52:6B:2B:77:B3:C4:E8:88
m=video 1 RTP/SAVPF 100
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=mid:video
a=rtcp:9 IN IP4 0.0.0.0
a=rtpmap:100 VP8/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 goog-remb
a=sendonly
a=rtcp-mux
a=ssrc:455461391 cname:user604422501@host-6a96398f
a=ice-ufrag:r2kq
a=ice-pwd:6VJu/y0Kbc4iUDQB/1ZrnE
a=fingerprint:sha-256 57:26:29:A5:DD:CD:42:74:C9:A3:BB:C4:67:D1:1C:24:E9:4B:4C:86:6F:93:32:03:52:6B:2B:77:B3:C4:E8:88
如您所见,在 SDP 报价中,两种媒体(音频和视频)都是 "receiveOnly" 并且在 SDP 答案中 "sendOnly",所以我认为没有与SDP.
有人知道为什么要请求麦克风许可吗?如果您需要更多信息,请告诉我。
谢谢!
我没有和你的 code/libraries 合作过,对于那部分我无能为力,但是从 Apple documentation 我们可以读到:
The first time your app’s audio session attempts to use an audio input route while using a category that enables recording, the system automatically prompts the user for permission. You can explicitly ask earlier by calling the requestRecordPermission(_:) method. Until the user grants your app permission to record, your app can record only silence.
这可能会给你一些线索,某处(可能在 libjingle 中)正在访问 iOS Audio Session
并且可能是什么触发了麦克风权限。
给你。您需要像
这样创建本地流 -(RTCMediaStream*)createLocalMediaStream
{
RTCMediaStream* localStream = [_factory mediaStreamWithLabel:@"ARDAMS"];
if(![[ReveSingleton sharedManager].localCallControl isEqualToNumber:@251])
{
RTCVideoTrack* localVideoTrack;
localVideoTrack = [self createLocalVideoTrack];
if (localVideoTrack) {
[localStream addVideoTrack:localVideoTrack];
[_delegate appClient:self didReceiveLocalVideoTrack:localVideoTrack];
}
}
[localStream addAudioTrack:[_factory audioTrackWithID:@"ARDAMSa0"]];
if (_isSpeakerEnabled)
[self enableSpeaker];
return localStream;
}
createLocalVideoTrack 方法会像
- (RTCVideoTrack*)createLocalVideoTrack
{
RTCVideoTrack* localVideoTrack = nil;
#if !TARGET_IPHONE_SIMULATOR && TARGET_OS_IPHONE
NSString* cameraID = nil;
for (AVCaptureDevice* captureDevice in
[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) {
if (captureDevice.position == AVCaptureDevicePositionFront) {
cameraID = [captureDevice localizedName];
[captureDevice lockForConfiguration:nil];
//configure frame rate
[captureDevice unlockForConfiguration];
// [AVCaptureDevice release];
break;
}
}
NSAssert(cameraID, @"Unable to get the front camera id");
RTCVideoCapturer* capturer = [RTCVideoCapturer capturerWithDeviceName:cameraID];
RTCMediaConstraints* mediaConstraints = [self defaultMediaStreamConstraints];
RTCVideoSource* videoSource = [_factory videoSourceWithCapturer:capturer constraints:mediaConstraints];
localVideoTrack = [_factory videoTrackWithID:@"ARDAMSv0" source:videoSource];
#endif
return localVideoTrack;
}
处理代码时,将在屏幕上询问相机和麦克风权限。