ijkplayer 是一款做视频直播的框架, 基于ffmpeg, 支持 Android 和 iOS,
<h2>一. 下载ijkplayer</h2>
ijkplayer
下载地址:https://github.com/Bilibili/ijkplayer
下载完成后解压, 解压后文件夹内部目录如下图:
<h2>二. 编译 ijkplayer
</h2>
说是编译ijkplayer
, 其实是编译 ffmpeg
, 在这里我们已经下载好了ijkplayer
, 所以 github
上README.md
中的Build iOS
那一步中有一些步骤是不需要的.
下面开始一步一步编译:
1.打开终端, cd
到ijkplayer-master
文件夹中, 也就是下载完解压后的文件夹, 如下图:
进入到这个文件夹
2.执行命令行./init-ios.sh
, 这一步是去下载ffmpeg
的, 时间会久一点, 耐心等一下.如下图:
3.在第2步中下载完成后, 执行cd ios
, 也就是进入到ios
目录中, 如下图:
进入ios 文件夹
4.进入
ios
文件夹后, 在终端依次执行./compile-ffmpeg.sh clean
和./compile-ffmpeg.sh all
命令, 编译 ffmpeg
, 也就是README.md
中这两步, 如下图:
编译时间较久, 耐心等待一下.
<h2>三. 打包IJKMediaFramework.framework
框架</h2>
集成ijkplayer
有两种方法:
一种方法是按照IJKMediaDemo
工程中那样, 直接导入工程IJKMediaPlayer.xcodeproj,
在这里不做介绍, 如下图:
导入IJKMediaPlayer.xcodeproj
第二种集成方法是把ijkplayer
打包成framework
导入工程中使用. 下面开始介绍如何打包IJKMediaFramework.framework
, 按下面步骤开始一步一步做:
1.首先打开工程IJKMediaPlayer.xcodeproj,
位置如下图:
打开后是这样的, 如下图:
2.工程打开后设置工程的 scheme
, 具体步骤如下图:
3.设置好
scheme
后, 分别选择真机和模拟器进行编译, 编译完成后, 进入 Finder
, 如下图:
进入 Finder
后, 可以看到有真机和模拟器两个版本的编译结果, 如下图:
下面开始合并真机和模拟器版本的 framework,
注意不要合并错了, 合并的是这个文件, 如下图:
打开终端, 进行合并, 命令行具体格式为:
lipo -create "真机版本路径" "模拟器版本路径" -output "合并后的文件路径"
合并后如下图:
下面很重要, 需要用合并后的IJKMediaFramework把原来的IJKMediaFramework替换掉, 如下图, 希望你能看懂:
上图中的1、2两步完成后, 绿色框住的那个IJKMediaFramework.framework
文件就是我们需要的框架了, 可以复制出来, 稍后我们需要导入工程使用.
</h2>四. iOS工程中集成ijkplayer
</h2>
新建工程, 导入合并后的IJKMediaFramework.framework
以及相关依赖框架以及相关依赖框架,如下图:
导入 framework及依赖框架.png
导入框架后, 在
ViewController.m
进行测试, 首先导入IJKMediaFramework.h
头文件, 编译看有没有错, 如果没有错说明集成成功.
<h1>ijkplayer 集成完毕下面是代码</h1>
- 主要是从下载的IJKsdk中扒的一些通知,监听
- 创建毛玻璃
- 初始化控件
//
// ZJVideoController.m
// SchoolBus
//
// Created by zhang on 2017/5/8.
// Copyright © 2017年 zhang. All rights reserved.
//
#import "ZJVideoController.h"
#import <IJKMediaFramework/IJKMediaFramework.h>
@interface ZJVideoController ()
@property(atomic, retain) id<IJKMediaPlayback> player;
@property (nonatomic, strong) UIImageView * blurImageView;
@end
@implementation ZJVideoController
- (void)viewDidLoad {
[super viewDidLoad];
//设置视频流空件
[self initPlayer];
//创建毛玻璃效果
[self initUI];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
//注册直播需要用的通知
[self installMovieNotificationObservers];
//准备播放
[self.player prepareToPlay];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
// 界面消失,一定要记得停止播放
[self.player pause];
[self.player stop];
[self.player shutdown];
[self removeMovieNotificationObservers];
}
- (void)initUI{
self.view.backgroundColor = [UIColor blackColor];
self.blurImageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
self.blurImageView.userInteractionEnabled = YES;
self.blurImageView.image = [UIImage imageNamed:@"default_room"];
[self.view addSubview:self.blurImageView];
//创建毛玻璃效果
UIBlurEffect * blur = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
//创建毛玻璃视图
UIVisualEffectView * ve = [[UIVisualEffectView alloc] initWithEffect:blur];
ve.frame = self.blurImageView.bounds;
//毛玻璃视图加入图片view上
[self.blurImageView addSubview:ve];
}
- (void)initPlayer {
IJKFFOptions * options = [IJKFFOptions optionsByDefault];
//设置流地址
IJKFFMoviePlayerController * player = [[IJKFFMoviePlayerController alloc] initWithContentURLString:@"http://pull99.a8.com/live/1495075034121158.flv?ikHost=ws&ikOp=1&codecInfo=8192" withOptions:options];
self.player = player;
CGFloat height = [UIScreen mainScreen].bounds.size.height -64-49;
CGFloat width = [UIScreen mainScreen].bounds.size.width;
self.player.view.frame = CGRectMake(0, 64, width*0.5, height*0.5);
self.player.shouldAutoplay = YES;
[self.view addSubview:self.player.view];
}
#pragma mark Install Movie Notifications
/* Register observers for the various movie object notifications. */
-(void)installMovieNotificationObservers
{
//监听网络环境,监听缓冲方法
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(loadStateDidChange:)
name:IJKMPMoviePlayerLoadStateDidChangeNotification
object:_player];
//监听直播完成回调
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlayBackDidFinish:)
name:IJKMPMoviePlayerPlaybackDidFinishNotification
object:_player];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(mediaIsPreparedToPlayDidChange:)
name:IJKMPMediaPlaybackIsPreparedToPlayDidChangeNotification
object:_player];
//监听用户主动操作
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlayBackStateDidChange:)
name:IJKMPMoviePlayerPlaybackStateDidChangeNotification
object:_player];
}
#pragma mark Remove Movie Notification Handlers
/* Remove the movie notification observers from the movie object. */
-(void)removeMovieNotificationObservers
{
[[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMoviePlayerLoadStateDidChangeNotification object:_player];
[[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMoviePlayerPlaybackDidFinishNotification object:_player];
[[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMediaPlaybackIsPreparedToPlayDidChangeNotification object:_player];
[[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMoviePlayerPlaybackStateDidChangeNotification object:_player];
}
- (void)loadStateDidChange:(NSNotification*)notification
{
// MPMovieLoadStateUnknown = 0,未知
// MPMovieLoadStatePlayable = 1 << 0,缓冲结束可以播放
// MPMovieLoadStatePlaythroughOK = 1 << 1, // Playback will be automatically started in this state when shouldAutoplay is YES 缓冲结束自动播放
// MPMovieLoadStateStalled = 1 << 2, // Playback will be automatically paused in this state, if started
//暂停
IJKMPMovieLoadState loadState = _player.loadState;
if ((loadState & IJKMPMovieLoadStatePlaythroughOK) != 0) {
NSLog(@"loadStateDidChange: IJKMPMovieLoadStatePlaythroughOK: %d\n", (int)loadState);
} else if ((loadState & IJKMPMovieLoadStateStalled) != 0) {
NSLog(@"loadStateDidChange: IJKMPMovieLoadStateStalled: %d\n", (int)loadState);
} else {
NSLog(@"loadStateDidChange: ???: %d\n", (int)loadState);
}
self.blurImageView.hidden = YES;
[self.blurImageView removeFromSuperview];
}
- (void)moviePlayBackDidFinish:(NSNotification*)notification
{
// MPMovieFinishReasonPlaybackEnded, 直播结束
// MPMovieFinishReasonPlaybackError, 直播错误
// MPMovieFinishReasonUserExited 用户退出
int reason = [[[notification userInfo] valueForKey:IJKMPMoviePlayerPlaybackDidFinishReasonUserInfoKey] intValue];
switch (reason)
{
case IJKMPMovieFinishReasonPlaybackEnded:
NSLog(@"playbackStateDidChange: IJKMPMovieFinishReasonPlaybackEnded: %d\n", reason);
break;
case IJKMPMovieFinishReasonUserExited:
NSLog(@"playbackStateDidChange: IJKMPMovieFinishReasonUserExited: %d\n", reason);
break;
case IJKMPMovieFinishReasonPlaybackError:
NSLog(@"playbackStateDidChange: IJKMPMovieFinishReasonPlaybackError: %d\n", reason);
break;
default:
NSLog(@"playbackPlayBackDidFinish: ???: %d\n", reason);
break;
}
}
- (void)mediaIsPreparedToPlayDidChange:(NSNotification*)notification
{
NSLog(@"mediaIsPreparedToPlayDidChange\n");
}
- (void)moviePlayBackStateDidChange:(NSNotification*)notification
{
// MPMoviePlaybackStateStopped,
// MPMoviePlaybackStatePlaying,
// MPMoviePlaybackStatePaused,
// MPMoviePlaybackStateInterrupted,
// MPMoviePlaybackStateSeekingForward,
// MPMoviePlaybackStateSeekingBackward
switch (_player.playbackState)
{
case IJKMPMoviePlaybackStateStopped: {
NSLog(@"IJKMPMoviePlayBackStateDidChange %d: stoped", (int)_player.playbackState);
break;
}
case IJKMPMoviePlaybackStatePlaying: {
NSLog(@"IJKMPMoviePlayBackStateDidChange %d: playing", (int)_player.playbackState);
break;
}
case IJKMPMoviePlaybackStatePaused: {
NSLog(@"IJKMPMoviePlayBackStateDidChange %d: paused", (int)_player.playbackState);
break;
}
case IJKMPMoviePlaybackStateInterrupted: {
NSLog(@"IJKMPMoviePlayBackStateDidChange %d: interrupted", (int)_player.playbackState);
break;
}
case IJKMPMoviePlaybackStateSeekingForward:
case IJKMPMoviePlaybackStateSeekingBackward: {
NSLog(@"IJKMPMoviePlayBackStateDidChange %d: seeking", (int)_player.playbackState);
break;
}
default: {
NSLog(@"IJKMPMoviePlayBackStateDidChange %d: unknown", (int)_player.playbackState);
break;
}
}
}
@end