前言
在看这篇之前,如果您还不了解直播原理,请查看上篇文章如何快速的开发一个完整的iOS直播app(原理篇)
开发一款直播app,集成ijkplayer成功后,就算完成直播功能一半的工程了,只要有拉流url,就能播放直播啦
本篇主要讲解的是直播app中,需要用到的一个很重要的开源框架ijkplayer
,然后集成这个框架可能对大多数初学者
还是比较有难度的,所以本篇主要教你解决集成【ijkplayer】遇见的各种坑
。
很多文章,可能讲解的是如何做,我比较注重讲解为什么
这样做,大家有什么不明白,还可以多多提出来
。
如果喜欢我的文章,可以关注我微博:袁峥Seemygo
效果
直播.gif一、基本知识
README.md文件
:框架的描述文件,描述这个框架怎么使用
编译语言
:程序在被执行之前,需要一个专门的编译过程,把程序编译成为机器语言的文件,运行时不需要翻译,所以编译型语言的程序执行效率高,比如OC,C,C++
解释性语言
:解释性语言的程序不需要编译,在运行程序的时候才翻译,每个语句都是执行的时候才翻译。这样解释性语言每执行一次就需要逐行翻译一次,效率比较低
解释性语言执行和编译语言执行的区别
:
- 解释性语言一行一行的解析,如果有错误,就不会执行,直接执行下一行。
- 编译语言,只要有错,就不能编译,一行都不能执行。
脚本语言
:属于解析语言,必须通过解释器解析,将其一条条的翻译成机器可识别的指令,并按程序顺序执行。
- python:脚本语言,适合网络应用程序的开发,有利于开发效率,现在显得越来越强大
- PHP:服务器端脚本语言,适合做动态网站
- JS:作为客户端的脚本语言,在浏览中解释执行,
- shell:操作系统脚本语言,一般指Unix/Linux中使用的命令行
- 编译语言,执行文件是二进制。脚本语言是解释执行的,执行文件是文本
shell解释器
:shell是一个命令行解释器,相当于windows的cmd,处于内核和用户之间,负责把用户的指令传递给内核并且把执行结果回显给用户.
- 默认Unix都有shell,OS基于Unix,因此OS自带shell。
bash
: bash是一种shell解释器版本,shell有很多种版本,就像人,也分不同国家的人。
- 牛程序员看到不爽的Shell解释器,就会自己重新写一套,慢慢形成了一些标准,常用的Shell解释器有这么几种,sh、bash、csh等
shell
:通常我们说的shell,指的是shell脚本语言,而不是shell解释器。
- 在编写shell时,第一行一定要指明系统需要哪种shell解释器解释你的shell脚本,如:#! /bin/bash,使用bash解析脚本语言
-
什么时候使用shell命令
,比如有些系统命令经常需要用到,可以把命令封装到一个脚本文件,以后就不用再敲一遍了,直接执行脚本语言。 - 比如ijkplayer,就用脚本文件下载ffmpeg,因为下载ffmpeg需要执行很多命令,全部封装到脚本文件中。
- 在导入一些第三方框架的时候,经常需要用到一些命令,所以一般都会封装到一个脚本文件中,以后只要执行脚本,就会自动执行集成第三方框架的命令。
sh
:sheel脚本文件后缀名
二、下载ijkPlayer
- 去到B站得github主页,找到ijkplayer项目,下载源码 ijkplayer下载地址
- 打开Demo,查看用法,
一般学习第三方库,都是先查看Demo
Snip20160825_4.png
三、编译ijkPlayer的步骤
1、找到ijkPlayerMediaDemo并运行
- 提示
'libavformat/avformat.h' file not found
原因
:因为libavformat是ffmpeg中的库,而ijkplayer是基于ffmpeg这个库的,因此需要导入ffmpeg
解决
:查看ijkplayer的README.md,一般都会有说明。
init-ios.sh
脚本的作用:下载ffmpeg源码
- 想了解脚本具体怎么做的,可以查看之前写的文章带你走进脚本世界,ijkplayer之【init-ios.sh】脚本分析,全面剖析了
init-ios.sh
这个脚本做了哪些事情。
如何执行init-ios.sh
脚本文件
-
步骤一:
找到init-ios.sh脚本文件
-
步骤二:
打开终端,cd进入到ijkplayer-master的目录中
- 注意是 cd 这个文件夹
-
步骤三:
输入./init-ios.sh,就会执行当前脚本了。
- 执行完脚本后,就会发现ijkplayer中有
ffmpeg
了
2、下载好ffmpeg源码后,再次运行Demo
- 发现还是报
'libavformat/avformat.h' file not found
错误 -
原因
:执行init-ios.sh,仅仅是下载源码
,但是源码并没有参与编译,需要把源码编译成.a文件- Demo依赖于IJKMediaPlayer库
- 打开 IJKMediaPlayer库,查看下源码
-
打开 IJKMediaPlayer库
IJKMediaPlayer源码.png -
右击,发现FFMPEG中的库都是红的,表示不存在
Snip20160829_23.png -
解决
:查看ijkplayer的README.md
编译ffmpeg库
- 步骤一:进入到
脚本文件
的目录下
cd ios.png
- 步骤二:执行
./compile-ffmpeg.sh clean
- 步骤二功能:删除一些文件和文件夹,为编译ffmpeg.sh做准备,在编译ffmpeg.sh的时候,会自动创建刚刚删除的那些文件,为避免文件名冲突,因此在编译ffmpeg.sh之前先删除等会会自动创建的文件夹或者文件
- 步骤三:执行./compile-ffmpeg.sh all,真正的编译各个平台的ffmpeg库,并生成所以平台的通用库.
执行compile-ffmpeg.sh all前
编译前.png执行compile-ffmpeg.sh all后
编译后.png3.再次运行Demo,就能成功了,因为IJKMediaPlayer库获取到ffmpeg库了
-
编译完ffmpeg后,IJKMediaPlayer库中显示
成功获取到ffmpeg库.png -
cmd+r,Demo运行成功
四、如何集成到ijkplayer到自己的项目中
- 注意:
ijkplayer
的README
中的方法比较麻烦,不方便携带,不推荐。
1.推荐自己把IJKMediaPlayer打包成静态库,在导入到自己的项目中。
- 如何打包,请参考,iOS中集成ijkplayer视频直播框架,写的非常不错,就不一一详细介绍了,但是
只有发布版本的库
。 - 我自己打包了ijkplayer两个版本库,分别用于调试和发布(DEBUG和Release),点击下载
- 由于文件太大上传不了GitHUb,就上传到百度云了
2.直接把ijkplayer库拖入到自己的工程中,
- 调试的话,拖入调试版本的ijkplayer库,发布的话,拖入发布版本的ijkplayer库
3.导入ijkplayer依赖的库,具体可以查看ijkplayer的README
Snip20160829_6.png Snip20160829_7.png五、使用ijkplayer直播
1.ijkplayer用法简介
- ijkplayer用法比较简单,其实只要有直播地址,就能直播了
- 注意:最好
真机测试
,模拟器测试比较卡,不流畅
,真机就没有问题了
2.抓取数据
- 抓了很多直播app的数据,发现映客主播的质量是最高的。
- 映客主播url:http://116.211.167.106/api/live/aggregation?uid=133825214&interest=1
- uid=账号ID,这里是我的账号ID
- interest=兴趣 ,1表示只查看女生,哈哈
- 上下拉刷新的接口没抓到,就一下加载200条数据,哈哈
- (void)loadData
{
// 映客数据url
NSString *urlStr = @"http://116.211.167.106/api/live/aggregation?uid=133825214&interest=1";
// 请求数据
AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
mgr.responseSerializer = [AFJSONResponseSerializer serializer];
mgr.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", nil];
[mgr GET:urlStr parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary * _Nullable responseObject) {
_lives = [YZLiveItem mj_objectArrayWithKeyValuesArray:responseObject[@"lives"]];
[_tableView reloadData];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"%@",error);
}];
}
3.获取拉流url,直播
-
IJKFFMoviePlayerController
:用来做直播的类
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
// 设置直播占位图片
NSURL *imageUrl = [NSURL URLWithString:[NSString stringWithFormat:@"http://img.meelive.cn/%@",_live.creator.portrait]];
[self.imageView sd_setImageWithURL:imageUrl placeholderImage:nil];
// 拉流地址
NSURL *url = [NSURL URLWithString:_live.stream_addr];
// 创建IJKFFMoviePlayerController:专门用来直播,传入拉流地址就好了
IJKFFMoviePlayerController *playerVc = [[IJKFFMoviePlayerController alloc] initWithContentURL:url withOptions:nil];
// 准备播放
[playerVc prepareToPlay];
// 强引用,反正被销毁
_player = playerVc;
playerVc.view.frame = [UIScreen mainScreen].bounds;
[self.view insertSubview:playerVc.view atIndex:1];
}
4.结束播放
- 界面不播放,一定要记得结束播放,否则会报内存溢出
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// 界面消失,一定要记得停止播放
[_player pause];
[_player stop];
}
结束语
后续还会更新更多有关直播的资料,希望做到教会每一个朋友从零开始做一款直播app,并且Demo也会慢慢完善.
Demo点击下载
- 由于FFMPEG库比较大,大概100M。
- 本来想自己上传所有代码了,上传了1个小时,还没成功,就放弃了。
- 提供另外一种方案,需要你们自己导入IJKPlayer库
具体步骤:
- 下载Demo后,打开YZLiveApp.xcworkspace问题
- pod install就能解决
- 下载jkplayer库,点击下载
- 把jkplayer直接拖入到与Classes同一级目录下,直接运行程序,就能成功了
- 注意不需要
打开工程,把jkplayer拖入到工程中
,而是直接把jkplayer库拷贝到与Classes同一级目录下就可以了。 - 错误示范:
不要向下面这样操作
网友评论
./libavutil/arm/asm.S:50:9: error: unknown directive
.arch armv7-a
解决方法:
在 compile-ffmpeg.sh 中将FF_ALL_ARCHS_IOS8_SDK="armv7 i386 x86_64"
修改为:FF_ALL_ARCHS_IOS8_SDK="arm64 i386 x86_64"
armv7/config.h 找不到的错误
# if defined(__ARM_ARCH_7S__)
# include "armv7s/config.h"
# elif defined(__ARM_ARCH)
# if __ARM_ARCH == 7
# include "arm64/config.h"
# else
# error Unsupport ARM architecture
# endif
# else
# error Unsupport ARM architecture
# endif
我在里边也修改了下 才能运行 不知道会不会出现其他问题
ld: library not found for -lcrypto
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I===== custom modules begin =====
register demuxer : ijklivehook
===== custom modules end =====
av_version_info: ff3.1--ijk0.6.0--20160718--001
ijkmp_set_inject_opaque(0x7ff5477136d0)
ijkmp_set_inject_opaque()=void
2018-01-04 16:49:28.942604+0800 bilibili[6448:2284590] OK setup GL
ijkmp_ios_set_view(glView=0x7ff54761cdf0)
ijkmp_ios_set_view(glView=0x7ff54761cdf0)=void
ijkmp_set_data_source(url="http://qqpull.inke.cn/live/1515052239109266.flvikDnsOp=1&ikHost=tx&ikOp=0&codecInfo=8192&ikMinBuf=3000&ikMaxBuf=8000&ikSlowRate=0.9&ikFastRate=1.1&dpSrc=6";)
ijkmp_set_data_source(url="http://qqpull.inke.cn/live/1515052239109266.flvikDnsOp=1&ikHost=tx&ikOp=0&codecInfo=8192&ikMinBuf=3000&ikMaxBuf=8000&ikSlowRate=0.9&ikFastRate=1.1&dpSrc=6";)=0
ijkmp_prepare_async()
ijkmp_prepare_async()=0
2018-01-04 16:49:28.978713+0800 bilibili[6448:2284590] invalidateRenderBuffer
2018-01-04 16:49:28.978843+0800 bilibili[6448:2285070] IJKSDLGLView: setupDisplay not ready
hahadeMacBook-Pro:ios Robin$ ./compile-ffmpeg.sh all
====================
[*] check xcode version
====================
FF_ALL_ARCHS = armv7 arm64 i386 x86_64
====================
[*] check host
====================
FF_ARCH=armv7
FF_BUILD_OPT=
tools/do-compile-ffmpeg.sh: line 53: /Users/haha/Desktop/ijkplayer-master: No such file or directory
NSString *flv = @"http://pull2.inke.cn/live/1509344911708023.flv?ikHost=ws&ikOp=1&codecInfo=8192";;
IJKFFMoviePlayerController *moviePlayer = [[IJKFFMoviePlayerController alloc] initWithContentURLString:flv withOptions:nil];
moviePlayer.view.frame = [[UIScreen mainScreen] bounds];
[moviePlayer prepareToPlay];
_moviePlayer = moviePlayer;
[self.view insertSubview:moviePlayer.view atIndex:1];
只有声音没有画面,知道是什么问题吗?
<项目名称> was compiled with optimization - stepping may behave oddly; variables may not be available.
https://coding.net/u/wanglei123/p/ijkplayerDemo/git
Demo里边“采集”切换摄像头后有点问题,视频连接为空,输出数据代理里边都变成音频了
if (_videoConnection == connection) {
NSLog(@"采集到视频数据");
} else {
NSLog(@"采集到音频数据");
}
在高分辨率图像不进行压缩,就可以了。
[[SDImageCache sharedImageCache] setShouldDecompressImages:NO];
[[SDWebImageDownloader sharedDownloader] setShouldDecompressImages:NO];
xcrun -sdk iphoneos clang is unable to create an executable file.
C compiler test failed.
找了好多资料也没解决
C compiler test failed.
If you think configure made a mistake, make sure you are using the latest
version from Git. If the latest version fails, report the problem to the
ffmpeg-user@ffmpeg.org mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file "config.log" produced by configure as this will help
solve the problem.
sunyayongdeMacBook-Pro:~ Yaya$ cd /Users/Yaya/Desktop/ijkplayer-master
sunyayongdeMacBook-Pro:ijkplayer-master Yaya$ ./init-ios.sh
git version 2.9.3 (Apple Git-75)
== pull gas-preprocessor base ==
Fetching origin
/Users/Yaya/Desktop/ijkplayer-master
== pull ffmpeg base ==
Cloning into 'extra/ffmpeg'...
remote: Counting objects: 494447, done.
error: RPC failed; curl 56 SSLRead() return error -98064 bytes/s
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed
sunyayongdeMacBook-Pro:ijkplayer-master Yaya$
一直下载出错
Cloning into 'extra/ffmpeg'...
remote: Counting objects: 494425, done.
remote: Compressing objects: 100% (85/85), done.
error: RPC failed; curl 56 SSLRead() return error -36.00 KiB/s
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed
怎么解决呢, 峥哥.
Cloning into 'extra/ffmpeg'...
remote: Counting objects: 494425, done.
remote: Compressing objects: 100% (85/85), done.
error: RPC failed; curl 56 SSLRead() return error -36536.00 KiB/s
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed
这个./init-ios.sh下不了 是我这边原因??
remote: Counting objects: 493518, done.
error: RPC failed; curl 56 SSLRead() return error -360.00 KiB/s
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed
有什么解决的方法吗
xcrun -sdk iphoneos clang is unable to create an executable file.
C compiler test failed.
______./compile-ffmpeg.sh all出错, 也查看了git的issue仍然无法解决......., 不知道有没有遇到同样的问题的呢,?????
fatal: early EOF
fatal: index-pack failed 然后ffmpeg没下载成功。怎么回事了
invalidateRenderBuffer
setupDisplay not ready
invalidateRenderBuffer
"_inflate", referenced from:
_http_read_stream in IJKMediaFramework(http.o)
_rtmp_open in IJKMediaFramework(rtmpproto.o)
"_inflateEnd", referenced from:
_http_close in IJKMediaFramework(http.o)
_http_read_header in IJKMediaFramework(http.o)
_rtmp_open in IJKMediaFramework(rtmpproto.o)
"_inflateInit2_", referenced from:
_http_read_header in IJKMediaFramework(http.o)
"_inflateInit_", referenced from:
_rtmp_open in IJKMediaFramework(rtmpproto.o)
"_uncompress", referenced from:
_id3v2_read_internal in IJKMediaFramework(id3v2.o)
_mov_read_cmov in IJKMediaFramework(mov.o)
"_zlibCompileFlags", referenced from:
_http_read_header in IJKMediaFramework(http.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
峥哥,按照你的详细解答,从编译demo到运行都很顺利,将IJKMediaFramework 拖到自己的工程中,就报了这个错,不知道咋解决
----------------------
C compiler test failed.
If you think configure made a mistake, make sure you are using the latest
version from Git. If the latest version fails, report the problem to the
ffmpeg-user@ffmpeg.org mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file "config.log" produced by configure as this will help
solve the problem.
ps:期待大神把直播功能早早完善 好让我等膜拜学习