iOS---视频播放、剪切、暂停
#import "TVViewController.h"
#import<AVFoundation/AVFoundation.h>
#import<MediaPlayer/MediaPlayer.h>
@interface TVViewController ()<UIScrollViewDelegate>
{
BOOLplayToEndTimeBool;//是否播放结束
}
@property(nonatomic,strong)AVPlayer* payerTV;
@property(nonatomic,strong)AVPlayerItem* playAtem;
@property(nonatomic,strong)UIView* loadProgressView;
@property(nonatomic,strong)UILabel* totalTimeLab;
@property(nonatomic,strong)AVPlayerLayer* playerLayer;
@property(nonatomic,strong)NSURL* url;
@property(nonatomic,strong)UILabel* currentTimeLab;
@property(nonatomic,strong)NSMutableArray* timeMutArr;
@property(nonatomic,strong)UIScrollView*editScrollView;
@property(nonatomic,strong)NSString* tempPath;
@end
@implementationTVViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initInterface];
[selfinitTV];
}
#pragma mark----视屏的初始化
- (void)initTV{
[self addPlayer];
[selfaddBut];
}
#pragma mark----添加播放器
- (void)addPlayer{
playToEndTimeBool = NO;//默认没有播放结束
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(PlayToEndTime) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
self.url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"tv" ofType:@"mp4"]];
self.playAtem = [AVPlayerItem playerItemWithURL:self.url];
//self.playAtem.asset
self.payerTV = [[AVPlayer alloc]initWithPlayerItem:_playAtem];
//创建播放器
self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.payerTV];
self.playerLayer.frame = CGRectMake(0, 160, [UIScreen mainScreen].bounds.size.width, 140);
[self.view.layer addSublayer:self.playerLayer];
// [self.payerTV seekToTime:CMTimeMakeWithSeconds(0, 1000)];//设置播放位置 1000位帧率
[self.payerTV seekToTime:CMTimeMake(0, 1)];
/*volume--表示当前播放器的音频音量;0.0表示“关闭所有音频”,1.0表示“以当前项的最大音量播放”。
iOS注意:不要使用此属性实现用于媒体播放的音量滑块。为此,使用MPVolumeView,它在外观上是可定制的,并提供用户期望的标准媒体播放行为。
这个属性在iOS中最有用的是控制AVPlayer相对于其他音频输出的音量,而不是最终用户的音量控制。*/
self.payerTV.volume=0.5;
UIProgressView* progressView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar];
progressView.frame = CGRectMake(0, 150, [UIScreen mainScreen].bounds.size.width, 20);
[self.viewaddSubview:progressView];
self.loadProgressView = [[UIView alloc]initWithFrame:CGRectMake(0, 145, 10, 10)];
[self.view addSubview:self.loadProgressView];
self.loadProgressView.backgroundColor = [UIColor yellowColor];
__weak typeof(self)WeakSelf = self;
//监听视频播放进度
[self.payerTV addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(1, NSEC_PER_SEC) queue:NULL usingBlock:^(CMTime time) {
__strongtypeof(WeakSelf) strongSelf = WeakSelf;
//进度 当前时间/总时间
CGFloat progress = CMTimeGetSeconds(strongSelf.payerTV.currentItem.currentTime) / CMTimeGetSeconds(strongSelf.payerTV.currentItem.duration);
progressView.progress= progress;
strongSelf.currentTimeLab.text = [NSString stringWithFormat:@"播放视频时长%f秒", CMTimeGetSeconds(strongSelf.payerTV.currentItem.currentTime)];
//CGSize size = strongSelf.playAtem.presentationSize;//获取视频的大小
if(progress ==1) {
//防止当进度为1时,loadProgressView在视图上消失
strongSelf.loadProgressView.frame=CGRectMake(progress*[UIScreenmainScreen].bounds.size.width-10,145,10,10);
}else{
strongSelf.loadProgressView.frame=CGRectMake(progress*[UIScreenmainScreen].bounds.size.width,145,10,10);
}
}];
//在进度条上面--添加手势--可以拖动控制播放的位置
UIPanGestureRecognizer* pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panGestureRecognizer:)];
[self.loadProgressView addGestureRecognizer:pan];
[self AVAssetImageGenerator];
}
#pragma mark---获取视频帧图像
-(void)AVAssetImageGenerator{
/*
AVAssetImageGenerator 提供独立于回放的资产的缩略图或预览图像的对象。
*/
self.editScrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 300, [UIScreen mainScreen].bounds.size.width, 80)];
[self.view addSubview:self.editScrollView];
self.editScrollView.delegate = self;
//读取解析视频帧
//初始化AVURLAsset对象
AVURLAsset* asset = [[AVURLAsset alloc]initWithURL:self.url options:nil];
//获取总视频的长度 = 总帧数 / 每秒的帧数
longsumTime = asset.duration.value/ asset.duration.timescale;
//创建AVAssetImageGenerator对象
AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc]initWithAsset:asset];
generator.maximumSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 80);
generator.appliesPreferredTrackTransform = YES;
generator.requestedTimeToleranceBefore = kCMTimeZero;
generator.requestedTimeToleranceAfter = kCMTimeZero;
// 添加需要帧数的时间集合
self.timeMutArr = [NSMutableArray array];
for(inti =0; i < sumTime; i++) {
CMTime time = CMTimeMake(i *asset.duration.timescale , asset.duration.timescale);
NSValue *value = [NSValue valueWithCMTime:time];
[self.timeMutArraddObject:value];
}
__blocklongcount =0;
[generatorgenerateCGImagesAsynchronouslyForTimes:self.timeMutArr completionHandler:^(CMTime requestedTime, CGImageRef img, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error){
if (result == AVAssetImageGeneratorSucceeded) {
NSLog(@"%ld",count);
dispatch_sync(dispatch_get_main_queue(), ^{
UIImageView*thumImgView = [[UIImageViewalloc]init];
thumImgView.image= [UIImageimageWithCGImage:img];
[self.editScrollViewaddSubview:thumImgView];
thumImgView.frame=CGRectMake(50+count*50,0,50,70);
self.editScrollView.contentSize=CGSizeMake(100+count*50,0);
});
count++;
}
if (result == AVAssetImageGeneratorFailed) {
NSLog(@"Failed with error: %@", [error localizedDescription]);
}
if (result == AVAssetImageGeneratorCancelled) {
NSLog(@"AVAssetImageGeneratorCancelled");
}
}];
[self.editScrollView setContentOffset:CGPointMake(50, 0)];
}
- (void)scrollViewDidEndDragging:(UIScrollView*)scrollView willDecelerate:(BOOL)decelerate{
NSLog(@"%f",scrollView.contentOffset.x);
NSLog(@"%f",scrollView.contentSize.width);
NSLog(@"%f",scrollView.contentSize.width);
CGFloatprogress = scrollView.contentOffset.x/scrollView.contentSize.width;
self.loadProgressView.frame = CGRectMake(progress*[UIScreen mainScreen].bounds.size.width, 145, 10, 10);
}
#pragma mark---视频裁剪
- (void)deleteTv{
self.tempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"tmpMov.mp4"];
[self deleteTempFile];//视频裁剪的时候要清理一下之前的视屏
AVAsset *asset = [AVAsset assetWithURL:self.url];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
initWithAsset:asset presetName:AVAssetExportPresetPassthrough];
NSURL *furl = [NSURL fileURLWithPath:self.tempPath];
exportSession.outputURL= furl;//
exportSession.outputFileType = AVFileTypeMPEG4;
NSInteger startTime = CMTimeGetSeconds(self.payerTV.currentItem.currentTime);//希望剪切的---开始时间点
NSInteger endTime = CMTimeGetSeconds(self.payerTV.currentItem.duration);//希望剪切的---结束时间点
CMTime start = CMTimeMakeWithSeconds(startTime, CMTimeGetSeconds(self.playAtem.duration));
CMTime duration = CMTimeMakeWithSeconds(endTime - startTime, CMTimeGetSeconds(self.payerTV.currentItem.duration));
CMTimeRangerange =CMTimeRangeMake(start, duration);
exportSession.timeRange= range;
[exportSessionexportAsynchronouslyWithCompletionHandler:^{
switch([exportSessionstatus]) {
case AVAssetExportSessionStatusFailed:
NSLog(@"Export failed: %@", [[exportSessionerror]localizedDescription]);
break;
case AVAssetExportSessionStatusCancelled:
NSLog(@"Export canceled");
break;
default:
NSLog(@"NONE");
NSURL*movieUrl = [NSURLfileURLWithPath:self.tempPath];
dispatch_sync(dispatch_get_main_queue(), ^{
UISaveVideoAtPathToSavedPhotosAlbum([movieUrlrelativePath],self,@selector(video:didFinishSavingWithError:contextInfo:),nil);
NSLog(@"编辑后的视频路径: %@",self.tempPath);
});
break;
}
}];
}
- (void)video:(NSString*)videoPath didFinishSavingWithError:(NSError*)error contextInfo:(void*)contextInfo {
if(error) {
NSLog(@"保存到相册失败");
}else{
NSLog(@"保存到相册成功");
}
}
-(void)addBut{
UIButton* playBut = [UIButton buttonWithType:UIButtonTypeCustom];
[self.viewaddSubview:playBut];
playBut.frame=CGRectMake(20,104,80,30);
[playButsetTitle:@"播放" forState:UIControlStateNormal];
[playButsetTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[playButaddTarget:self action:@selector(play) forControlEvents:UIControlEventTouchUpInside];
playBut.titleLabel.font = [UIFont systemFontOfSize:16.0f];
UIButton* suspendedBut = [UIButton buttonWithType:UIButtonTypeCustom];
[self.viewaddSubview:suspendedBut];
suspendedBut.frame=CGRectMake(120,104,80,30);
[suspendedButsetTitle:@"暂停" forState:UIControlStateNormal];
[suspendedButsetTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[suspendedButaddTarget:self action:@selector(suspended) forControlEvents:UIControlEventTouchUpInside];
suspendedBut.titleLabel.font = [UIFont systemFontOfSize:16.0f];
UIButton* forwardBut = [UIButton buttonWithType:UIButtonTypeCustom];
[self.viewaddSubview:forwardBut];
forwardBut.frame=CGRectMake(120,64,80,30);
[forwardButsetTitle:@"前进" forState:UIControlStateNormal];
[forwardButsetTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[forwardButaddTarget:self action:@selector(forward) forControlEvents:UIControlEventTouchUpInside];
forwardBut.titleLabel.font = [UIFont systemFontOfSize:16.0f];
UIButton* retBut = [UIButton buttonWithType:UIButtonTypeCustom];
[self.viewaddSubview:retBut];
retBut.frame=CGRectMake(220,104,80,30);
[retButsetTitle:@"重播" forState:UIControlStateNormal];
[retButsetTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[retButaddTarget:self action:@selector(ret) forControlEvents:UIControlEventTouchUpInside];
retBut.titleLabel.font = [UIFont systemFontOfSize:16.0f];
UIButton* backBut = [UIButton buttonWithType:UIButtonTypeCustom];
[self.viewaddSubview:backBut];
backBut.frame=CGRectMake(220,64,80,30);
[backButsetTitle:@"后退" forState:UIControlStateNormal];
[backButsetTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[backButaddTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
backBut.titleLabel.font = [UIFont systemFontOfSize:16.0f];
self.totalTimeLab = [[UILabel alloc]initWithFrame:CGRectMake(10, 190, 280, 30)];
[self.view addSubview:self.totalTimeLab];
self.totalTimeLab.textColor = [UIColor blackColor];
self.totalTimeLab.font = [UIFont systemFontOfSize:14.0f];
self.currentTimeLab = [[UILabel alloc]initWithFrame:CGRectMake(10, 160, 280, 30)];
[self.view addSubview:self.currentTimeLab];
self.currentTimeLab.textColor = [UIColor blackColor];
self.currentTimeLab.font = [UIFont systemFontOfSize:14.0f];
}
#pragma mark---
- (void)panGestureRecognizer:(UIPanGestureRecognizer*)pan{
//获取手势的位置
CGPointposition =[pantranslationInView:self.loadProgressView];
//通过stransform 进行平移交换
self.loadProgressView.transform = CGAffineTransformTranslate(self.loadProgressView.transform, position.x, position.y);
//将增量置为零
[pansetTranslation:CGPointZero inView:self.loadProgressView];
CGFloat progress = self.loadProgressView.frame.origin.x/[UIScreen mainScreen].bounds.size.width;
[self.payerTV seekToTime:CMTimeMakeWithSeconds(CMTimeGetSeconds(self.payerTV.currentItem.duration)*progress, 1000)];//设置播放位置 1000位帧率
[self.payerTVplay];
}
#pragma mark----重播
-(void)ret{
// [self.payerTV seekToTime:CMTimeMakeWithSeconds(0, 1000)];//设置播放位置 1000位帧率
// [self.payerTV play];
//播放剪切之后的视屏
self.url= [NSURL fileURLWithPath:self.tempPath];
self.playAtem = [AVPlayerItem playerItemWithURL:self.url];
self.payerTV = [[AVPlayer alloc]initWithPlayerItem:_playAtem];
//创建播放器
self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.payerTV];
self.playerLayer.frame = CGRectMake(0, 160, [UIScreen mainScreen].bounds.size.width, 140);
[self.view.layer addSublayer:self.playerLayer];
[self.payerTV seekToTime:CMTimeMakeWithSeconds(0, 1000)];//设置播放位置 1000位帧率
[self.payerTVplay];
}
#pragma mark--视屏后退
-(void)back{
// CGFloat currentTime= CMTimeGetSeconds(self.payerTV.currentItem.currentTime);
// if (currentTime>2) {
// [self.payerTV seekToTime:CMTimeMakeWithSeconds(currentTime-2, 1000)];//设置播放位置 1000位帧率
// }
[selfdeleteTv];
}
#pragma mark--视屏前进
-(void)forward{
CGFloat currentTime= CMTimeGetSeconds(self.payerTV.currentItem.currentTime);
CGFloat totalTime = CMTimeGetSeconds(self.payerTV.currentItem.duration);
if((totalTime-currentTime)>2) {
[self.payerTV seekToTime:CMTimeMakeWithSeconds(CMTimeGetSeconds(self.payerTV.currentItem.currentTime)+2, 1000)];//设置播放位置 1000位帧率
}
}
#pragma mark----播放结束
-(void)PlayToEndTime{
playToEndTimeBool = YES;//播放结束
}
#pragma mark---播放
-(void)play{
// CMTime time = _payerTV.currentItem.duration;//当前播放对象的持续时间总长
// CMTime currentTime =_payerTV.currentTime;//当前播放对象的播放位置
// if (time.timescale == currentTime.timescale) {//当播放结束的时候,重新从头播放
// [self.payerTV seekToTime:CMTimeMakeWithSeconds(0, 1000)];//设置播放位置 1000位帧率
// }
if (playToEndTimeBool) {
playToEndTimeBool = NO;
[self.payerTV seekToTime:CMTimeMakeWithSeconds(0, 1000)];//设置播放位置 1000位帧率
}
[self.payerTVplay];
self.totalTimeLab.text= [NSStringstringWithFormat:@"播放视频总时长%ff秒",CMTimeGetSeconds(self.payerTV.currentItem.duration)];
}
- (void)deleteTempFile{
NSURL *url = [NSURL fileURLWithPath:self.tempPath];
NSFileManager *fm = [NSFileManager defaultManager];
BOOLexist = [fmfileExistsAtPath:url.path];
NSError*err;
if(exist) {
[fmremoveItemAtURL:urlerror:&err];
}else{
}
}
#pragma mark---暂停
-(void)suspended{
[self.payerTVpause];
}
- (void)dealloc{
self.payerTV =nil;
}
#pragma mark--界面初始化
- (void)initInterface{
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"视屏的播放与截取";
}
@end