WebRTC音视频通话-iOS端调用ossrs直播拉流

WebRTC音视频通话-iOS端调用ossrs直播拉流

之前实现iOS端调用ossrs服务,文中提到了推流。没有写拉流流程,所以会用到文中的WebRTCClient。请详细查看:https://blog.csdn.net/gloryFlow/article/details/132262724

一、iOS播放端拉流效果

二、实现iOS端调用ossrs拉流

最近有朋友问过,我发现之前少了一块拉流流程,这里补充一下。

2.1、拉流实现时候设置WebRTCClient

拉流实现时候设置WebRTCClient时候初始化,这里isPublish为false

objectivec 复制代码
#pragma mark - Lazy
- (WebRTCClient *)webRTCClient {
    if (!_webRTCClient) {
        _webRTCClient = [[WebRTCClient alloc] initWithPublish:NO];
    }
    return _webRTCClient;
}

2.2、设置拉流显示的画面View。

之前的文中摄像头画面显示使用的是startCaptureLocalVideo,但是拉流需要设置remoteRenderView

WebRTCClient中有定义:

objectivec 复制代码
/**
 RTCVideoRenderer
 */
@property (nonatomic, weak) id<RTCVideoRenderer> remoteRenderView;

设置拉流显示的画面View

objectivec 复制代码
#import "RTCPlayView.h"

@interface RTCPlayView ()

@property (nonatomic, strong) WebRTCClient *webRTCClient;
@property (nonatomic, strong) RTCEAGLVideoView *remoteRenderer;

@end

@implementation RTCPlayView

- (instancetype)initWithFrame:(CGRect)frame webRTCClient:(WebRTCClient *)webRTCClient {
    self = [super initWithFrame:frame];
    if (self) {
        self.webRTCClient = webRTCClient;
        
        self.remoteRenderer = [[RTCEAGLVideoView alloc] initWithFrame:CGRectZero];
        self.remoteRenderer.contentMode = UIViewContentModeScaleAspectFit;
        [self addSubview:self.remoteRenderer];
        self.webRTCClient.remoteRenderView = self.remoteRenderer;
    }
    return self;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    self.remoteRenderer.frame = self.bounds;
    NSLog(@"self.remoteRenderer frame:%@", NSStringFromCGRect(self.remoteRenderer.frame));
}

@end

这里使用的创建RTCEAGLVideoView,设置self.webRTCClient.remoteRenderView为self.remoteRenderer

2.3、调用ossrs服务play,接口为rtc/v1/play/

实现拉流调用流程和推流类似,这里不再说明,请查看 https://blog.csdn.net/gloryFlow/article/details/132262724

具体方法如下

objectivec 复制代码
- (void)playBtnClick {
    __weak typeof(self) weakSelf = self;
    [self.webRTCClient offer:^(RTCSessionDescription *sdp) {
        [weakSelf.webRTCClient changeSDP2Server:sdp urlStr:@"https://192.168.10.102:1990/rtc/v1/play/" streamUrl:@"webrtc://192.168.10.102:1990/live/livestream" closure:^(BOOL isServerRetSuc) {
            NSLog(@"isServerRetSuc:%@",(isServerRetSuc?@"YES":@"NO"));
        }];
    }];
}

完整的Controller代码如下

objectivec 复制代码
#import "RTCPlayViewController.h"

@interface RTCPlayViewController ()<WebRTCClientDelegate>

@property (nonatomic, strong) WebRTCClient *webRTCClient;

@property (nonatomic, strong) RTCPlayView *rtcPlayView;

@property (nonatomic, strong) UIButton *playBtn;

@end

@implementation RTCPlayViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    self.rtcPlayView = [[RTCPlayView alloc] initWithFrame:CGRectZero webRTCClient:self.webRTCClient];
    [self.view addSubview: self.rtcPlayView];
    self.rtcPlayView.backgroundColor = [UIColor lightGrayColor];
    self.rtcPlayView.frame = self.view.bounds;
    
    CGFloat screenWidth = CGRectGetWidth(self.view.bounds);
    CGFloat screenHeight = CGRectGetHeight(self.view.bounds);
    self.playBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    self.playBtn.frame = CGRectMake(50, screenHeight - 160, screenWidth - 2*50, 46);
    self.playBtn.layer.cornerRadius = 4;
    self.playBtn.backgroundColor = [UIColor grayColor];
    [self.playBtn setTitle:@"publish" forState:UIControlStateNormal];
    [self.playBtn addTarget:self action:@selector(playBtnClick) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.playBtn];
    
    self.webRTCClient.delegate = self;
}

- (void)playBtnClick {
    __weak typeof(self) weakSelf = self;
    [self.webRTCClient offer:^(RTCSessionDescription *sdp) {
        [weakSelf.webRTCClient changeSDP2Server:sdp urlStr:@"https://192.168.10.102:1990/rtc/v1/play/" streamUrl:@"webrtc://192.168.10.102:1990/live/livestream" closure:^(BOOL isServerRetSuc) {
            NSLog(@"isServerRetSuc:%@",(isServerRetSuc?@"YES":@"NO"));
        }];
    }];
}

#pragma mark - WebRTCClientDelegate
- (void)webRTCClient:(WebRTCClient *)client didDiscoverLocalCandidate:(RTCIceCandidate *)candidate {
    NSLog(@"webRTCClient didDiscoverLocalCandidate");
}

- (void)webRTCClient:(WebRTCClient *)client didChangeConnectionState:(RTCIceConnectionState)state {
    NSLog(@"webRTCClient didChangeConnectionState");
    /**
     RTCIceConnectionStateNew,
     RTCIceConnectionStateChecking,
     RTCIceConnectionStateConnected,
     RTCIceConnectionStateCompleted,
     RTCIceConnectionStateFailed,
     RTCIceConnectionStateDisconnected,
     RTCIceConnectionStateClosed,
     RTCIceConnectionStateCount,
     */
    UIColor *textColor = [UIColor blackColor];
    BOOL openSpeak = NO;
    switch (state) {
        case RTCIceConnectionStateCompleted:
        case RTCIceConnectionStateConnected:
            textColor = [UIColor greenColor];
            openSpeak = YES;
            break;
            
        case RTCIceConnectionStateDisconnected:
            textColor = [UIColor orangeColor];
            break;
            
        case RTCIceConnectionStateFailed:
        case RTCIceConnectionStateClosed:
            textColor = [UIColor redColor];
            break;
            
        case RTCIceConnectionStateNew:
        case RTCIceConnectionStateChecking:
        case RTCIceConnectionStateCount:
            textColor = [UIColor blackColor];
            break;
            
        default:
            break;
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
        NSString *text = [NSString stringWithFormat:@"%ld", state];
        [self.playBtn setTitle:text forState:UIControlStateNormal];
        [self.playBtn setTitleColor:textColor forState:UIControlStateNormal];
        
        if (openSpeak) {
            [self.webRTCClient speakOn];
        }
//        if textColor == .green {
//            self?.webRTCClient.speakerOn()
//        }
    });
}

- (void)webRTCClient:(WebRTCClient *)client didReceiveData:(NSData *)data {
    NSLog(@"webRTCClient didReceiveData");
}


#pragma mark - Lazy
- (WebRTCClient *)webRTCClient {
    if (!_webRTCClient) {
        _webRTCClient = [[WebRTCClient alloc] initWithPublish:NO];
    }
    return _webRTCClient;
}

@end

至此,可以实现iOS端调用的ossrs视频通话拉流

其他

之前搭建ossrs服务,可以查看:https://blog.csdn.net/gloryFlow/article/details/132257196

之前实现iOS端调用ossrs音视频通话,可以查看:https://blog.csdn.net/gloryFlow/article/details/132262724

之前WebRTC音视频通话高分辨率不显示画面问题,可以查看:https://blog.csdn.net/gloryFlow/article/details/132240952

修改SDP中的码率Bitrate,可以查看:https://blog.csdn.net/gloryFlow/article/details/132263021

GPUImage视频通话视频美颜滤镜,可以查看:https://blog.csdn.net/gloryFlow/article/details/132265842

RTC直播本地视频或相册视频,可以查看:https://blog.csdn.net/gloryFlow/article/details/132267068

三、小结

WebRTC音视频通话-iOS端调用ossrs直播拉流。用到了WebRTC调用ossrs实现推拉流效果。内容较多,描述可能不准确,请见谅。

https://blog.csdn.net/gloryFlow/article/details/132417602

学习记录,每天不停进步。

相关推荐
DisonTangor3 分钟前
苹果发布iOS 18.2首个公测版:Siri接入ChatGPT、iPhone 16拍照按钮有用了
ios·chatgpt·iphone
- 羊羊不超越 -6 分钟前
App渠道来源追踪方案全面分析(iOS/Android/鸿蒙)
android·ios·harmonyos
EasyCVR21 分钟前
EHOME视频平台EasyCVR视频融合平台使用OBS进行RTMP推流,WebRTC播放出现抖动、卡顿如何解决?
人工智能·算法·ffmpeg·音视频·webrtc·监控视频接入
冷凝女子2 小时前
【QT】海康视频及openCv抓拍正脸接口
qt·opencv·音视频·海康
安步当歌3 小时前
【WebRTC】视频编码链路中各个类的简单分析——VideoStreamEncoder
音视频·webrtc·视频编解码·video-codec
顾北川_野4 小时前
Android CALL关于电话音频和紧急电话设置和获取
android·音视频
顶呱呱程序4 小时前
2-143 基于matlab-GUI的脉冲响应不变法实现音频滤波功能
算法·matlab·音视频·matlab-gui·音频滤波·脉冲响应不变法
EasyCVR5 小时前
萤石设备视频接入平台EasyCVR多品牌摄像机视频平台海康ehome平台(ISUP)接入EasyCVR不在线如何排查?
运维·服务器·网络·人工智能·ffmpeg·音视频
runing_an_min5 小时前
ffmpeg 视频滤镜:屏蔽边框杂色- fillborders
ffmpeg·音视频·fillborders
2401_8658548816 小时前
iOS应用想要下载到手机上只能苹果签名吗?
后端·ios·iphone