背景: 去年下半年由于种种因素驱动下,准备去考研,在之前同事的推荐下,参加了考研培训班,培训班发了纸质书籍和线上视频观看账号,由于线上视频需要全程联网才能观看,突发奇想,要是我把这些视频下载下来,没网的时候也能拿出来观看复习多好; 在此背景下,花了几天时间简单做了一个app出来辅助复习,前段时间通过了考研复试,这几天利用空闲时间,完善了app功能,同时记录下开发过程和一些感悟;
效果:
功能简单介绍: 在线播放(下载).m3u8视频,PC浏览器查看和离线观看!
注意: 由于涉及到培训班视频的隐私问题,这里不给出视频播放画面,敬请谅解!
如何实现?
市面上众多培训班的视频一般都不是普通的.mp4视频,很多都是经过了加密或者非专业人士知道的特殊视频格式, 工作期间经常使用抓包工具,我想先试下抓包看看,说不定可以了解到一些信息,从而启发下一步,好,说干就干....
在用charles抓包的时候,发现截图该域名下不断的有新请求产生,有一个.M3U8请求地址,还有不断产生的.ts.ts请求地址, 网上搜索相关文章,茅塞顿开,实现起来并不复杂。
涉及到的技术实现网上文章很多,当时备考时间短,我把自己的核心需求理了下,网上找相关"轮子",有满足自己的需要就直接拿来组装了 ,哈哈
技术要点
一.iOS音视频播放
iOS音视频播放技术现在很成熟了,之前在项目中有涉及到视频播放相关处理的功能,代码中主要使用的类是AVPlayer,个人建议首先看苹果文档,最全面最权威的了,网上找到的不够全面,要综合不同文章才能全面些,打开位置Xcode-Window-Developer Documentation,搜索类名
官方说明该类可用来处理本地和远程基于文件的媒体播放,例如quiktime电影,mp3音频文件,以及使用HLS直播提供的视听媒体; 使用该对象就可以直接播放前面说的.m3u8文件了;
不过这样会存在一个问题,当网络不好的时候,体验就很糟糕了,而且也不能离线观看; 看能不能处理成常用的.mp4文件,方便保存和离线观看?
基本思路是: 批量下载.ts.ts文件=》合并文件=>转码成.mp4
批量下载ts.ts文件就基本的文件网络下载思路了
合并文件: 用一个NSMutableData来存储合并后的文件数据,循环读取每一个.ts片段数据,追加到NSMutableData
转码成.mp4: 这一步需要用到FFmpeg框架来做,对应的iOS库,一般可采用命令行的方式进行调用,这里的转码示例如下:
调用方式即:
ffmpeg -ss 00:00:00 -i 源文件.ts文件路径 -b:v 2000K -y 目标.mp4文件路径
存在一个问题,我转码出来,发现.mp4视频文件出奇的大,724MB,而.ts源文件才70MB左右,如果我把培训班的视频都下载下来了,那占用手机空间就会很大,我用的手机是128GB,剩余空间也就不到15GB 。
我把参数都去掉,用默认的
ffmpge -i <in file> <output file>
转码出来是180MB左右,不同命令参数转码出来的文件大小相差很大,这涉及到对ffmpeg的理解和一些音视频的概念基础知识了。
关于.ts转.mp4的各种命令也很多,我上网找到如下命令行:
覆盖目标文件,使用h264_mp4toannexb,使用源文件声音编解码器,视频编解码器
ffmpeg -y -i <in file> -vcodec copy -acodec copy -vbsf h264_mp4toannexb <output file>
源文件开头到末尾,目标文件视频的码率设置为2000kbps ffmpeg -ss 00:00:00 -i <in file> -b:v 2000K -y <output file>
ffmpeg -y -i <in file> -c:v libx264 -c:a copy -bsf:a aac_adtstoasc <output file>
iOS里使用ffmpeg命令行的代码,涉及到一些objective-c调c语言的方式,分享下
//输入源文件沙盒路径 char* input=(char*) [inputPath UTF8String]; //输出目标文件沙盒路径 char* output= (char*)[outpath UTF8String]; //ffmpeg命令 char* a[]={"ffmpeg","-y","-i",input,output}; //开始调起ffmpeg ffmpeg_main(sizeof(a)/sizeof(*a),a);
基本概念
1.视频和视频格式的说明
视频是N多张图片的集合,播放视频本职其实就是连续播放"很多"张图片,其播放每张图片的时间间隔非常的短,我们把每一张图片称为每一帧,每一帧图片有多少像素,称为这张图像的分辨率,比如我们有一个1.mp4视频文件,它的分辨率就是每一帧图像的分辨率;
拿到一个视频文件,我们除了知道常见的分辨率和封装格式外,诸如帧率,码率最好也了解一下; 帧率说明视频单位时间1秒内可以播放多少张图像,视频的帧率可以是恒定的,也可以是动态的,码率说明单位时间内记录视频数据的总量,比如一个24分钟,900MB的视
频,其码率为7200MBit/1440s=5000Kbps=5Mbps,单位一般是kbit/s或者Mbi