下载:gitHub链接 -- https://github.com/Bilibili/ijkplayer
编译:
通过以上图片中命令行来编译ffmpeg(编译时间较长,耐心等待即可)。
打包IJKMediaFramework
工程打开后设置工程的 scheme, 具体步骤如下图:
3.设置好 scheme 后, 分别选择真机和模拟器进行编译, 编译完成后, 进入 Finder, 如下图:
进入 Finder 后, 可以看到有真机和模拟器两个版本的编译结果, 如下图:
下面开始合并真机和模拟器版本的 framework, 注意不要合并错了, 合并的是这个文件, 如下图:
打开终端, 进行合并, 命令行具体格式为:
1
|
lipo
-
create
"真机版本路径"
"模拟器版本路径"
-
output
"合并后的文件路径"
|
合并后如下图:
下面很重要, 需要用合并后的IJKMediaFramework
把原来的IJKMediaFramework
替换掉, 如下图, 希望你能看懂:
导入:#import
///播放器controller (哔哩哔哩)
@interface PlayViewController ()
@property(nonatomic,strong)IJKFFMoviePlayerController * player;
@end
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.view addGestureRecognizer:_resetBottomTapGesture];
[self.conversationMessageCollectionView reloadData];
//准备播放 (哔哩哔哩)
[self.player prepareToPlay];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.navigationTitle = self.navigationItem.title;
}
/**
* 移除监听
*
* @param animated
*/
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:@"kRCPlayVoiceFinishNotification"
object:nil];
[self.conversationMessageCollectionView removeGestureRecognizer:_resetBottomTapGesture];
[self.conversationMessageCollectionView
addGestureRecognizer:_resetBottomTapGesture];
//退出页面,弹幕停止
[self.view stopDanmaku];
// 停止播放
// [_txlivePlayer stopPlay];
// [_txlivePlayer removeVideoWidget]; // 记得销毁view控件
}
- (void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
//销毁播放器
[self.player shutdown];
}
#pragma mark -- 视频播放器
- (void)addPlayerWithurl:(NSString *)url{
// 创建player
//bilibili 播放器
IJKFFOptions *options = [IJKFFOptions optionsByDefault]; //使用默认配置
self.player = [[IJKFFMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:url] withOptions:options]; //初始化播放器,播放在线视频或直播(RTMP)
self.player.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
self.player.view.frame = _playView.bounds;
self.player.scalingMode = IJKMPMovieScalingModeFill; //缩放模式
self.player.shouldAutoplay = YES; //开启自动播放
_playView.autoresizesSubviews = YES;
[_playView addSubview:self.player.view];
}
//监听加载状态改变通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loadStateDidChange:) name:IJKMPMoviePlayerLoadStateDidChangeNotification object:nil];
- (void)stopBtnDidClicked:(UIButton *)sender{
if (!sender.selected) {
// 暂停播放
[self.player pause];
}else{
//恢复播放
[self.player play];
}
//改变状态
sender.selected = !sender.selected;
}
///播放状态发生改变时
- (void)loadStateDidChange:(NSNotification *) notification
{
//状态为缓冲几乎完成,可以连续播放
if ((self.player.loadState & IJKMPMovieLoadStatePlaythroughOK) != 0) {
if (!self.player.isPlaying) {
//开始播放
[self.player play];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:self.player.view animated:YES];
if (_noPlayView.hidden == NO) {
_noPlayView.hidden = YES;
}
});
}else{
// 如果是网络状态不好, 断开后恢复, 也需要去掉加载
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:self.player.view animated:YES];
if (_noPlayView.hidden == NO) {
_noPlayView.hidden = YES;
}
});
}
}
//缓冲中
else if (self.player.loadState & IJKMPMovieLoadStateStalled){
[MBProgressHUD showHUDAddedTo:self.player.view animated:YES];
[[DataHandle sharedDataHandel]getPlayRoomInfoWithRoomID:self.roomId Block:^(id object) {
///判断是否正在播放
if ([((RoomPlayInfoModel *)object).live_status isEqual:@0]) {
//主播不在家 播放状态
_isBiliPlay = NO;
_noPlayView.hidden = NO;
//_noPlayView.hidden = YES;
}
}];
/*
这里主播可能已经结束直播了。我们需要请求服务器查看主播是否已经结束直播。
方法:
1、从服务器获取主播是否已经关闭直播。
优点:能够正确的获取主播端是否正在直播。
缺点:主播端异常crash的情况下是没有办法通知服务器该直播关闭的。
2、用户http请求该地址,若请求成功表示直播未结束,否则结束
优点:能够真实的获取主播端是否有推流数据
缺点:如果主播端丢包率太低,但是能够恢复的情况下,数据请求同样是失败的。
*/
}
}