获取音频的专辑图与视频的缩略图截取

在音频和视频中,都会有缩略图的默认占位图,音频文件中封装了这些数据,所以直接从mp3等文件中读取出来就可以了。而视频,系统的播放器类是没有缩略图显示的,需要自己根据帧率截取一帧。

一、需要导入库

AVFoundation.framework
CoreMedia.framework
MediaPlayer.framework

二、获取音频的专辑图

//音乐的路径地址
- (UIImage *)musicImageWithMusicURL:(NSURL *)url {
       NSData *data = nil;
       // 初始化媒体文件
       AVURLAsset *mp3Asset = [AVURLAsset URLAssetWithURL:url options:nil];
       // 读取文件中的数据
       for (NSString *format in [mp3Asset availableMetadataFormats]) { 
             for (AVMetadataItem *metadataItem in [mp3Asset metadataForFormat:format]) {
                  //artwork这个key对应的value里面存的就是封面缩略图,其它key可以取出其它摘要信息,例如title - 标题
                  if ([metadataItem.commonKey isEqualToString:@"artwork"]) {
                       data = [(NSDictionary*)metadataItem.value objectForKey:@"data"];
                       break;
                  }
             }
       }
       if (!data) { 
            // 如果音乐没有图片,就返回默认图片
            return [UIImage imageNamed:@"default"];
       }
       return [UIImage imageWithData:data];
}

除了获取图片(data),还可以获取很多信息。如果有需要,可以NSLog以下这个集合,就知道了。

三、截取视频的某一帧缩略图

//视频的地址和截取哪一秒的缩略图
-(UIImage*)getVideoPreViewImageFromVideoPath:(NSString*)videoPath withAtTime:(float)atTime
{
    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:videoPath] options:nil];
    AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    gen.appliesPreferredTrackTransform = YES;
    gen.requestedTimeToleranceAfter = kCMTimeZero;
    gen.requestedTimeToleranceBefore = kCMTimeZero;
    CMTime time = CMTimeMakeWithSeconds(atTime, 600);
    NSError *error = nil;
    CMTime actualTime;
    CGImageRef image = [gen copyCGImageAtTime:time actualTime:&actualTime error:&error];
    UIImage *img = [[UIImage alloc] initWithCGImage:image];
    UIGraphicsBeginImageContext(CGSizeMake(JLXScreenSize.width, JLXScreenSize.height));
    [img drawInRect:CGRectMake(0, 0, JLXScreenSize.width, JLXScreenSize.height)];
    UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    CGImageRelease(image);
    return scaledImage;
}

四、CMTime简单介绍

通常开发者认为时间的呈现格式应该是浮点数据,我们一般使用NSTimeInterval,实际上它是简单的双精度double类型,只是typedef了一下,但是由于浮点型数据计算很容易导致精度的丢失,在一些要求高精度的应用场景显然不适合,于是苹果在Core Media框架中定义了CMTime数据类型作为时间的格式,类型定义如下:

typedef struct
{
     CMTimeValue    value;        
     CMTimeScale    timescale;    
     CMTimeFlags    flags;        
     CMTimeEpoch    epoch;        
} CMTime;

CMTime定义是一个C语言的结构体,CMTime是以分数的形式表示时间,value表示分子,timescale表示分母,flags是位掩码,表示时间的指定状态。

我们可以通过CMTimeShow函数打印CMTime的相关信息如:

CMTimeShow(t1);
CMTimeShow(t2);

4.1、CMTime计算

相加

CMTime t3 = CMTimeAdd(t1, t2);

相减

CMTime t4 = CMTimeSubtract(t3, t1);

我们也可以通过CMTimeGetSeconds函数获取时间的秒数。

4.2、CMTimeRange

CMTimeRange是一个表示时间范围的一个数据类型,定义如下:

typedef struct
{
    CMTime      start;        
    CMTime      duration;    
} CMTimeRange;

其中start表示时间的起点,duratin表示时间范围的持续时间。

一般使用CMTimeRangeMake和CMTimeRangeFromTimeToTime创建如:

 CMTimeRange timeRange1 = CMTimeRangeMake(t1, t2);
 CMTimeRange timeRange2 = CMTimeRangeFromTimeToTime(t4, t3);

4.3、CMTimeRange的交集和并集

有时候我们需要获取两个时间范围的交叉时间范围或者两个时间范围的总和时间范围。

交叉时间范围

CMTimeRange intersectionRange = CMTimeRangeGetIntersection(timeRange2, timeRange1);

总和时间范围

CMTimeRange unionRange = CMTimeRangeGetUnion(timeRange1, timeRange2);

五、CMTimeMake和CMTimeMakeWithSeconds介绍

CMTime是专门用于标识电影时间的结构体,通常用如下两个函数来创建CMTime

5.1、CMTimeMake

CMTime CMTimeMake (
   int64_t value,    //表示 当前视频播放到的第几桢数
   int32_t timescale //每秒的帧数
);

5.2、CMTimeMakeWithSeconds

CMTime CMTimeMakeWithSeconds(
     Float64 seconds,          //第几秒的截图,是当前视频播放到的帧数的具体时间
     int32_t preferredTimeScale //首选的时间尺度 "每秒的帧数"
 ); 
float minValue = [slider minimumValue];
float maxValue = [slider maximumValue];
float value = [slider value];
seconds  = duration * (value - minValue) / (maxValue - minValue);
preferredTimeScale =  1 *NSEC_PER_SEC; //如果只写 1 的话 有很大的误差,使用纳秒也是为了保证指定一个时间播放视频的精确度   

具体开发时候精确度设置的问题看需求

关键词解释:

  • NSEC:纳秒。
  • USEC:微妙。
  • SEC:秒
  • PER:每

所以:

1.NSEC_PER_SEC,每秒有多少纳秒。

2.USEC_PER_SEC,每秒有多少毫秒。(注意是指在纳秒的基础上)

3.NSEC_PER_USEC,每毫秒有多少纳秒。

1秒可以写成如下几种:

  1 * NSEC_PER_SEC

  1000 * USEC_PER_SEC

  USEC_PER_SEC * NSEC_PER_USEC

六、参考文章

Last modification:May 8th, 2017 at 11:22 am
如果看了这个文章可以让你少加会班,可以请我喝杯可乐
已打赏名单
微信公众号

Leave a Comment