我的播放器——使用Vitamio开发iOS平台上的万能播放器(1)

2023-11-21 07:10

本文主要是介绍我的播放器——使用Vitamio开发iOS平台上的万能播放器(1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

迅速了解

    Vitamio是干什么的?看官方怎么说:

   “Vitamio SDK for iOS是Yixia Ltd官方推出的 iOS 平台上使用的软件开发工具包(SDK),为iOS开发者提供简单、快捷的接口,帮助开发者实现 iOS 平台上的媒体播放应用。”

    说白了,就是可以帮助你便捷地开发自己的iOS播放器。

本文目标

    从0开始建工程,使用VitamioSDK开发一个最简单的播放器:打开app之后,能看到一个播放按钮,点击按钮,就开始播放事先放在Documents目录下的视频文件,再按一下按钮可以暂停。

    就这么简单。

准备工作

    下载Vitamio SDK:

    https://github.com/yixia/Vitamio-iOS

    当前版本是4.2.0。上个版本是1.1.3,这跳跃也太大了吧?估计是为了和安卓的Vitamio SDK保持同步。

    压缩包解压后内容如下:


    Doc放文档,用浏览器打开Doc/html/index.html可查看Vitamio官方文档(还是苹果官方文档的风格哦)。各种接口什么的貌似齐全,但全英文看着有点眼花啊。

    Demo放了一个直接编译就能运行的工程,可以播放多个在线视频。你要是乐意,完全可以照着这个demo改造成自己想要的app。

    Vitamio放的就是我们将要用到的SDK。

具体步骤

    本文用于调试的真机是ipod touch5,系统是iOS7.0.4。

新建工程

    新建一个Single View工程


    起个名字叫myPlayer



简单UI

在storyboard中拖放三个控件,分别是UILabel,用于展示视频名称;UIView用于承载播放画面,UIButton用于播放或暂停。


    按钮的default状态显示“播放”,selected状态显示“暂停”:

    建立控件与变量的连接:

UILabel是lblTitle

UIView是playerView

UIButton是btnPlayOrPause,点击事件是btnPlayOrPauseClick

再加一个NSString变量存视频地址

目前看起来这样:

@interface iTechBlueViewController : UIViewController
{NSString* videoPath;
}
@property (weak, nonatomic) IBOutlet UILabel *lblTitle;
@property (weak, nonatomic) IBOutlet UIView *playerView;
@property (weak, nonatomic) IBOutlet UIButton *btnPlayOrPause;
- (IBAction)btnPlayOrPauseClick:(id)sender;
@end

检测视频文件

我们要遍历Documents文件夹下的文件,将找到的第一个视频文件的地址记住,并将其名称显示在UILabel上。

-(NSString*)findVideoInDocuments
{NSString *documentsDirectory = [NSString stringWithFormat:@"%@/Documents", NSHomeDirectory()];NSFileManager *fileMg = [[NSFileManager alloc] init];//遍历Documents下的文件,找到视频文件就返回它的全路径NSArray *subPaths = [fileMg contentsOfDirectoryAtPath:documentsDirectory error:nil];if (subPaths) {for (NSString *subPath in subPaths) {if ( [self isMediaFile:[subPath pathExtension]]) {NSString *path = [documentsDirectory stringByAppendingPathComponent:subPath];return path;}}}return nil;
}

-(BOOL)isMediaFile:(NSString*)pathExtension
{//可用格式/*".M1V", ".MP2", ".MPE", ".MPG", ".WMAA",".MPEG", ".MP4", ".M4V", ".3GP", ".3GPP", ".3G2", ".3GPP2", ".MKV",".WEBM", ".MTS", ".TS", ".TP", ".WMV", ".ASF", ".ASX", ".FLV",".MOV", ".QT", ".RM", ".RMVB", ".VOB", ".DAT", ".AVI", ".OGV",".OGG", ".VIV", ".VIVO", ".WTV", ".AVS", ".SWF", ".YUV"*///简单粗暴地判断是否为视频格式,这里先试6个NSString*ext = [pathExtension uppercaseString];if([ext isEqualToString:@"MP4"]){return YES;}else if([ext isEqualToString:@"MOV"]){return YES;}else if([ext isEqualToString:@"RMVB"]){return YES;}else if([ext isEqualToString:@"MKV"]){return YES;}else if([ext isEqualToString:@"FLV"]){return YES;}else if([ext isEqualToString:@"TS"]){return YES;}return NO;
}

- (void)viewDidLoad
{[super viewDidLoad];videoPath = [self findVideoInDocuments];if(videoPath){_lblTitle.text = [videoPath lastPathComponent];}
}

现在编译一下看看有没有问题吧!

好,虽然没问题,但也只是我们拖出来的那个界面而已。

咱们现在用iFunBox往Documents文件夹下放一个视频吧。

什么!?你还没用过iFunBox?赶紧去下载一个试试,确实能给开发带来便利哦。

我放了一个特小的文件0.ts进去。


再编译试试,这回题目就出来啦!



添加Vitamio并配置工程(or not?)

现在我们已经有了视频文件并且获得了它的具体路径,接着就是要播放它了。开始使用Vitamio!

将上文解压后获得的Vitamio文件夹添加至工程:



添加后如果你手痒编译,竟然发现是能编译成功的!

难道VitamioSDK这么强悍,不需要任何配置就能用了?且往下看。

写播放器代码

引入Vitamio头文件

#import "Vitamio.h"

声明一个播放器变量

VMediaPlayer       *mMPayer;

声明使用播放器协议

<VMediaPlayerDelegate>

以上三行代码写好,Vitamio SDK的各种接口就可以任你调遣了。这是最精简的配置。

VMediaPlayerVMediaPlayerDelegate都藏了什么好东西?我们只能边学变探索。

现在咱们的头文件看起来是这样的:

#import <UIKit/UIKit.h>
#import "Vitamio.h"@interface iTechBlueViewController : UIViewController<VMediaPlayerDelegate>
{NSString* videoPath;VMediaPlayer       *mMPayer;
}
@property (weak, nonatomic) IBOutlet UILabel *lblTitle;
@property (weak, nonatomic) IBOutlet UIView *playerView;
@property (weak, nonatomic) IBOutlet UIButton *btnPlayOrPause;
- (IBAction)btnPlayOrPauseClick:(id)sender;
@end

初始化播放器,以下代码是初始化播放器的最精简写法。

-(void)initPlayer
{if (!mMPayer) {mMPayer = [VMediaPlayer sharedInstance];[mMPayer setupPlayerWithCarrierView:self.playerView withDelegate:self];}
}

可以看到,我们将自己拖到界面上的playerView传了过去,表示要用它来承载视频画面。

准备播放视频,同样,下面代码是 准备播放视频最精简的写法:

-(void)prepareVideo
{if(videoPath){//播放时不要锁屏[UIApplication sharedApplication].idleTimerDisabled = YES; NSURL* videoURL = [NSURL fileURLWithPath:videoPath];[mMPayer setDataSource:videoURL];[mMPayer prepareAsync];}
}

我们的代码写到prepareAsync,就把工作丢给Vitamio了。它会在准备好后在协议方法中通知我们的。

如果这时候你是一副“啥意思”的表情,请看工程的这个地方:


它在警告你:有些method没有实现,那是因为我们引用了VMediaPlayerDelegate之后还没去实现它需要的几个方法:


@required表示,以上三个方法是必须的,我们一一实现之。

首先添加一个布尔变量BOOL didPrepared,它非常重要,是我们的代码首次介入播放器的逻辑。

didPrepared是在Vitamio准备好播放视频后被调用的,我们可以在这时候记录下布尔值——播放准备好了,同时让播放器开始播放:

- (void)mediaPlayer:(VMediaPlayer *)player didPrepared:(id)arg
{//显示“暂停”两字_btnPlayOrPause.selected = YES;didPrepared = YES;[player start];
}

playbackComplete会在视频播放结束后被调用,这时可以记录播放历史、退出播放器什么的,但这里我们要的是最简,所以将播放器重置,从而要再播放的话,就得调用我们写的prepareVideo,这时 didPrepared设为NO。

- (void)mediaPlayer:(VMediaPlayer *)player playbackComplete:(id)arg
{_btnPlayOrPause.selected = NO;[player reset];didPrepared = NO;
}

error会在Vitamio处理视频出错时被调用,让你有机会提醒用户或做其他处理,这里我们只是默默得打一个log:

- (void)mediaPlayer:(VMediaPlayer *)player error:(id)arg
{NSLog(@"VMediaPlayer Error: %@", arg);
}

记得在ViewDidLoad中调用 initPlayer进行初始化,变这样:

- (void)viewDidLoad
{[super viewDidLoad];videoPath = [self findVideoInDocuments];if(videoPath){_lblTitle.text = [videoPath lastPathComponent];[self initPlayer];}
}

如果你想一打开app就播放视频,可以将第一次prepareVideo放在ViewDidAppear中。

在按钮点击中控制播放还是暂停:

- (IBAction)btnPlayOrPauseClick:(id)sender {if(videoPath){BOOL isPlaying = [mMPayer isPlaying];if (isPlaying) {[mMPayer pause];_btnPlayOrPause.selected = NO;} else {if(didPrepared)[mMPayer start];else[self prepareVideo];_btnPlayOrPause.selected = YES;}}
}


这里用Vitamio接口isPlaying来判断是否正在播放是最准确的,比我们自己维护一个播放状态要好。

但视频是否准备好这个状态由我们记录(didPrepared)。

点击播放时比想象中复杂,是因为要判断视频是否已经准备好,如果是的话继续播放,如果没有的话得调用做准备的方法。

写到这,代码好像就完成啦!去编译吧!去启动你写的第一个播放器吧少年!


配置Vitamio

你当时就震惊了。代码写得好顺利,现在一编译,为什么直接就failed了呢?出来50个error!

不用着急这调试,你该记起在VitamioSDK 添加进来后还没有配置吧?

原来还是得配置的,刚才开心得太早。。。

首先需要去Build Phases添加些framework和dylib,如下所示:

文字版如下:

如果你有强迫症,倒序添加下面的库,得到的就是按首字母从小到大排列的顺序

libbz2.dylib
libiconv.dylib
libstdc++.dylib
libz.dylibAVFoundation.framework
AudioToolbox.framework
CoreMedia.framework
CoreVideo.framework
MediaPlayer.framework
OpenGLES.framework
QuartzCore.framework

添加后再编译。

欧耶,编译通过啦!

但是点击播放后会崩溃,有一条log是:

[UIDevice platformString]: unrecognized selector sent to instance
还是不着急调试,去到Build Setting,找到Linking下的Other Linker Flags,添加“-ObjC”:

然后编译再试,oh my god!可以播放啦!

如果这时候你依然很冷静,在思考一个问题:为啥这么一设就好了呢?其实Vitamio sdk作者早已料到你有此一问,你可以在上文提到的Doc文件夹下找到一个FAQ.md文件,里面就专门对这个问题进行了解答。

另外,我不会告诉你,Doc下的 Vitamio_SDK_for_iOS_User_Manual_cn.md是一篇比本博文更简洁但信息足够齐全的中文教程。你值得一读。

多说两句

能够播放和暂停是一个好的开始,但你肯定觉得不够。停止呢?进度控制呢?时长呢?快放呢?后台播放呢?切换上一首下一首呢?截图呢?视频缩略图呢?播放在线视频呢?……

各种播放器该有的功能在以后的博客里都会讲到,敬请期待。

最后,记得设置你工程的version为1.0。

源码在这

https://github.com/itechblue/myPlayer

这篇关于我的播放器——使用Vitamio开发iOS平台上的万能播放器(1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/400690

相关文章

使用Java将实体类转换为JSON并输出到控制台的完整过程

《使用Java将实体类转换为JSON并输出到控制台的完整过程》在软件开发的过程中,Java是一种广泛使用的编程语言,而在众多应用中,数据的传输和存储经常需要使用JSON格式,用Java将实体类转换为J... 在软件开发的过程中,Java是一种广泛使用的编程语言,而在众多应用中,数据的传输和存储经常需要使用j

Nginx使用Keepalived部署web集群(高可用高性能负载均衡)实战案例

《Nginx使用Keepalived部署web集群(高可用高性能负载均衡)实战案例》本文介绍Nginx+Keepalived实现Web集群高可用负载均衡的部署与测试,涵盖架构设计、环境配置、健康检查、... 目录前言一、架构设计二、环境准备三、案例部署配置 前端 Keepalived配置 前端 Nginx

Python logging模块使用示例详解

《Pythonlogging模块使用示例详解》Python的logging模块是一个灵活且强大的日志记录工具,广泛应用于应用程序的调试、运行监控和问题排查,下面给大家介绍Pythonlogging模... 目录一、为什么使用 logging 模块?二、核心组件三、日志级别四、基本使用步骤五、快速配置(bas

使用animation.css库快速实现CSS3旋转动画效果

《使用animation.css库快速实现CSS3旋转动画效果》随着Web技术的不断发展,动画效果已经成为了网页设计中不可或缺的一部分,本文将深入探讨animation.css的工作原理,如何使用以及... 目录1. css3动画技术简介2. animation.css库介绍2.1 animation.cs

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

Python文件操作与IO流的使用方式

《Python文件操作与IO流的使用方式》:本文主要介绍Python文件操作与IO流的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、python文件操作基础1. 打开文件2. 关闭文件二、文件读写操作1.www.chinasem.cn 读取文件2. 写

PyQt6中QMainWindow组件的使用详解

《PyQt6中QMainWindow组件的使用详解》QMainWindow是PyQt6中用于构建桌面应用程序的基础组件,本文主要介绍了PyQt6中QMainWindow组件的使用,具有一定的参考价值,... 目录1. QMainWindow 组php件概述2. 使用 QMainWindow3. QMainW

使用Python自动化生成PPT并结合LLM生成内容的代码解析

《使用Python自动化生成PPT并结合LLM生成内容的代码解析》PowerPoint是常用的文档工具,但手动设计和排版耗时耗力,本文将展示如何通过Python自动化提取PPT样式并生成新PPT,同时... 目录核心代码解析1. 提取 PPT 样式到 jsON关键步骤:代码片段:2. 应用 JSON 样式到

java变量内存中存储的使用方式

《java变量内存中存储的使用方式》:本文主要介绍java变量内存中存储的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍2、变量的定义3、 变量的类型4、 变量的作用域5、 内存中的存储方式总结1、介绍在 Java 中,变量是用于存储程序中数据

关于Mybatis和JDBC的使用及区别

《关于Mybatis和JDBC的使用及区别》:本文主要介绍关于Mybatis和JDBC的使用及区别,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、JDBC1.1、流程1.2、优缺点2、MyBATis2.1、执行流程2.2、使用2.3、实现方式1、XML配置文件