带你用AVPlayer实现音频和视频播放
项目概述
- 以下项目是基于AVPlayer的实际运用,实现音频播放、横竖屏视频切换播放、类似抖音的竖屏全屏播放效果。
项目地址:AVPlayerAudioVideo
如果文章和项目对你有帮助,还请给个Star️,你的Star️是我持续输出的动力,谢谢啦
1.音频播放器效果:

2.竖屏和横屏的切换效果:
3.类似抖音竖屏全屏的效果:
竖屏全屏用UICollectionView实现,只创建了三个UICollectionViewCell视图实例。无论有多少视频需要播放,都是复用这三个UICollectionViewCell视图实例,有效控制内存大小,避免内存加载过大、内存爆满的情况。
UICollectionViewCell复用时有一个难点,就是记录视频当前已播放的位置,一开始用CMTime来保存发现不行,然后用CMTimeValue和CMTimeScale分别记录也是存在各种问题,后来使用AVPlayerItem来保存已播放位置才彻底解决。
遇到的问题
- 播放时,扬声器没有声音,插上耳机才有声音。
原因是app扬声器默认跟随系统声音模式,而手机调了静音模式,因此扬声器跟随静音模式,没有声音。
解决方式:设置Category,让扬声器不跟随系统声音模式。
//必须设置,否则扬声器默认跟随系统声音模式
//AVAudioSessionCategoryPlayAndRecord模式能播放能录音,该模式下声音默认出口是听筒(戴耳机才有声音),切换到扬声器通过以下方式
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
- 当反复快速移动滑块时,滑块会出现跳跃的现象。
这是由于移动滑块时,会调用seekToTime:,该方法用于搜索并播放指定视频帧,执行时需要一点时间,不会立马搜索并播放到指定视频帧,此时addPeriodicTimeObserverForInterval:queue:usingBlock:回调会设置滑块的位置,出现手指已让滑块移动到某一位置,突然有一瞬间滑块回到之前的位置,然后立马又回到手指停留的位置。
解决方式:用seekToTime:toleranceBefore:toleranceAfter:completionHandler:代替seekToTime:,搜索并播放到指定视频帧会有completionHandler的回调,获得该回调后再设置滑块的位置。具体处理细节详见项目。
什么是AVPlayer
- AVPlayer存在于AVFoundation框架中,它是一个视频播放器,用来播放视频,但也可以用来播放音乐,播放音乐时不需要实现界面。换句话说,只要掌握了视频播放,音频播放自然就掌握了。
- AVPlayerItem:和媒体资源存在对应关系,管理媒体资源的信息和状态。它的初始化需要URL或AVAsset。
- AVPlayer:播放器,控制资源的播放和暂停,AVPlayerItem是它的属性,它的初始化需要URL或AVPlayerItem。
+ (instancetype)playerWithURL:(NSURL *)URL;
+ (instancetype)playerWithPlayerItem:(nullable AVPlayerItem *)item;
- AVPlayerLayer:播放器图层,用于展示视频内容,AVPlayer是它的属性,它的初始化需要AVPlayer。如果是播放音频,则不需要创建AVPlayerLayer。
+ (AVPlayerLayer *)playerLayerWithPlayer:(nullable AVPlayer *)player
- AVPlayerItem、AVPlayer、AVPlayerLayer三者关系,做个类比:
AVPlayerItem是光盘,AVPlayer是dvd影碟机,AVPlayerLayer是电视机屏幕。
视频播放功能实现
1.通过网络链接播放视频资源
//url有中文时需要URL编码
NSURL *url = [NSURL URLWithString:[self.str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:url];
AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
playerLayer.frame = CGRectMake(0, 50, self.view.frame.size.width, 200);
[self.view.layer addSublayer:playerLayer];
2.常用操作
- 播放和暂停
[player play];
[player pause];
- 替换播放资源
[player replaceCurrentItemWithPlayerItem:videoItem];
3.监听播放进度
- 使用
addPeriodicTimeObserverForInterval:queue:usingBlock:监听播放器的进度,常用于指示播放进度,获取播放时长等信息。
1)Interval参数表示回调的间隔时间,block是每到一个间隔时间执行一次。
例如Interval传CMTimeMake(1,10),1表示当前有1帧,10表示每秒10帧,1/10=0.1,即player在播放中时每0.1秒执行一次block,包括开始播放、暂停播放也会回调。
2)方法返回一个观察者对象,当不再播放时,要移除该观察者。
添加观察者
self.timeObserve = [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 10) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
float current = CMTimeGetSeconds(time);
float total = CMTimeGetSeconds(weakSelf.player.currentItem.duration);
weakSelf.playTime = [NSString stringWithFormat:@"%.f",current];
weakSelf.playDuration = [NSString stringWithFormat:@"%.2f",total];
if (weakSelf.slider.isTracking == NO) {
weakSelf.slider.value = current / total;
}
}];
移除观察者
if (self.timeObserve) {
[self.player removeTimeObserver:self.timeObserve];
}
4.移动滑块播放指定时刻的视频帧
- 使用
seekToTime:或seekToTime:completionHandler:或seekToTime:toleranceBefore:toleranceAfter:completionHandler:播放指定时刻的视频内容。
精确搜索某一时刻的视频帧可能会导致额外的解码延迟,seekToTime:默认不是精确搜索,而是有一个小范围的误差。
seekToTime:toleranceBefore:toleranceAfter:completionHandler:的搜索的范围是[time-toleranceBefore, time+toleranceAfter],当toleranceBefore和toleranceAfter设置为kCMTimePositiveInfinity时,执行效果等同于seekToTime:completionHandler:
[self.player seekToTime:goalTime toleranceBefore:kCMTimePositiveInfinity toleranceAfter:kCMTimePositiveInfinity completionHandler:^(BOOL finished) {
}];
带你用AVPlayer实现音频和视频播放的更多相关文章
- iOS开发——高级篇——远程音频、视频播放
一.远程音频播放(<AVFoundation/AVFoundation.h>) #import <AVFoundation/AVFoundation.h> /** 播放器 */ ...
- iOS AvPlayer AvAudioPlayer音频的后台播放问题
iOS 4开始引入的multitask,我们可以实现像ipod程序那样在后台播放音频了.如果音频操作是用苹果官方的AVFoundation.framework实现,像用AvAudioPlayer,Av ...
- 那些H5用到的技术(2)——音频和视频播放
前言audio标签Web Audio API自动播放的问题背景音乐的实现立即播放的问题SoundJSvideo标签播放样式的问题格式的问题总结 前言 正常情况,除了非常简陋的小功能H5,音乐播放是必不 ...
- 一种高灵敏度自带DSP降噪算法的音频采集解决方案
背景调研 随着AI渗透到各行各业,人们对语音的需求也越来越大,最近一两年,各种AI音频设备如雨后春笋般冒出.各种智能AI设备的推出,意味者市场对低成本的音频采集设备越来越多.针对这种情况,我们开发 ...
- HTML5音频,视频播放
1.此方法可支持多种浏览器 <audio controls="controls"> <source src="1.mp3" ></ ...
- HTML5音频视频-视频播放
- iOS: ios视频播放(MPMediaPlayerController,AVPlayer,AVPlayerViewcontroller、ffmpeg-AVPlayer)
介绍: 和音频播放一样,ios也提供个很多的API.如mediaPlayer.framework下的MPMediaPlayerController.AVFounditon.framework下的AVP ...
- C# Winform 中如何实现音乐播放和视频播放
C# Winform 中如何实现音乐播放和视频播放 namespace WindowsFormsApplication1 { public partial class Form2 : Form { ...
- 音频 API 一览
iOS 和 OS X 平台都有一系列操作音频的 API,其中涵盖了从低到高的全部层级.随着时间的推移.平台的增长以及改变,不同 API 的数量可以说有着非常巨大的变化.本文对当前可以使用的 API 以 ...
随机推荐
- k8s核心资源之Pod概念&入门使用讲解(三)
目录 1. k8s核心资源之Pod 1.1 什么是Pod? 1.2 Pod如何管理多个容器? 1.3 Pod网络 1.4 Pod存储 1.5 Pod工作方式 1.5.1 自主式Pod 1.5.2 控制 ...
- Excel中怎么快速选中区域
连续的表格选定 一张表格中会有不同的部分,若想选择某一个区域的数据的时候我们可以使用快捷键Ctrl+A,这是需要先选中第一个单元格,接着点击Ctrl+A即可选中连续的单元格. 汇总后需要汇 ...
- IP 地址无效化
给你一个有效的 IPv4 地址 address,返回这个 IP 地址的无效化版本. 所谓无效化 IP 地址,其实就是用 "[.]" 代替了每个 ".". 示例 ...
- 如何画UML,几种简单的模型分析
如何画UML 前言 UML 类 类的关系 1.依赖关系 2.继承关系 3.实现关系 4.关联关系 5.聚合关系 6.组合关系 总结 参考 如何画UML 前言 最近在学习设计模式,其中不免涉及到 UML ...
- PHP中的PDO操作学习(三)预处理类及绑定数据
要说 PDO 中最强大的功能,除了为不同的数据库提供了统一的接口之外,更重要的就是它的预处理能力,也就是 PDOStatement 所提供的功能.因为它的存在,才让我们可以安心地去使用而不用操心 SQ ...
- spring入门1-IOC和DI
1.概述 1.1.简介 Spring是分层的 Java SE/EE应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control:反转控制)和 AOP(Aspect Or ...
- promise对象总结
一.Promise是异步编程的一种解决方案,它是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果.从语法上说,Promise 是一个对象,从它可以获取异步操作的消息.Promis ...
- Dapr + .NET Core实战(十一)单机Dapr集群
如何单机部署Dapr集群 第十篇讲过了K8S集群下如何使用Dapr运行程序,但是很多人一直在问如何单机下进行Dapr的负载,这节课我们来聊聊如何单机进行Dapr的负载. 首先要说的是单机下,通过 da ...
- Serverless:这真的是未来吗?(一)
原文 | https://www.pulumi.com/blog/is_serverless_the_future_part_1/ 作者 | Lee Briggs & Piers Karsen ...
- Java秘诀!零基础怎样快速学习Java?
对于零基础想学Java的朋友,其实一开始最应该做的就是定好学习目标和端正学习态度,切记不要三天打鱼两天晒网! 首先你是零基础,现在急需把Java学好,在保证学习质量的同时,用最短的时间学好Java应该 ...