![](https://img.haomeiwen.com/i791315/353dcf1dd8ccc62c.jpeg)
前言
虽然我不同意你的观点 但我誓死捍卫你说话的权利!--伏尔泰
很长时间没有写文章了,这个题目其实我很早就想动笔写了,因为从我第一个完整的APP项目开始,几乎每一个APP都有视频播放的需求,但是我却迟迟不敢动笔,因为我觉得关于视频播放的底层技术实现我还是一知半解。但还是写下了这篇,希望路过的大神可以不吝赐教,也希望和我一样正在进步的人可以有所收益,少走弯路,看完这篇文章以后可以选择最适合自己的技术实现方案。
青铜时代
还记得刚学iOS的时候吗?那个时候惊讶于各种牛逼的功能只需要几句简单的代码就可以完成。视频播放也是这样,翻开几本陈旧的iOS教材,你就可以在目录里看到它。没错,它就是:
<MediaPlayer/MediaPlayer.h>
在MediaPlayer框架中,如果你足够懒,那么利用MPMoviePlayerViewController你便可以三行代码完成你的播放功能。然而,抬头看看各大视频APP,他们的播放界面是这样的:
![](https://img.haomeiwen.com/i791315/31a06bc9aaa58191.jpg)
低头看看自己的播放器,却是这样的:
![](https://img.haomeiwen.com/i791315/074264e04aed0d01.png)
妈蛋,好Low啊有木有,是可忍孰不可忍!好在Apple官方还给我们提供了一个类MPMoviePlayerController,通过这个类我们可以自定义播放器的UI,在这里推荐一款由国内工程师开源的基于MPMoviePlayerController播放器KRVideoPlayer,相信小伙伴们的大多数数的需求可以完美的解决。
工业时代
历史的车轮滚滚向前,永不停歇、
然而MPMoviePlayerController自定义播放器并不是完美的:
- MPMoviePlayerController在iOS9被Apple废弃了;
- 当我们的需求需要深度定制播放器的时候,MPMoviePlayerController就显得力不从心了,比如笔者之前在做一个配音软件时,需要只播放视频的画面,而不需要视频的声音,同时还需要开启音频的录制,以及另开一个音频播放器播放背景音效。这个时候,MPMoviePlayerController哭了。
鉴于<MediaPlayer/MediaPlayer.h>的局限性,新的框架应运而生--AVKit。
AVKit是建立在AVFoundation上,解决视频播放的高级对象。从AVFoundation Programming Guide中我们可以看到这样一张技术栈示意图:
![](https://img.haomeiwen.com/i791315/aad85e00404ba462.png)
如果有人记得AVFoundation刚出那年的WWDC的话,一定对AVFoundation的性能表现印象深刻,同时播放100部视频而丝毫不卡顿!在笔者的使用过程中也验证了这一点,无论是对于本地视频还是网络在线点播,AVFoundation表现都异常优异。
我们先来看看AVKit的结构:
![](https://img.haomeiwen.com/i791315/e4cbbd0d8012969e.png)
由于本篇只是起一个“导购”的作用,而且关于AVKit的相关文章文档多如牛毛因此便不再介绍。下面推荐几个基于AVKit的第三方视频框架:
后工业时代
然而,凡事总会有一个然而,AVKit也并非完美无瑕,当我们需要播放一些非常规格式的视频的时候(比如RMVB),AVKit又只能望洋兴叹了。
相信Mac用户都很熟悉一款VLC播放器,这款播放器在Mac上表现异常优异,支持的格式几乎涵盖了所有格式(就是这么屌!)。没错,就是它创造者--VideoLAN,开源了一款牛逼的视频播放框架MobileVLCKit!
我们先来看看它所支持的格式:
*.rmvb *.asf *.avi *.divx *.dv *.flv *.gxf *.m1v *.m2v *.m2ts *.m4v *.mkv *.mov *.mp2 *.mp4 *.mpeg *.mpeg1 *.mpeg2 *.mpeg4 *.mpg *.mts *.mxf *.ogg *.ogm *.ps *.ts *.vob *.wmv *.a52 *.aac *.ac3 *.dts *.flac *.m4a *.m4p *.mka *.mod *.mp1 *.mp2 *.mp3 *.ogg.
是不是很心动呢?那我们就开始吧!
1. 框架编译
在Show you code之前,我们总需要先有它的库吧?官方给出了详细的教程,英文不好?翻墙网速不好?没关系!这里有编译完成的VLC框架,下载下来就好啦!
2.项目编译
MobileVLCKit的静态库非常大,解压下来以后差不多有600+MB,但是编译之后只有几M而已,所以放心使用吧。
-
Linked Frameworks and Libraries中添加下载完成的MobileVLCKit;
-
添加依赖框架,MobileVLCKit依赖于以下的框架:
![](https://img.haomeiwen.com/i791315/c1badf2a702e5675.png)
- 修改编译选项,由于该框架底层由C++所编写,所以我们需要更改相关的编译选项;
![](https://img.haomeiwen.com/i791315/745a5643b6b6d608.png)
- 修改Framework Search Paths,否则工程无法找到该框架;
![](https://img.haomeiwen.com/i791315/c07821131c515441.png)
PS: "std::ios_base::Init::~Init()", referenced from
出现这样的编译问题,是需要再加进libstdc++.dylib和libstdc++.6.dylib(为6.1使用,xcode5以后默认complier也可以编译通过)
OK!不错意外的话,CMD + B编译成功了!
为了抛砖引玉,献上我自己基于MobileVLCKit写的播放器:MRVLCPlayer,本来我只是想做一个Demo的,但是做着做着想做成一个框架,现在还有很多功能没有完善,但是作为一个Demo应该是够用了。
![](https://img.haomeiwen.com/i791315/c3151dfe38a0e0dd.gif)
信息时代
当然啦,如果你懂得一些视频解码更专业的知识,你还可以使用ffmpeg和live555,这样可以更加底层的学习视频相关的技术。当然啦,博主现在也在学习这方面的知识,在此只是推荐给大家,顺便悄悄的说一句,其实MobileVLCKit也是基于ffmpeg二次开发的。
石器时代后记
无论多么牛逼多么晦涩难懂的技术,最终的目的都是服务于人。人类从石器时代进化到如今,手中的工具换了一茬又一茬,一味的炫技没有任何意义,选择适合自己的工具才是正道。我相信,百分之九十以上的需求,在本文的信息时代之前都能解决,选择权在你的手中。好了不说了,我要把我旁边的母猿打晕拖进洞穴了,我们下次见~
网友评论
"_VTIsHardwareDecodeSupported", referenced from:
_OpenDecoder in MobileVLCKit(libvideotoolbox_plugin_la-videotoolbox.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
请问楼主,这个问题怎么解决
shader program 1: WARNING: Output of vertex shader 'TexCoord1' not read by fragment shader
WARNING: Output of vertex shader 'TexCoord2' not read by fragment shader
我集成成功了,可是播放avi没有声音
楼楼有没有什么建议呀 我查资料也没找到有效的解决办法
初始化后的日志:
2017-09-07 16:00:05.419949+0800 jiaPei[2069:705365] creating player instance using shared library
[000000010ee07d68] core generic error: option marq-color does not exist
[000000010ee07d68] core generic error: option marq-opacity does not exist
[000000010ee07d68] core generic error: option marq-position does not exist
[000000010ee07d68] core generic error: option marq-refresh does not exist
[000000010ee07d68] core generic error: option marq-size does not exist
[000000010ee07d68] core generic error: option marq-timeout does not exist
[000000010ee07d68] core generic error: option marq-x does not exist
[000000010ee07d68] core generic error: option marq-y does not exist
[000000010d712398] http access error: seek too far
2017-09-07 16:00:07.943686+0800 jiaPei[2069:705770] Metal GPU Frame Capture Enabled
2017-09-07 16:00:07.945175+0800 jiaPei[2069:705770] Metal API Validation Enabled
2017-09-07 16:00:08.002795+0800 jiaPei[2069:705770] libMobileGestalt MobileGestaltSupport.m:153: pid 2069 (jiaPei) does not have sandbox access for frZQaeyWLUvLjeuEK43hmg and IS NOT appropriately entitled
2017-09-07 16:00:08.002871+0800 jiaPei[2069:705770] libMobileGestalt MobileGestalt.c:550: no access to InverseDeviceID (see <rdar://problem/11744455>)
shader program 1: WARNING: Output of vertex shader 'TexCoord1' not read by fragment shader
WARNING: Output of vertex shader 'TexCoord2' not read by fragment shader
视频自动结束前的日志
[000000010d712398] core access error: read error: Connection reset by peer
[h264 @ 0x104a57400] AVC: nal size 240047
[h264 @ 0x104a57400] AVC: nal size 240047
[h264 @ 0x104a57400] no frame!
[000000010d712398] http access error: seek failed
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x1049f4e00] stream 1, offset 0x59b39a: partial file
//http://120.25.226.186:32812/resources/videos/minion_02.mp4
//http://flv3.bn.netease.com/videolib3/1707/27/uwUMB9833/SD/uwUMB9833-mobile.mp4
player.mediaURL = [NSURL URLWithString:[string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
但出現了一個問題
多次來回播放後「Terminated due to memory issue」
閃退了,內存泄露的原因完全找不到....求救
报错控制台输出: MRVLCPlayer was compiled with optimization - stepping may behave oddly; variables may not be available.
2017-02-13 16:21:43.069536 MRVLCPlayer[407:86881] creating player instance using shared library
进度条一直转,请问楼主怎么解决?
clang: warning: libstdc++ is deprecated; move to libc++
ld: '/Users/wangchong/Desktop/qiutu/qiutu/MobileVLCKit.framework/MobileVLCKit(audio.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)请问是怎么回事
UIView *playView = [[UIView alloc]initWithFrame:CGRectMake(0, 64, kScreenWidth, 300)];
// playView.backgroundColor = [UIColor redColor];
[self.view addSubview:playView];
[playView setAutoresizingMask:UIViewAutoresizingFlexibleWidth ];
//创建视频播放控制者
self.viewPlayer = [[VLCMediaPlayer alloc]init];
self.viewPlayer.delegate =self;
VLCMedia *media = [VLCMedia mediaWithPath:[[NSBundle mainBundle] pathForResource:@"02" ofType:@"mov"]];
self.viewPlayer.media = media;
self.viewPlayer.drawable=playView;
[self.viewPlayer play];
楼主能帮我看一下吗?怎么都播放不出来
creating player instance using shared library
[00007fc18a63d228] core generic error: option marq-color does not exist
[00007fc18a63d228] core generic error: option marq-opacity does not exist
[00007fc18a63d228] core generic error: option marq-position does not exist
[00007fc18a63d228] core generic error: option marq-refresh does not exist
[00007fc18a63d228] core generic error: option marq-size does not exist
[00007fc18a63d228] core generic error: option marq-timeout does not exist
[00007fc18a63d228] core generic error: option marq-x does not exist
[00007fc18a63d228] core generic error: option marq-y does not exist
博主,我这个是为什么呀?~~url绝对没问题。
shader program 1: WARNING: Output of vertex shader 'TexCoord1' not read by fragment shader
WARNING: Output of vertex shader 'TexCoord2' not read by fragment shader
-> 0x1142fe867 <+0>: pushq %rbp
0x1142fe868 <+1>: movq %rsp, %rbp
0x1142fe86b <+4>: pushq %r15
0x1142fe86d <+6>: pushq %r14
0x1142fe86f <+8>: pushq %r12
0x1142fe871 <+10>: pushq %rbx
0x1142fe872 <+11>: movq %rdx, %r14
0x1142fe875 <+14>: movq %rsi, %r15
0x1142fe878 <+17>: movq %rdi, %rbx
0x1142fe87b <+20>: callq 0x1142fe475 ; __cxa_get_globals
0x1142fe880 <+25>: movq %rax, %r12
0x1142fe883 <+28>: callq 0x1142fee20 ; std::get_unexpected()
0x1142fe888 <+33>: movq %rax, -0x60(%rbx)
0x1142fe88c <+37>: callq 0x1142fee53 ; std::get_terminate()
0x1142fe891 <+42>: movq %rax, -0x58(%rbx)
0x1142fe895 <+46>: movq %r15, -0x70(%rbx)
0x1142fe899 <+50>: movq %r14, -0x68(%rbx)
0x1142fe89d <+54>: leaq -0x20(%rbx), %r14
0x1142fe8a1 <+58>: movabsq $0x434c4e47432b2b00, %rax ; imm = 0x434C4E47432B2B00 这里breakpotion
Undefined symbols for architecture x86_64:
"_VTDecompressionSessionCreate", referenced from:
_StartVideoToolbox in MobileVLCKit(videotoolbox.o)
"_VTDecompressionSessionDecodeFrame", referenced from:
_DecodeBlock in MobileVLCKit(videotoolbox.o)
"_VTDecompressionSessionInvalidate", referenced from:
_StopVideoToolbox in MobileVLCKit(videotoolbox.o)
"_VTDecompressionSessionWaitForAsynchronousFrames", referenced from:
_OpenDecoder in MobileVLCKit(videotoolbox.o)
_CloseDecoder in MobileVLCKit(videotoolbox.o)
"_iconv", referenced from:
_sub_recode in MobileVLCKit(ass.o)
_print_unicode in MobileVLCKit(exp-txt.o)
_vlc_iconv in MobileVLCKit(libc.o)
_vbi_ucs2be in MobileVLCKit(export.o)
_smb_iconv in MobileVLCKit(smb_utils.o)
_iconv_ucs2 in MobileVLCKit(conv.o)
__vbi_iconv_open in MobileVLCKit(conv.o)
...
(maybe you meant: _vbi_fputs_iconv_ucs2, _vbi_strndup_iconv_caption , __vbi_iconv_open , __vbi_iconv_close , _vbi_export_puts_iconv_ucs2 , __vbi_strndup_iconv , __vbi_iconv_ucs2 , _vbi_strndup_iconv_ucs2 , _vbi_fputs_iconv , _vbi_export_puts_iconv , _vlc_iconv , _vlc_iconv_open , _vbi_strndup_iconv , _vlc_iconv_close )
"_iconv_close", referenced from:
_sub_recode in MobileVLCKit(ass.o)
_vbi_print_page_region in MobileVLCKit(exp-txt.o)
_export in MobileVLCKit(exp-txt.o)
_vlc_iconv_close in MobileVLCKit(libc.o)
_vbi_ucs2be in MobileVLCKit(export.o)
_smb_iconv in MobileVLCKit(smb_utils.o)
__vbi_iconv_close in MobileVLCKit(conv.o)
...
(maybe you meant: __vbi_iconv_close, _vlc_iconv_close )
"_iconv_open", referenced from:
"_merge16_arm64_neon", referenced from:
_Open in MobileVLCKit(libdeinterlace_plugin_la-deinterlace.o)
"_merge8_arm64_neon", referenced from:
_Open in MobileVLCKit(libdeinterlace_plugin_la-deinterlace.o)
ld: symbol(s) not found for architecture arm64
是什么原因呢,怎么解决啊
Undefined symbols for architecture arm64: "_merge16_arm64_neon", referenced from: _Open in MobileVLCKit(libdeinterlace_plugin_la-deinterlace.o) "_merge8_arm64_neon", referenced from: _Open in MobileVLCKit(libdeinterlace_plugin_la-deinterlace.o) ld: symbol(s) not found for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
creating player instance using shared library
shader program 1: WARNING: Output of vertex shader 'TexCoord1' not read by fragment shader
WARNING: Output of vertex shader 'TexCoord2' not read by fragment shader
"_merge16_arm64_neon", referenced from:
_Open in MobileVLCKit(libdeinterlace_plugin_la-deinterlace.o)
"_merge8_arm64_neon", referenced from:
_Open in MobileVLCKit(libdeinterlace_plugin_la-deinterlace.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
请问楼主,这个是什么问题?
我看楼主的demo工程是这样设置的,但是我的编译报错 100多个错误
/Desktop/02_Libs/MobileVLCKit.framework/MobileVLCKit(ios2.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture armv7
我看了下我的bitcode是YES,如果改成NO的话有100多个错误。。。全是c的错误