一、本地流创建,属性声明:
//音视频标识
#define KT_STREAM @"CCSTREAM"
#define KT_VIDEO_0 @"CCVideo_0"
#define KT_AUDIO_0 @"CCAUDIO_0"
@interface ConferenceStreamViewController ()
//数据源
@property(nonatomic,strong)RTCVideoSource *source;
//capture
@property(nonatomic,strong)RTCCameraVideoCapturer *capturer;
//Peer 工厂
@property(nonatomic,strong)RTCPeerConnectionFactory *factory;
//本地流
@property(nonatomic,strong)RTCMediaStream *rtcLocalStream;
//标记前后摄像头
@property(nonatomic,assign)BOOL _usingFrontCamera;
@end
二、创建本地流并推流
-(void)doPublishMedia
{
if (_rtcLocalStream == nil)
{
//如果为空,则创建点对点工厂
if (!_factory)
{
_factory = [RTCPeerConnectionFactory sharedInstance];
}
NSArray<AVCaptureDevice *> *captureDevices = [RTCCameraVideoCapturer captureDevices];
AVCaptureDevicePosition position = _usingFrontCamera ? AVCaptureDevicePositionFront : AVCaptureDevicePositionBack;
AVCaptureDevice * device = captureDevices[0];
for (AVCaptureDevice *obj in captureDevices)
{
if (obj.position == position)
{
device = obj;
break;
}
}
//检测摄像头权限
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)
{
NSLog(@"相机访问受限");
}
else
{
if (device)
{
//创建本地流
_rtcLocalStream = [_factory mediaStreamWithStreamId:KT_STREAM];
//获取数据源
_source = [_factory videoSource];
//音频
RTCAudioTrack * audioTrack = [_factory audioTrackWithTrackId:KT_AUDIO_0];
//视频
RTCVideoTrack *videoTrack = [_factory videoTrackWithSource:_source trackId:KT_VIDEO_0];
//将audioTrack、videoTrack添加到流
[_rtcLocalStream addAudioTrack:audioTrack];
[_rtcLocalStream addVideoTrack:videoTrack];
//拿到capture对象
RTCCameraVideoCapturer * capture = [[RTCCameraVideoCapturer alloc] initWithDelegate:_source];
AVCaptureDeviceFormat * format = [[RTCCameraVideoCapturer supportedFormatsForDevice:device] lastObject];
CGFloat fps = [[format videoSupportedFrameRateRanges] firstObject].maxFrameRate;
_capturer = capture;
[capture startCaptureWithDevice:device format:format fps:fps completionHandler:^(NSError * error) {
NSLog(@"startCaptureWithDevice---:%@",error);
dispatch_async(dispatch_get_main_queue(), ^{
//展示预览
[((StreamView *)self.view).localVideoView setCaptureSession:[_capturer captureSession] ];
});
}];
}
else
{
NSLog(@"该设备不能打开摄像头");
}
}
//设置音视频编码格式
ICSStreamSourceInfo *sInfo = [[ICSStreamSourceInfo alloc]init];
sInfo.audio = ICSAudioCodecOpus;
sInfo.video = ICSVideoCodecH264;
//创建ICSLocalStream 流
_localStream = [[ICSLocalStream alloc]initWithMediaStream:_rtcLocalStream source:sInfo];
#pragma mark
ICSPublishOptions* options=[[ICSPublishOptions alloc] init];
ICSAudioCodecParameters* opusParameters=[[ICSAudioCodecParameters alloc] init];
opusParameters.name=ICSAudioCodecOpus;
ICSAudioEncodingParameters *audioParameters=[[ICSAudioEncodingParameters alloc] init];
audioParameters.codec=opusParameters;
//设置音频码率
audioParameters.maxBitrate = 50;
options.audio=[NSArray arrayWithObjects:audioParameters, nil];
ICSVideoCodecParameters *h264Parameters=[[ICSVideoCodecParameters alloc] init];
h264Parameters.name=ICSVideoCodecH264;
ICSVideoEncodingParameters *videoParameters=[[ICSVideoEncodingParameters alloc]init];
videoParameters.codec=h264Parameters;
//设置视频码率
//这里一定要设置,不然推流一会儿就会因码率太高而卡死
videoParameters.maxBitrate = 200;
options.video=[NSArray arrayWithObjects:videoParameters, nil];
[_conferenceClient publish:_localStream withOptions:options onSuccess:^(ICSConferencePublication* p) {
_publication=p;
_publication.delegate=self;
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"publish success!");
});
} onFailure:^(NSError* err) {
NSLog(@"publish failure!");
}];
}
}
三、切换摄像头
/**
* 切换摄像头
*/
- (void)swichCamera
{
_usingFrontCamera = !_usingFrontCamera;
[self localSwitchCamera];
}
/*** 切换本地视频流*/
-(void)localSwitchCamera
{
NSArray<AVCaptureDevice *> *captureDevices = [RTCCameraVideoCapturer captureDevices];
AVCaptureDevicePosition position = _usingFrontCamera ? AVCaptureDevicePositionFront : AVCaptureDevicePositionBack;
AVCaptureDevice * device = captureDevices[0];
for (AVCaptureDevice *obj in captureDevices)
{
if (obj.position == position)
{
device = obj;
break;
}
}
//检测摄像头权限
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)
{
NSLog(@"相机访问受限");
}
else
{
if (device)
{
AVCaptureDeviceFormat * format = [[RTCCameraVideoCapturer supportedFormatsForDevice:device] lastObject];
CGFloat fps = [[format videoSupportedFrameRateRanges] firstObject].maxFrameRate;
[_capturer startCaptureWithDevice:device format:format fps:fps completionHandler:^(NSError * error) {
NSLog(@"11111111");
dispatch_async(dispatch_get_main_queue(), ^{
[((StreamView *)self.view).localVideoView setCaptureSession:[_capturer captureSession] ];
});
}];
}
else
{
NSLog(@"该设备不能打开摄像头");
}
}
}