手把手教你实现微信小视频iOS代码实现

2020-01-15 19:12:24王冬梅

转换是转换成功了,但是出现了新的问题,使用ImageIO生成gif图片时会导致内存暴涨,瞬间涨到100M以上,如果多个gif图同时生成的话一样会crash掉,为了解决这个问题需要用一个串行队列来进行gif图的生成   

1.2 视频转换为UIImages
主要是通过AVAssetReader、AVAssetTrack、AVAssetReaderTrackOutput 来进行转换 

 


//转成UIImage
- (void)convertVideoUIImagesWithURL:(NSURL *)url finishBlock:(void (^)(id images, NSTimeInterval duration))finishBlock
{
    AVAsset *asset = [AVAsset assetWithURL:url];
    NSError *error = nil;
    self.reader = [[AVAssetReader alloc] initWithAsset:asset error:&error];
    
    NSTimeInterval duration = CMTimeGetSeconds(asset.duration);
    __weak typeof(self)weakSelf = self;
    dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    dispatch_async(backgroundQueue, ^{
      __strong typeof(weakSelf) strongSelf = weakSelf;
      NSLog(@"");
      
      
      if (error) {
        NSLog(@"%@", [error localizedDescription]);
        
      }
      
      NSArray *videoTracks = [asset tracksWithMediaType:AVMediaTypeVideo];
      
      AVAssetTrack *videoTrack =[videoTracks firstObject];
      if (!videoTrack) {
        return ;
      }
      int m_pixelFormatType;
      //   视频播放时,
      m_pixelFormatType = kCVPixelFormatType_32BGRA;
      // 其他用途,如视频压缩
      //  m_pixelFormatType = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
      
      NSMutableDictionary *options = [NSMutableDictionary dictionary];
      [options setObject:@(m_pixelFormatType) forKey:(id)kCVPixelBufferPixelFormatTypeKey];
      AVAssetReaderTrackOutput *videoReaderOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:videoTrack outputSettings:options];
      
      if ([strongSelf.reader canAddOutput:videoReaderOutput]) {
        
        [strongSelf.reader addOutput:videoReaderOutput];
      }
      [strongSelf.reader startReading];
      
      
      NSMutableArray *images = [NSMutableArray array];
      // 要确保nominalFrameRate>0,之前出现过android拍的0帧视频
      while ([strongSelf.reader status] == AVAssetReaderStatusReading && videoTrack.nominalFrameRate > 0) {
         @autoreleasepool {
        // 读取 video sample
        CMSampleBufferRef videoBuffer = [videoReaderOutput copyNextSampleBuffer];
        
        if (!videoBuffer) {
          break;
        }
        
        [images addObject:[WKVideoConverter convertSampleBufferRefToUIImage:videoBuffer]];
        
        CFRelease(videoBuffer);
      }
      
      
     }
      if (finishBlock) {
        dispatch_async(dispatch_get_main_queue(), ^{
          finishBlock(images, duration);
        });
      }
    });
 

}

在这里有一个值得注意的问题,在视频转image的过程中,由于转换时间很短,在短时间内videoBuffer不能够及时得到释放,在多个视频同时转换时任然会出现内存问题,这个时候就需要用autoreleasepool来实现及时释放