直播類app中拉流技術(shù)的實(shí)現(xiàn)

之前說過推流的實(shí)現(xiàn) 瞄崇,現(xiàn)在來說一下拉流的實(shí)現(xiàn)。demo下載地址:https://pan.baidu.com/s/1miSAGre
拉流的實(shí)現(xiàn)我們主要通過LFLiveKit鸭你,LFLiveKit支持H264和AAC編碼爽彤,支持美顏和水印效果,傳輸協(xié)議是rtmp昂利,支持弱網(wǎng)丟幀届腐,記載網(wǎng)絡(luò)環(huán)境差的情況下,為了保證視頻的通常蜂奸,會(huì)自動(dòng)丟棄個(gè)別幀犁苏。
先看一下LFLiveKit提供的Demo運(yùn)行效果:(準(zhǔn)備工具VLC軟件)
1.github上搜索LFLiveKit。
2.打開下載后文件的LFLiveKitDemo工程(這里我們使用的是OC的Demo扩所,不是swift),控制臺(tái)中cd +這個(gè)工程的路徑围详,然后pod install,之后便可運(yùn)行在真機(jī)上。
3.打開LFLivePreview.m文件助赞,在這個(gè)文件的末尾會(huì)發(fā)現(xiàn)有這樣一行代碼: stream.url = @"rtmp://live.hkstv.hk.lxdns.com:1935/live/stream153”;并將這個(gè)網(wǎng)址復(fù)制到瀏覽器中打開买羞,此時(shí)會(huì)自動(dòng)打開VLC軟件,點(diǎn)擊playList中的網(wǎng)址雹食,便可播放手機(jī)端的拉流視頻畜普。
4.如果以上步驟執(zhí)行無誤,就說明手機(jī)端的拉流視頻已經(jīng)成功推送到服務(wù)器上群叶,我們通過VLC可以獲取到服務(wù)器上的推流視頻吃挑。

接下來看看如何將LFLiveKit繼承到我們自己的項(xiàng)目中去。
首先在podfile文件中添加pod ‘LFLiveKit’ 街立,然后 pod install舶衬。接下來就可以直接開始代碼部分了。

創(chuàng)建一個(gè)繼承與UIView的LFLivePreview類赎离,在LFLivePreview.h文件中對(duì)外提供兩個(gè)方法逛犹,開始拉直播和關(guān)閉直播方法。

@interface LFLivePreview : UIView
- (void)startLive;
- (void)stopLive;
@end

在LFLivePreview.m文件中蟹瘾,首先導(dǎo)入頭文件#import "LFLiveSession.h”圾浅,并遵守LFLiveSessionDelegate協(xié)議,然后添加一個(gè)屬性@property (nonatomic, strong) LFLiveSession *session;看一些這個(gè)屬性的懶加載代碼:

- (LFLiveSession *)session {
    if (!_session) {

        /***   默認(rèn)分辨率368 * 640  音頻:44.1 iphone6以上48  雙聲道  方向豎屏 ***/
        
        LFLiveAudioConfiguration * audioConfiguration =[LFLiveAudioConfiguration defaultConfiguration];
        
        LFLiveVideoConfiguration * videoConfiguration = [LFLiveVideoConfiguration defaultConfiguration];
        //最新寫法
         _session = [[LFLiveSession alloc]initWithAudioConfiguration:audioConfiguration videoConfiguration:videoConfiguration captureType:LFLiveCaptureDefaultMask];
        
       // _session = [[LFLiveSession alloc] initWithAudioConfiguration:audioConfiguration videoConfiguration:videoConfiguration liveType:LFLiveRTMP];
        
        _session.delegate = self;
        _session.showDebugInfo = NO;
        _session.preView = self;
        
    }
    return _session;
}

在初始化這個(gè)view的時(shí)候首先要實(shí)現(xiàn)音頻和視頻授權(quán)操作憾朴。

- (void)requestAccessForVideo {
    __weak typeof(self) _self = self;
    AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    switch (status) {
    case AVAuthorizationStatusNotDetermined: {
        // 許可對(duì)話沒有出現(xiàn)狸捕,發(fā)起授權(quán)許可
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
                if (granted) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [_self.session setRunning:YES];
                    });
                }
            }];
        break;
    }
    case AVAuthorizationStatusAuthorized: {
        // 已經(jīng)開啟授權(quán),可繼續(xù)
        dispatch_async(dispatch_get_main_queue(), ^{
            [_self.session setRunning:YES];
        });
        break;
    }
    case AVAuthorizationStatusDenied:
    case AVAuthorizationStatusRestricted:
        // 用戶明確地拒絕授權(quán)众雷,或者相機(jī)設(shè)備無法訪問

        break;
    default:
        break;
    }
}
- (void)requestAccessForAudio {
    AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
    switch (status) {
    case AVAuthorizationStatusNotDetermined: {
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {
            }];
        break;
    }
    case AVAuthorizationStatusAuthorized: {
        break;
    }
    case AVAuthorizationStatusDenied:
    case AVAuthorizationStatusRestricted:
        break;
    default:
        break;
    }
}

開始直播

- (void)startLive {
    LFLiveStreamInfo *stream = [LFLiveStreamInfo new];
     //這是直播的網(wǎng)址,直接復(fù)制LFLiveKit提供的這個(gè)地址
    stream.url = @"rtmp://live.hkstv.hk.lxdns.com:1935/live/stream153";
    [self.session startLive:stream];
}

- (void)startLive:(LFLiveStreamInfo *)streamInfo {
    if (!streamInfo) return;
    _streamInfo = streamInfo;
    _streamInfo.videoConfiguration = _videoConfiguration;
    _streamInfo.audioConfiguration = _audioConfiguration;
    [self.socket start];
}

停止直播

- (void)stopLive {
    [self.session stopLive];
}

- (void)stopLive {
    self.uploading = NO;
    [self.socket stop];
    self.socket = nil;
}

美顏效果

- (void)beautyBtnClick:(UIButton *)btn{
    self.session.beautyFace = !self.session.beautyFace;
    self.beautyButton.selected = !self.session.beautyFace;
}

鏡頭切換

- (void)cameraBtnClick:(UIButton *)btn{
    AVCaptureDevicePosition devicePositon = self.session.captureDevicePosition;
    self.session.captureDevicePosition = (devicePositon == AVCaptureDevicePositionBack) ? AVCaptureDevicePositionFront : AVCaptureDevicePositionBack;
}

退出直播

- (void)closeBtnClick:(UIButton *)btn{
    [self stopLive];
    [self.controller dismissViewControllerAnimated:YES completion:nil];
}

下面這個(gè)代理方法是監(jiān)控直播狀態(tài)的代理方法

- (void)liveSession:(nullable LFLiveSession *)session liveStateDidChange:(LFLiveState)state {
    NSLog(@"liveStateDidChange: %ld", state);
    switch (state) {
    case LFLiveReady:
        _stateLabel.text = @"未連接";
        break;
    case LFLivePending:
        _stateLabel.text = @"連接中";
        break;
    case LFLiveStart:
        _stateLabel.text = @"已連接";
        break;
    case LFLiveError:
        _stateLabel.text = @"連接錯(cuò)誤";
        break;
    case LFLiveStop:
        _stateLabel.text = @"未連接";
        break;
    default:
        break;
    }
}

外部直播控制器界面調(diào)用形式

- (IBAction)startLive:(id)sender {
    UIView * back = [[UIView alloc] initWithFrame:self.view.bounds];
    back.backgroundColor = [UIColor blackColor];
    [self.view addSubview:back];
    LFLivePreview * liveView = [[LFLivePreview alloc] initWithFrame:self.view.bounds withController:self];
    [self.view addSubview:liveView];
    [liveView startLive];
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末灸拍,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子砾省,更是在濱河造成了極大的恐慌鸡岗,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件编兄,死亡現(xiàn)場(chǎng)離奇詭異轩性,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)狠鸳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門揣苏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人件舵,你說我怎么就攤上這事卸察。” “怎么了铅祸?”我有些...
    開封第一講書人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵坑质,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng)涡扼,這世上最難降的妖魔是什么稼跳? 我笑而不...
    開封第一講書人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮壳澳,結(jié)果婚禮上岂贩,老公的妹妹穿的比我還像新娘茫经。我一直安慰自己巷波,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開白布卸伞。 她就那樣靜靜地躺著抹镊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪荤傲。 梳的紋絲不亂的頭發(fā)上垮耳,一...
    開封第一講書人閱讀 49,842評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音遂黍,去河邊找鬼终佛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛雾家,可吹牛的內(nèi)容都是我干的铃彰。 我是一名探鬼主播,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼芯咧,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼牙捉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起敬飒,我...
    開封第一講書人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤邪铲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后无拗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體带到,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年英染,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了揽惹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡税迷,死狀恐怖永丝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情箭养,我是刑警寧澤慕嚷,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響喝检,放射性物質(zhì)發(fā)生泄漏嗅辣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一挠说、第九天 我趴在偏房一處隱蔽的房頂上張望澡谭。 院中可真熱鬧,春花似錦损俭、人聲如沸蛙奖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)雁仲。三九已至,卻和暖如春琐脏,著一層夾襖步出監(jiān)牢的瞬間攒砖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工日裙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吹艇,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓昂拂,卻偏偏與公主長(zhǎng)得像受神,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子政钟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容